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. How can I add custom widget to QListView?
Forum Updated to NodeBB v4.3 + New Features

How can I add custom widget to QListView?

Scheduled Pinned Locked Moved Solved General and Desktop
17 Posts 4 Posters 2.7k Views 3 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.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #3

    Since it's only text that you are showing, you could simply paint them at the correct position. It would make your code simpler and lighter.

    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
    • B Offline
      B Offline
      BushyAxis793
      wrote on last edited by BushyAxis793
      #4

      Thanks for the answer. I was able to add the widget to the QListView. But another problem arose. When adding a new item it gets "drawn" in place of the previous one. How do I fix this?

      36ff5ecb-8316-485d-a87e-8f100b651828-image.png

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

        It's not really clear. Can you show some picture of what is happening ?

        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
        • B Offline
          B Offline
          BushyAxis793
          wrote on last edited by
          #6

          Below I upload the QListView before adding the new item:

          13c13aff-0cf4-4b78-82d7-69ea9ffa8c1f-image.png

          After adding the first element, the QListView looks like this:

          44577b16-4afa-4f92-a921-c89a8e09f486-image.png

          After adding the second:

          c59b872f-73b2-4ae7-ba56-0752e8bfda66-image.png

          Below is my AddItem function:

          void OperationWidgetModel::AddItem(OperationWidget *item)
          {
          
              beginInsertRows(QModelIndex(),widgetList.count(),widgetList.count());
              widgetList.append(item);
              endInsertRows();
          }
          

          I don't know why, but the next element overlaps the previous one.

          M 1 Reply Last reply
          0
          • B BushyAxis793

            Below I upload the QListView before adding the new item:

            13c13aff-0cf4-4b78-82d7-69ea9ffa8c1f-image.png

            After adding the first element, the QListView looks like this:

            44577b16-4afa-4f92-a921-c89a8e09f486-image.png

            After adding the second:

            c59b872f-73b2-4ae7-ba56-0752e8bfda66-image.png

            Below is my AddItem function:

            void OperationWidgetModel::AddItem(OperationWidget *item)
            {
            
                beginInsertRows(QModelIndex(),widgetList.count(),widgetList.count());
                widgetList.append(item);
                endInsertRows();
            }
            

            I don't know why, but the next element overlaps the previous one.

            M Offline
            M Offline
            mpergand
            wrote on last edited by mpergand
            #7

            @BushyAxis793
            Show your paint() code,
            you probably don't use option.rect to get the right position.

            1 Reply Last reply
            1
            • B Offline
              B Offline
              BushyAxis793
              wrote on last edited by
              #8

              Here is my paint():

              void OperationWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
              {
              
                  if(!index.isValid())
                  {
                      return;
                  }
              
                  painter->save();
              
                  if(option.state & QStyle::State_Selected)
                  {
                      painter->fillRect(option.rect,option.palette.highlight());
                  }
              
              
                  OperationWidget* widget = index.data().value<OperationWidget*>();
              
                  QRect boundRect = QRect(0,00,275,70);
                  
                  painter->setPen(QPen(Qt::black,0.5,Qt::SolidLine));
                 
                  painter->drawRect(boundRect);
              
                  QRect operationNameRect = QRect(0,10,275,70);
                  QRect operationToolsRect =  QRect(10,40,275,70);
                  QRect operationTimeRect = QRect(-10,40,275,70);
                  QFont bold("Roboto",10);
                  bold.setBold(true);
                  painter->setFont(bold);
                  painter->setPen(Qt::black);
              
                  painter->drawText(operationNameRect,Qt::AlignTop | Qt::AlignHCenter,widget->GetOperationName());
                  painter->drawText(operationToolsRect,Qt::AlignLeft,QString::number(widget->GetToolsQuantity())+ " [szt.]");
                  painter->drawText(operationTimeRect,Qt::AlignRight,QString::number(widget->GetOperationTime())+ " [min.]");
              
              
              
              
              
              }
              
              M 1 Reply Last reply
              0
              • B BushyAxis793

                Here is my paint():

                void OperationWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
                {
                
                    if(!index.isValid())
                    {
                        return;
                    }
                
                    painter->save();
                
                    if(option.state & QStyle::State_Selected)
                    {
                        painter->fillRect(option.rect,option.palette.highlight());
                    }
                
                
                    OperationWidget* widget = index.data().value<OperationWidget*>();
                
                    QRect boundRect = QRect(0,00,275,70);
                    
                    painter->setPen(QPen(Qt::black,0.5,Qt::SolidLine));
                   
                    painter->drawRect(boundRect);
                
                    QRect operationNameRect = QRect(0,10,275,70);
                    QRect operationToolsRect =  QRect(10,40,275,70);
                    QRect operationTimeRect = QRect(-10,40,275,70);
                    QFont bold("Roboto",10);
                    bold.setBold(true);
                    painter->setFont(bold);
                    painter->setPen(Qt::black);
                
                    painter->drawText(operationNameRect,Qt::AlignTop | Qt::AlignHCenter,widget->GetOperationName());
                    painter->drawText(operationToolsRect,Qt::AlignLeft,QString::number(widget->GetToolsQuantity())+ " [szt.]");
                    painter->drawText(operationTimeRect,Qt::AlignRight,QString::number(widget->GetOperationTime())+ " [min.]");
                
                
                
                
                
                }
                
                M Offline
                M Offline
                mpergand
                wrote on last edited by
                #9

                @BushyAxis793 said in How can I add custom widget to QListView?:

                QRect boundRect = QRect(0,00,275,70);

                You must set the origin with option.rect.
                Look at the Y position : qDebug()<<option.rect.y();

                see an example Here

                B 1 Reply Last reply
                3
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #10

                  Beside what @mpergand pointed, are you still using one widget per row ? This is bad design. The proper use of the delegate means you can drop that widget completely.

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

                  B 1 Reply Last reply
                  1
                  • M mpergand

                    @BushyAxis793 said in How can I add custom widget to QListView?:

                    QRect boundRect = QRect(0,00,275,70);

                    You must set the origin with option.rect.
                    Look at the Y position : qDebug()<<option.rect.y();

                    see an example Here

                    B Offline
                    B Offline
                    BushyAxis793
                    wrote on last edited by
                    #11

                    @mpergand I think I don't understand. I change my origin for :

                    QRect boundRect = op.rect;
                    

                    Now I have the same issue but without border.

                    89be88e1-21b0-44a5-83e5-2b08f06645a6-image.png

                    1 Reply Last reply
                    0
                    • SGaistS SGaist

                      Beside what @mpergand pointed, are you still using one widget per row ? This is bad design. The proper use of the delegate means you can drop that widget completely.

                      B Offline
                      B Offline
                      BushyAxis793
                      wrote on last edited by
                      #12

                      @SGaist To be honest, I ultimately wanted to use QListWidget, but it doesn't have all the features. And I've been struggling with QListView + Model + Delegate for a few weeks now.

                      M 1 Reply Last reply
                      0
                      • B BushyAxis793

                        @SGaist To be honest, I ultimately wanted to use QListWidget, but it doesn't have all the features. And I've been struggling with QListView + Model + Delegate for a few weeks now.

                        M Offline
                        M Offline
                        mpergand
                        wrote on last edited by mpergand
                        #13

                        @BushyAxis793

                        I think you need to implement sizeHint() as well.

                        As @SGaist noted, your code is confusing :)

                        Can you post a skech of what you want to do, is it a single list of text cells ?

                        1 Reply Last reply
                        0
                        • B Offline
                          B Offline
                          BushyAxis793
                          wrote on last edited by
                          #14

                          Let me describe as simply as I can. I have added a QListWidget in the main window of my program. I created a new class called OperationWidget, which inherits from QWidget. It has all the methods and variables it needs. In an additional QDialog window, I set the parameters of the OperationWidget object and then add it to QListWidget. I can add and remove items from QListWidget, but I cannot change the position of the items. So I have to use QListView + OperationWidgetModel + OperationWidgetDelegate. I have never worked with models and delegates, but I know there is no other way. I want the whole thing to look like the QListWidget.

                          OperationWidget.h

                          #ifndef OPERATIONWIDGET_H
                          #define OPERATIONWIDGET_H
                          
                          #include <QWidget>
                          
                          namespace Ui {
                          class OperationWidget;
                          }
                          
                          class OperationWidget : public QWidget
                          {
                              Q_OBJECT
                          
                          public:
                              explicit OperationWidget(QWidget *parent = nullptr);
                              ~OperationWidget();
                          
                              void SetOperationName(const QString&);
                              QString GetOperationName()const;
                          
                              void SetWorkplaceName(const QString&);
                              QString GetWorkplaceName()const;
                          
                              void SetToolQuantity(const int&);
                              int GetToolsQuantity()const;
                          
                              void SetOperationTime(const double&);
                              double GetOperationTime() const;
                          
                              void SetOperationDescription(const QString&);
                              QString GetOperationDescription()const;
                          
                              void SetPreparationAndCompletionTime(const int&);
                              int GetPreparationAndCompletionTime()const;
                          
                              void SetWorkplaceNumber(const QString&);
                              QString GetWorkplaceNumber()const;
                          
                              void SetWorkplaceCost(const int&);
                              int GetWorkplaceCost()const;
                          
                              void SetUnitTime(const int&);
                              int GetUnitTime()const;
                          
                              void LoadToolTip();
                          
                          private:
                              Ui::OperationWidget *ui;
                              QString operationName;
                              QString workplaceName;
                              int toolsQuantity;
                              double operationTime;
                              QString operationDescription;
                              int preparationAndCompletionTime;
                              QString workplaceNumber;
                              int workplaceCost;
                              int unitTime;
                          
                          };
                          
                          #endif // OPERATIONWIDGET_H
                          
                          

                          OperationWidget.cpp

                          #include "operationwidget.h"
                          #include "ui_operationwidget.h"
                          #include <QFrame>
                          
                          OperationWidget::OperationWidget(QWidget *parent) :
                              QWidget(parent),
                              ui(new Ui::OperationWidget)
                          {
                              ui->setupUi(this);
                          
                          
                          }
                          
                          OperationWidget::~OperationWidget()
                          {
                              delete ui;
                          }
                          
                          void OperationWidget::SetOperationName(const QString &name)
                          {
                              operationName = name;
                              ui->operationNameLabel->setText(name);
                          }
                          
                          QString OperationWidget::GetOperationName() const
                          {
                              return operationName;
                          }
                          
                          void OperationWidget::SetWorkplaceName(const QString &name)
                          {
                              workplaceName = name;
                          }
                          
                          QString OperationWidget::GetWorkplaceName() const
                          {
                              return workplaceName;
                          }
                          
                          void OperationWidget::SetToolQuantity(const int &tools)
                          {
                              toolsQuantity = tools;
                              ui->toolsQuantityLabel->setText(QString::number(tools)+ " "+"[szt.]");
                          }
                          
                          int OperationWidget::GetToolsQuantity() const
                          {
                              return toolsQuantity;
                          }
                          
                          void OperationWidget::SetOperationTime(const double &time)
                          {
                              operationTime = time;
                              ui->timeOperationLabel->setText(QString::number(GetOperationTime())+ " "+ "[min.]");
                          }
                          
                          double OperationWidget::GetOperationTime() const
                          {
                              return operationTime;
                          }
                          
                          void OperationWidget::SetOperationDescription(const QString &description)
                          {
                              operationDescription = description;
                          }
                          
                          QString OperationWidget::GetOperationDescription() const
                          {
                              return operationDescription;
                          }
                          
                          void OperationWidget::SetPreparationAndCompletionTime(const int &tpz)
                          {
                              preparationAndCompletionTime = tpz;
                          }
                          
                          int OperationWidget::GetPreparationAndCompletionTime() const
                          {
                              return preparationAndCompletionTime;
                          }
                          
                          void OperationWidget::SetWorkplaceNumber(const QString &number)
                          {
                              workplaceNumber = number;
                          }
                          
                          QString OperationWidget::GetWorkplaceNumber() const
                          {
                              return workplaceNumber;
                          }
                          
                          void OperationWidget::SetWorkplaceCost(const int &cost)
                          {
                              workplaceCost = cost;
                          }
                          
                          int OperationWidget::GetWorkplaceCost() const
                          {
                              return workplaceCost;
                          }
                          
                          void OperationWidget::SetUnitTime(const int &unitT)
                          {
                              unitTime = unitT;
                          }
                          
                          int OperationWidget::GetUnitTime() const
                          {
                              return unitTime;
                          }
                          
                          void OperationWidget::LoadToolTip()
                          {
                              this->setToolTip("Nazwa stanowiska: "+GetWorkplaceName()+"\n"+
                                               "Nazwa operacji: "+GetOperationName()+ "\n"+
                                               "Numer stanowiska: "+GetWorkplaceNumber()+"\n"+
                                               "Koszt stanowiska: "+QString::number(GetWorkplaceCost())+ " [zł]"+"\n"+
                                               "Czas przygotowawczy: "+QString::number(GetPreparationAndCompletionTime())+" [min.]"+"\n"+
                                               "Czas jednostkowy: "+QString::number(GetUnitTime())+" [min.]"+"\n"+
                                               "Ilość narzędzi: "+QString::number(GetToolsQuantity())+"\n"+
                                               "Czas operacji: "+QString::number(GetOperationTime())+" [min.]"+"\n"+
                                               "Opis operacji: "+GetOperationDescription());
                          }
                          
                          

                          QListWidget in mainwindow:

                          cab0e9cd-6220-4085-8c3d-7cab8c607321-image.png

                          Put simply. I want to add my own widget to the QListView.

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

                            As written in the documentation and here as well: setCellWidget should only be used to show some static content not as a replacement of a properly implemented delegate.

                            There's no need for that widget of yours unless it's an editor.

                            You really should take the time to build a proper model to store your data. It will be a table of some sort. Which you can use with a QListView.

                            Basically, your delegate will have to pull the data from the model when drawing. You will essentially have to position the text properly. There really isn't more to it than that.

                            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
                            • B BushyAxis793 referenced this topic on
                            • B Offline
                              B Offline
                              BushyAxis793
                              wrote on last edited by
                              #16

                              I found the solution. The problem was in paint(). Now it looks much better

                              78c8e6f5-99f5-4984-90f9-3677c9d8a826-image.png

                              Thanks everyone for help!

                              Unfortunatelly, I found another issue. In slot when I add my widget to list:

                              void QueriesCreator::ReceiveOperationData(QString workplaceName, QString operationName, int tools, double time, QString description,int tpz, QString number, int cost, int unitT)
                              {
                              
                                  OperationWidget* operationWidget = new OperationWidget(new QWidget);
                              
                                  operationWidget->SetWorkplaceName(workplaceName);
                                  operationWidget->SetOperationName(operationName);
                                  operationWidget->SetToolQuantity(tools);
                                  operationWidget->SetOperationTime(time);
                                  operationWidget->SetOperationDescription(description);
                                  operationWidget->SetPreparationAndCompletionTime(tpz);
                                  operationWidget->SetWorkplaceNumber(number);
                                  operationWidget->SetWorkplaceCost(cost);
                                  operationWidget->SetUnitTime(unitT);
                                  operationWidget->LoadToolTip();
                              
                                  model.AddItem(operationWidget);
                              }
                              

                              As you can see I call LoadToolTip() method:

                              void OperationWidget::LoadToolTip()
                              {
                                  this->setToolTip("Nazwa stanowiska: "+GetWorkplaceName()+"\n"+
                                                   "Nazwa operacji: "+GetOperationName()+ "\n"+
                                                   "Numer stanowiska: "+GetWorkplaceNumber()+"\n"+
                                                   "Koszt stanowiska: "+QString::number(GetWorkplaceCost())+ " [zł]"+"\n"+
                                                   "Czas przygotowawczy: "+QString::number(GetPreparationAndCompletionTime())+" [min.]"+"\n"+
                                                   "Czas jednostkowy: "+QString::number(GetUnitTime())+" [min.]"+"\n"+
                                                   "Ilość narzędzi: "+QString::number(GetToolsQuantity())+"\n"+
                                                   "Czas operacji: "+QString::number(GetOperationTime())+" [min.]"+"\n"+
                                                   "Opis operacji: "+GetOperationDescription());
                              }
                              

                              But I can see any tooltip when I move cursor over widget. How can I enable it? Any ideas?

                              SGaistS 1 Reply Last reply
                              0
                              • B BushyAxis793 has marked this topic as solved on
                              • B BushyAxis793

                                I found the solution. The problem was in paint(). Now it looks much better

                                78c8e6f5-99f5-4984-90f9-3677c9d8a826-image.png

                                Thanks everyone for help!

                                Unfortunatelly, I found another issue. In slot when I add my widget to list:

                                void QueriesCreator::ReceiveOperationData(QString workplaceName, QString operationName, int tools, double time, QString description,int tpz, QString number, int cost, int unitT)
                                {
                                
                                    OperationWidget* operationWidget = new OperationWidget(new QWidget);
                                
                                    operationWidget->SetWorkplaceName(workplaceName);
                                    operationWidget->SetOperationName(operationName);
                                    operationWidget->SetToolQuantity(tools);
                                    operationWidget->SetOperationTime(time);
                                    operationWidget->SetOperationDescription(description);
                                    operationWidget->SetPreparationAndCompletionTime(tpz);
                                    operationWidget->SetWorkplaceNumber(number);
                                    operationWidget->SetWorkplaceCost(cost);
                                    operationWidget->SetUnitTime(unitT);
                                    operationWidget->LoadToolTip();
                                
                                    model.AddItem(operationWidget);
                                }
                                

                                As you can see I call LoadToolTip() method:

                                void OperationWidget::LoadToolTip()
                                {
                                    this->setToolTip("Nazwa stanowiska: "+GetWorkplaceName()+"\n"+
                                                     "Nazwa operacji: "+GetOperationName()+ "\n"+
                                                     "Numer stanowiska: "+GetWorkplaceNumber()+"\n"+
                                                     "Koszt stanowiska: "+QString::number(GetWorkplaceCost())+ " [zł]"+"\n"+
                                                     "Czas przygotowawczy: "+QString::number(GetPreparationAndCompletionTime())+" [min.]"+"\n"+
                                                     "Czas jednostkowy: "+QString::number(GetUnitTime())+" [min.]"+"\n"+
                                                     "Ilość narzędzi: "+QString::number(GetToolsQuantity())+"\n"+
                                                     "Czas operacji: "+QString::number(GetOperationTime())+" [min.]"+"\n"+
                                                     "Opis operacji: "+GetOperationDescription());
                                }
                                

                                But I can see any tooltip when I move cursor over widget. How can I enable it? Any ideas?

                                SGaistS Offline
                                SGaistS Offline
                                SGaist
                                Lifetime Qt Champion
                                wrote on last edited by
                                #17

                                A delegate does not handle tooltips, you should return them through the model for the Qt::ToolTipRole role.

                                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