Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Problem using QTableView and QAbstractTableModel with QGridLayout
QtWS25 Last Chance

Problem using QTableView and QAbstractTableModel with QGridLayout

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 5 Posters 261 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    james b-s
    wrote on last edited by
    #1

    I have a table where I needto add a pre-existing custom widget which derives from QObject and not QWidget.

    When testing, I created the table using QTableView and QAbstractTableModel and stuck in QStrings and everything worked as expected. The widget that I want to use requires that it be inside of a grid (don't ask). For testing, I modified my table to have a QString inside of a grid inside of directly in the table. Each table cell contains a grid with one cell which contains the QString. When I set the parent of the grid to be the table, and create an item, the table gets a row, but the qstring ends up in the middle of the table. When I don't set the parent of the grid, the qstring isn't displayed at all. In both cases, a blank cell is created in the table. The table has only one column.

    I figure that the parentage of the grid is probably the problem, but there doesn't seem to be a QWidget to which to set the parent.

    Any help/suggestions would be appreciated.

      QGridLayout* const pGridLayout = new QGridLayout(this);
      pGridLayout->setColumnMinimumWidth(0, 75);
      pGridLayout->addWidget(new QLabel("test"), 0, 0);
      dynamic_cast<MyModel*>(model())->AddRow(pGridLayout);
    
    
    void MyModel::AddRow(QGridLayout* cellValue)
    {
      const int row = m_data.count();
    
      beginInsertRows(QModelIndex(), row, row);
    
      m_data.push_back(cellValue);
      insertRows(row, 1);
    
      QModelIndex newIndex = index(row, 0);
      setData(newIndex, QVariant::fromValue(cellValue), Qt::EditRole);
    
      endInsertRows();
    }
    
    bool MyModel::setData(const QModelIndex & index, const QVariant & value, int role)
    {
      if (!index.isValid()) {
        return false;
      }
    
      if (role == Qt::EditRole) {
        const int row = index.row();
        const int column = index.column();
    
        auto ptr = static_cast<QGridLayout*>(value.value<void*>());
    
        m_data[row] = ptr;
        emit dataChanged(index, index);
        return true;
      }
    
      return false;
    }
    
    QVariant MyModel::data(const QModelIndex &index, int role) const
    {
      if (!index.isValid()) {
        return false;
      }
    
      if (role == Qt::DisplayRole || role == Qt::EditRole) {
        const int row = index.row();
        const int column = index.column();
    
        auto ptr = m_data.at(row);
        QVariant variant = QVariant::fromValue(static_cast<void*>(m_data.at(row)));
        return variant;
      }
    
      return QVariant();
    }
    
    Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
    {
      return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsEditable | QAbstractTableModel::flags(index);
    }
    
    Pl45m4P 1 Reply Last reply
    0
    • J james b-s

      I have a table where I needto add a pre-existing custom widget which derives from QObject and not QWidget.

      When testing, I created the table using QTableView and QAbstractTableModel and stuck in QStrings and everything worked as expected. The widget that I want to use requires that it be inside of a grid (don't ask). For testing, I modified my table to have a QString inside of a grid inside of directly in the table. Each table cell contains a grid with one cell which contains the QString. When I set the parent of the grid to be the table, and create an item, the table gets a row, but the qstring ends up in the middle of the table. When I don't set the parent of the grid, the qstring isn't displayed at all. In both cases, a blank cell is created in the table. The table has only one column.

      I figure that the parentage of the grid is probably the problem, but there doesn't seem to be a QWidget to which to set the parent.

      Any help/suggestions would be appreciated.

        QGridLayout* const pGridLayout = new QGridLayout(this);
        pGridLayout->setColumnMinimumWidth(0, 75);
        pGridLayout->addWidget(new QLabel("test"), 0, 0);
        dynamic_cast<MyModel*>(model())->AddRow(pGridLayout);
      
      
      void MyModel::AddRow(QGridLayout* cellValue)
      {
        const int row = m_data.count();
      
        beginInsertRows(QModelIndex(), row, row);
      
        m_data.push_back(cellValue);
        insertRows(row, 1);
      
        QModelIndex newIndex = index(row, 0);
        setData(newIndex, QVariant::fromValue(cellValue), Qt::EditRole);
      
        endInsertRows();
      }
      
      bool MyModel::setData(const QModelIndex & index, const QVariant & value, int role)
      {
        if (!index.isValid()) {
          return false;
        }
      
        if (role == Qt::EditRole) {
          const int row = index.row();
          const int column = index.column();
      
          auto ptr = static_cast<QGridLayout*>(value.value<void*>());
      
          m_data[row] = ptr;
          emit dataChanged(index, index);
          return true;
        }
      
        return false;
      }
      
      QVariant MyModel::data(const QModelIndex &index, int role) const
      {
        if (!index.isValid()) {
          return false;
        }
      
        if (role == Qt::DisplayRole || role == Qt::EditRole) {
          const int row = index.row();
          const int column = index.column();
      
          auto ptr = m_data.at(row);
          QVariant variant = QVariant::fromValue(static_cast<void*>(m_data.at(row)));
          return variant;
        }
      
        return QVariant();
      }
      
      Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
      {
        return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsEditable | QAbstractTableModel::flags(index);
      }
      
      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by Pl45m4
      #2

      @james-b-s said in Problem using QTableView and QAbstractTableModel with QGridLayout:

      I figure that the parentage of the grid is probably the problem, but there doesn't seem to be a QWidget to which to set the parent.

      The whole design seems to be problematic to be honest...

      Adding a layout as data to a model is super weird (and bad design, probably).

      void MyModel::AddRow(QGridLayout* cellValue)
      {
        const int row = m_data.count();
      
        beginInsertRows(QModelIndex(), row, row);
      
        m_data.push_back(cellValue);
        insertRows(row, 1);
      
        QModelIndex newIndex = index(row, 0);
        setData(newIndex, QVariant::fromValue(cellValue), Qt::EditRole);
        // ...
        // ...
      

      What do you expect from converting a QGridLayout* to QVariant here
      QVariant::fromValue(cellValue)
      where cellValue is your layout?
      What is your actual goal?
      A layout handles the graphical representation of widgets... this shouldn't be involved in any data structure or model/view.

      Why not use a list or other container instead if you really want to go this way?
      But better separate the graphical QGridLayout from your underlying data.
      From your description above, it is also difficult to get what you actually trying to do.

      To be accurate:

      I have a table where I need to add a pre-existing custom widget which derives from QObject and not QWidget.

      Something that doesn't inherit from QWidget is not a widget :)
      Most/All QObject classes don't have any visual representation...
      You cannot see a QGraphicsLayout (or a QTimer for instance)... what you see is the sum of its content widgets following its logic (size, position/alignment, style, etc)

      the qstring ends up in the middle of the table.

      A QLabel displaying your text of type QString ends up on your screen, not the QString.
      Yes, you are right, this is because you somewhere set the viewport widget or whole QTableView as parent of your QLabels. This causes them to be in their parent's coordinate system. So they appear on the screen.
      This has also nothing to do with proper MV(C) programming.
      The model holds and manages the data (and only the data), whereas the view displays data of such type in your desired way.


      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      1 Reply Last reply
      3
      • J Offline
        J Offline
        james b-s
        wrote on last edited by
        #3

        The problem is that I have pre-exiting widget (derived from QObject) that I need to display in a table. The widget is written to require that it be in a QGridLayout.

        I am converting my grid layout into a QVariant (and back) because setData() and data() requires a QVariant.

        Pl45m4P JonBJ 2 Replies Last reply
        0
        • J james b-s

          The problem is that I have pre-exiting widget (derived from QObject) that I need to display in a table. The widget is written to require that it be in a QGridLayout.

          I am converting my grid layout into a QVariant (and back) because setData() and data() requires a QVariant.

          Pl45m4P Offline
          Pl45m4P Offline
          Pl45m4
          wrote on last edited by Pl45m4
          #4

          @james-b-s said in Problem using QTableView and QAbstractTableModel with QGridLayout:

          I have pre-exiting widget (derived from QObject) that I need to display in a table. The widget is written to require that it be in a QGridLayout.

          I've read that but that should have nothing to do with what you do in your model/view...
          Your "widget" (QObject) must consist of some data... so you put the data in your model and not the "widget", layout or whatever.
          Even if your widget requires a QBananaLayout (FWIW, yes, I made that up) ... it should not matter.... Model/View is a "translation" of raw "data" to some visual representation, so that we humans are capable of interpreting (and editing) data better and faster. Having a widget in some layout also based off this data is another thing.

          So the better/cleaner way is that you put the actual data (QList<QString> / QStringList maybe) in your model and not a layout class managing the graphical representation of it.

          Not sure if this really suits your case, but have a look at QDataWidgetMapper.

          • https://doc.qt.io/qt-6/qdatawidgetmapper.html

          It helps to map/assign data from a model straight to your widgets (QWidget!!) on your screen.


          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          1 Reply Last reply
          2
          • GaoboG Offline
            GaoboG Offline
            Gaobo
            wrote on last edited by
            #5

            Maybe a picture that shows what you want would be better.🌚🌚And a widget that doesn't inherit from QWidget sounds quite odd.

            1 Reply Last reply
            0
            • J james b-s

              The problem is that I have pre-exiting widget (derived from QObject) that I need to display in a table. The widget is written to require that it be in a QGridLayout.

              I am converting my grid layout into a QVariant (and back) because setData() and data() requires a QVariant.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #6

              @james-b-s said in Problem using QTableView and QAbstractTableModel with QGridLayout:

              The problem is that I have pre-exiting widget (derived from QObject) that I need to display in a table.

              As others have said: QObjects have no visual representation and "widgets" must derive from QWidget. If it's really not derived from that and only from QObject it's not a widget.

              The widget is written to require that it be in a QGridLayout.

              Qt layouts only accept as widgets to place on them objects which are QWidgets. So either it's that or you can't place it on a layout, so I don't understand how that can be a requirement or even a possibility. Unless it's weird and the author means you have to put it inside a QWidget first before then putting it on a layout.

              I am converting my grid layout into a QVariant (and back) because setData() and data() requires a QVariant

              Do not attempt to save/serialize a layout, or a widget, as data. They are not suited to that. If required save data as some kind of structure which would allow the object to be recreated if required.

              1 Reply Last reply
              2
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                Hi,

                Beside what my fellows correctly pointed (nothing widgets related should be put into a model and QWidget is the base class for anything widget), you seem to need a custom vizualization of your data. If that is indeed the case, then the correct class to check is QStyledItemDelegate.

                That said, you still haven't really explained your goal and what exactly you want to show.

                It really seems that you want your text to be shown in the center of a cell which really does not require all the complexity you are describing.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                1

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved