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. QTableWidget or QTableView
Forum Updated to NodeBB v4.3 + New Features

QTableWidget or QTableView

Scheduled Pinned Locked Moved General and Desktop
36 Posts 6 Posters 17.4k Views 1 Watching
  • 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.
  • D Offline
    D Offline
    DaFranzl
    wrote on last edited by
    #1

    Hi,

    I just want to know what would be better for my use and how to use. I got a QList<PLAYER*> and wanted to show them in a table. But i dont know if i should us a QTableView or QTableWidget?

    1 Reply Last reply
    0
    • JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote on last edited by
      #2

      EDIT: Please disregard my message, in favour of the ones below. My advice was based on my personal approach, but I realized I can't compare properly since I haven't used QTableView myself.

      -QTableWidget is a special version of QTableView, that is much simpler to use. If this is your first time using the Model/View framework, I recommend QTableWidget.-

      -Note that you can't pass the QList straight into the QTableWidget -- you'll need to transfer the data into QTableWidgetItem first. (One reason that QTableView is more complicated is that you must write your own version of QTableWidgetItem)-

      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

      1 Reply Last reply
      0
      • A Offline
        A Offline
        andre
        wrote on last edited by
        #3

        I disagree with JKSH. I think that using QTableWidget is almost always the wrong thing to do, and it should not have made it to Qt in the first place. Its API is horribly confused about the widget, model and view properties, and it promotes using model/view API outside of the model/view context.

        You do not need to "write your own version of QTableWidgetItem", because you already have it: your PLAYER items. I would advice you to go the *View + model route. It is much more flexible, and that will benefit you in the future. It also creates a cleaner separation between your data and your UI.

        If you go the *model way, a quick way to get up to speed is to use QStandardItemModel. It has a similar API to QTableWidget, but it will allow you to change your implementation later to a custom QAbstractItemModel (or probabaly, a QAbstractTableModel) when you feel up to that.

        1 Reply Last reply
        0
        • K Offline
          K Offline
          KA51O
          wrote on last edited by
          #4

          Also there's a quite extensive and helpful "guide to model-view programming":https://qt-project.org/doc/qt-4.8/model-view-programming.html in the wiki, which covers every aspect and problem you might encounter.

          1 Reply Last reply
          0
          • D Offline
            D Offline
            DaFranzl
            wrote on last edited by
            #5

            Ok, thanks so far. My players are stored in a class called playerholder, which has a QHash<playerid, PLAYER*> and its functions are:

            -createPlayer(Player *player)
            -updatePlayer(Player *player)
            -deletePlayer(Player *player)
            -findPlayer(int id)
            -loadPlayers()

            They are connected to a database. Yesterday i tried to display the data by subclassing QAbstractTableModel. But my problem is i dont understand where i set which data is displayed and how the headers are named.

            1 Reply Last reply
            0
            • K Offline
              K Offline
              KA51O
              wrote on last edited by
              #6

              [quote author="DaFranzl" date="1344335647"]
              Yesterday i tried to display the data by subclassing QAbstractTableModel. But my problem is i dont understand where i set which data is displayed and how the headers are named.[/quote]
              You need to implement the "data(..)":http://qt-project.org/doc/qt-4.8/qabstractitemmodel.html#data and "headerData(..)":http://qt-project.org/doc/qt-4.8/qabstractitemmodel.html#headerData functions for this. To specify which data is displayed and which is used for other purposes have a look at the "item-roles":https://qt-project.org/doc/qt-4.8/model-view-programming.html#item-roles resp. "Qt::ItemDataRole":https://qt-project.org/doc/qt-4.8/qt.html#ItemDataRole-enum

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on last edited by
                #7

                Ok, great. It seems that you already have a kind of a data store object in your application. That's a good start! Instead of adding all kinds of needless API to this store by making it subclass QAbstractTableModel, I'd suggest you give it a single member function QAbstractItemModel model(). Internally, you make this method return your own implementation of a model-representation of your data. It may be derived from QAbstractTableModel or any other convenient class, but QAbstractTableModel is probably a good choice.

                If you make your implementation a (private) embedded class in your store class playerholder, it can get access to all the internals of playerholder without you having to expose these to the outside world. In your implemenatations of the functions that modify the contents of your playerholder (add, create, modify), make sure that you will allow the model to call the needed functions to reflect those changes in the model and the attached view(s). There is a list of begin... and end... protected methods available in QAbstractItemModel for this, while changes to items in the model can be signalled by directly emitting the dataChanged() signal from the model implementation.

                For your model implementation, you will at minimum need to reimplement these methods:

                • rowCount()
                • columnCount()
                • data(). The most important data role is Qt::DisplayRole.
                • headerData() if you want to have real headers

                Additionally, you might end up reimplementing flags() as well. If your model is user-editable, you'll also going to have to implement setData().

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  DaFranzl
                  wrote on last edited by
                  #8

                  Ok, this seems very complicated but i try to work it out, btw sorry for all these questions. Sofar my class PLAYERHOLDER looks like this.

                  @class PLAYERHOLDER
                  {
                  public:
                  static PLAYERHOLDER* getInstance();
                  void createPlayer(PLAYER player);
                  void updatePlayer(int id);
                  void deletePlayer(int id);
                  PLAYER
                  findPlayer(int id);
                  QList<PLAYER*> getPlayers();
                  void loadPlayers(int teamid);

                  private:
                  PLAYERHOLDER();
                  static PLAYERHOLDER thePlayerholder;
                  QHash<int, PLAYER
                  > playerlist;
                  DATASOURCE *datasource;

                  class CONTACTMODEL : public QAbstractTableModel
                  {
                      Q_OBJECT
                  public:
                      int rowCount( const QModelIndex &parent ) const;
                      int columnCount( const QModelIndex &parent ) const;
                      QVariant data( const QModelIndex &index, int role ) const;
                      QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
                  };
                  

                  };@

                  Is there any function missing?

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andre
                    wrote on last edited by
                    #9

                    Yeah, you're not actually exposing the model, so you'd need to add this to the public interface:
                    @
                    QAbstractItemModel* model() const;
                    @

                    Your class probably will need a private member to keep track of the model:
                    @
                    mutable CONTACTMODEL* m_model;
                    @

                    The CONTACTMODEL also needs a constructor, and needs access to PLAYERHOLDER itself, so you'd need to add to CONTACTMODEL:
                    @
                    public:
                    explicit CONTACTMODEL(PLAYERHOLDER* holder);
                    private:
                    PLAYERHOLDER* m_playerHolder;
                    @

                    For your implementation of createPlayer, updatePlayer and deletePlayer, it might be needed to expose some methods on CONTACTMODEL to PLAYERHOLDER, so it can notify the model (and attached views) of (impending) changes.

                    1 Reply Last reply
                    0
                    • D Offline
                      D Offline
                      DaFranzl
                      wrote on last edited by
                      #10

                      Ok, I have implemented the functions as far as I can. Are you sure u meant
                      @QAbstractItemModel* model() const;@
                      and not
                      @QAbstractTableModel* model() const;@
                      ?

                      If I am right with my guess is this the right implementation?

                      @QAbstractTableModel* PLAYERHOLDER::model() const
                      {
                      return new CONTACTMODEL(this);
                      }@

                      After running the Code I recieve many errors with this line.

                      @mutable CONTACTMODEL *m_model;@

                      Missing type specifier - int assumed. Note: 'default-int' isn't supported by C++ and also
                      Syntaxerror: Missing ; infront of *

                      (The errors are translated from German, they can vary a bit.

                      Also i dont know how to realise the data function, it looks like this at the moment:
                      @QVariant PLAYERHOLDER::CONTACTMODEL::data(const QModelIndex &index, int role) const
                      {
                      if (!index.isValid())
                      return QVariant();

                      if (index.row() >= m_playerHolder->playerlist.size())
                          return QVariant();
                      
                      if (role == Qt::DisplayRole)
                          switch (index.column())
                          {
                          case 0:
                              return m_playerHolder->playerlist.value(index.row())->getName();
                          case 1:
                              return m_playerHolder->playerlist.value(index.row())->getEmail();
                          case 2:
                              return m_playerHolder->playerlist.value(index.row())->getHandy();
                          case 3:
                              return m_playerHolder->playerlist.value(index.row())->getBirthday();
                          case 4:
                              return m_playerHolder->playerlist.value(index.row())->getPassnumber();
                          default:
                              return QVariant();
                          }
                      else
                          return QVariant();
                      

                      }@

                      But this can't work if for example the first row player has the id 1 and the second 3 so there is 1 row left.

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        andre
                        wrote on last edited by
                        #11

                        [quote author="DaFranzl" date="1344346587"]Ok, I have implemented the functions as far as I can. Are you sure u meant
                        @QAbstractItemModel* model() const;@
                        and not
                        @QAbstractTableModel* model() const;@
                        ?
                        [/quote]
                        Yes, I'm sure. The fact that you're using a QAbstractTableModel is an implementation detail. The views all work on QAbstractItemModel anyway. Note that you can return any type of model in your implementation, as they all inherit from QAbstractItemModel anyway.

                        [quote]
                        If I am right with my guess is this the right implementation?

                        @QAbstractTableModel* PLAYERHOLDER::model() const
                        {
                        return new CONTACTMODEL(this);
                        }@

                        After running the Code I recieve many errors with this line.

                        @mutable CONTACTMODEL *m_model;@

                        Missing type specifier - int assumed. Note: 'default-int' isn't supported by C++ and also
                        Syntaxerror: Missing ; infront of *

                        (The errors are translated from German, they can vary a bit.
                        [/quote]

                        In principle, this is correct, but I would not create a new CONTACTMODEL every time model() is called. Instead, initialize m_model to 0 in your constructor, and in your implementation, only create a new instance if m_model is 0, which you then assing to m_model. Then, return m_model. That will ensure you only create one model instance per PLAYERHOLDER.

                        I don't get why you get the error you get. The line is in the header, inside PLAYERHOLDER, right?

                        [quote]
                        Also i dont know how to realise the data function, it looks like this at the moment:
                        @QVariant PLAYERHOLDER::CONTACTMODEL::data(const QModelIndex &index, int role) const
                        {
                        if (!index.isValid())
                        return QVariant();

                        if (index.row() >= m_playerHolder->playerlist.size())
                            return QVariant();
                        
                        if (role == Qt::DisplayRole)
                            switch (index.column())
                            {
                            case 0:
                                return m_playerHolder->playerlist.value(index.row())->getName();
                            case 1:
                                return m_playerHolder->playerlist.value(index.row())->getEmail();
                            case 2:
                                return m_playerHolder->playerlist.value(index.row())->getHandy();
                            case 3:
                                return m_playerHolder->playerlist.value(index.row())->getBirthday();
                            case 4:
                                return m_playerHolder->playerlist.value(index.row())->getPassnumber();
                            default:
                                return QVariant();
                            }
                        else
                            return QVariant();
                        

                        }@

                        But this can't work if for example the first row player has the id 1 and the second 3 so there is 1 row left.[/quote]

                        Well, then I think you'll need to create a mapping, so you map a row number to an id. You can't use them directly. You could, for instance, use QHash::keys() like this:
                        @
                        QList<int> rowToKeyMapping = m_playerHolder->playerlist.keys();
                        if (role == Qt::DisplayRole)
                        switch (index.column())
                        {
                        case 0:
                        return m_playerHolder->playerlist.value(rowToKeyMapping[index.row())]->getName();
                        //etc.
                        @

                        Also, you still are missing some checks. You have a good start, but you should also check the column number and if a valid parent index is supplied.

                        1 Reply Last reply
                        0
                        • D Offline
                          D Offline
                          DaFranzl
                          wrote on last edited by
                          #12

                          Because of the error question, this is how my headerfile looks like.
                          @#ifndef PLAYERHOLDER_H
                          #define PLAYERHOLDER_H

                          #include <QtCore>
                          #include <player.h>
                          #include <datasource.h>

                          class PLAYERHOLDER
                          {
                          public:
                          static PLAYERHOLDER* getInstance();
                          void createPlayer(PLAYER player);
                          void updatePlayer(int id);
                          void deletePlayer(int id);
                          PLAYER
                          findPlayer(int id);
                          void loadPlayers(int teamid);

                          QAbstractItemModel* model() const;
                          

                          private:
                          PLAYERHOLDER();
                          static PLAYERHOLDER thePlayerholder;
                          QHash<int, PLAYER
                          > playerlist;
                          DATASOURCE *datasource;
                          mutable CONTACTMODEL *m_model;

                          class CONTACTMODEL : public QAbstractTableModel
                          {
                              Q_OBJECT
                          public:
                              explicit CONTACTMODEL(PLAYERHOLDER* holder);
                          
                              int rowCount( const QModelIndex &parent ) const;
                              int columnCount( const QModelIndex &parent ) const;
                              QVariant data( const QModelIndex &index, int role ) const;
                              QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
                          
                          private:
                              PLAYERHOLDER* m_playerHolder;
                          };
                          

                          };

                          #endif // PLAYERHOLDER_H
                          @

                          1 Reply Last reply
                          0
                          • A Offline
                            A Offline
                            andre
                            wrote on last edited by
                            #13

                            I think the problem is that the compiler doesn't know about CONTACTMODEL yet. Try to reorder your header a bit, or introduce a forward declaration for the CONTACTMODEL.

                            1 Reply Last reply
                            0
                            • D Offline
                              D Offline
                              DaFranzl
                              wrote on last edited by
                              #14

                              Solved :)

                              1 Reply Last reply
                              0
                              • D Offline
                                D Offline
                                DaFranzl
                                wrote on last edited by
                                #15

                                You said the nested class should have the Q_Object, but the compiler says it is not supported for nested classes

                                1 Reply Last reply
                                0
                                • A Offline
                                  A Offline
                                  andre
                                  wrote on last edited by
                                  #16

                                  I don't think I said that, but you probably don't need it either. Note that you could even keep the whole declaration of CONTACTMODEL out of the header. Just forward declare it, and put all of it in your cpp file or use a separate header file for it. That way, you can change it however you want and classes including PLAYERMODEL's header won't need to recompile.

                                  1 Reply Last reply
                                  0
                                  • D Offline
                                    D Offline
                                    DaFranzl
                                    wrote on last edited by
                                    #17

                                    I think i keep it as nested class sofar, a couple of posts before you said that i need more functions to keep the view updated if something in the playerholder changes. What function would that be?

                                    1 Reply Last reply
                                    0
                                    • A Offline
                                      A Offline
                                      andre
                                      wrote on last edited by
                                      #18

                                      The class itself can still be nested, it is just about the place where you declare it. The methods you're going to need to access are the protected beginInsertRows, endInsertRows, beginRemoveRows, and endRemoveRows as well as the itemsChanged signal. These are needed to make the model and the connected views react properly to modifications in your data.

                                      1 Reply Last reply
                                      0
                                      • D Offline
                                        D Offline
                                        DaFranzl
                                        wrote on last edited by
                                        #19

                                        I tried to forward declare the class, but i just failed:( Nerver did forward declaration before and google didnt help. At the moment i just added an update() function to CONTACTMODEL and call it after create,modify,delete functions.
                                        @void update()
                                        {
                                        this.reset();
                                        }@

                                        and it works:)

                                        1 Reply Last reply
                                        0
                                        • A Offline
                                          A Offline
                                          andre
                                          wrote on last edited by
                                          #20

                                          That's a nice hack, but please don't use it in production code. Instead, learn how to properly update your model.

                                          1 Reply Last reply
                                          0

                                          • Login

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