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. Painting Widget with QPainter
Forum Updated to NodeBB v4.3 + New Features

Painting Widget with QPainter

Scheduled Pinned Locked Moved General and Desktop
14 Posts 3 Posters 16.7k 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.
  • raven-worxR Offline
    raven-worxR Offline
    raven-worx
    Moderators
    wrote on last edited by
    #5

    try this:
    @
    painter->save();
    EditTargetPowerWidget *widgetTarget = new EditTargetPowerWidget();
    widgetTarget->resize( option.rect.size() );
    widgetTarget->targetStart->setText("Test");
    painter->translate(option.rect.topLeft());
    widgetTarget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );
    painter->restore();
    @

    And another suggestion:
    Don't create a new widget on every time your paint() method is called. No need to allocate new memory every time, beside you never delete this widget, thus it leaks.
    Rather hold a single instance in your delegate class and reuse it when needed.

    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
    If you have a question please use the forum so others can benefit from the solution in the future

    1 Reply Last reply
    0
    • M Offline
      M Offline
      maximus
      wrote on last edited by
      #6

      Thanks Raven it's working now!

      https://www.dropbox.com/s/no0edjn08ei66ap/workingPaint.png

      One last thing, I'll check more but if you know already, Inside this custom widget, I have QLabels but the main application stylesheet doesn't get applied to those label it seems (they should be white)
      Or i can just use .setStylesheet but I like all my presentation code to be in the same place.

      thanks again!


      Free Indoor Cycling Software - https://maximumtrainer.com

      1 Reply Last reply
      0
      • raven-worxR Offline
        raven-worxR Offline
        raven-worx
        Moderators
        wrote on last edited by
        #7

        set the stylesheet on the QApplication instance, so even parent-less widgets get the style, or

        set a parent-widget, so that i derives the stylesheet style from a widget which already has got it set in the hierarchy

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        1 Reply Last reply
        0
        • M Offline
          M Offline
          maximus
          wrote on last edited by
          #8

          Oh I totally forgot to give the widget a parent, there is the problem.
          Thanks again!


          Free Indoor Cycling Software - https://maximumtrainer.com

          1 Reply Last reply
          0
          • M Offline
            M Offline
            maximus
            wrote on last edited by
            #9

            The display is working fine now, but my delegate has a memory leak in the paint function now.

            I made a video showing the problem in action :
            https://www.youtube.com/watch?v=b882e4cEREE&feature=youtu.be

            I have noted that it is in the column that I used QWidget.render(). So in the code below, if I comment column 3,4 and 5, I don't have a memory leak.
            Sorry I know I asked a lot of question already, hopefully I can give back to Qt..

            Do you think that the line
            "widgetTarget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );"
            could trigger an infinite loop? I'm failing to see where all that memory goes.. I should probably learn to use the debugger also -_-

            @//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            void SpinBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {

            qDebug() << "paintNow...";
            if (option.state & QStyle::State_Selected) {
                painter->setPen(QPen( Qt::red, 5 ));
                painter->drawRect(option.rect);
                return;
            }
            
            painter->setPen(QPen( Qt::white, 1 ));
            
            /// Type
            if (index.column() == 0) {
                int value = index.model()->data(index, Qt::DisplayRole).toInt();
                QString intervalType = Interval::getTypeFromInt(value);
            
                painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter, intervalType);
            }
            
            /// Duration
            else if (index.column() == 1) {
                QTime time = index.model()->data(index, Qt::DisplayRole).toTime();
                QString toDisplay = Util::showQTimeAsString(time);
                painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter, toDisplay );
            }
            
            /// Display Message
            else if (index.column() == 2) {
                QString msg = index.model()->data(index, Qt::DisplayRole).toString();
                painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter, msg);
            }
            
            /// Target Power
            else if (index.column() == 3) {
            
            
                EditTargetPowerWidget *widgetTarget = new EditTargetPowerWidget(ptrParent, "POWER");
                std::shared_ptr<Interval> interval(qvariant_cast<std::shared_ptr<Interval>>( index.model()->data(index, Qt::DisplayRole) ));
            
                int targetStepPower = interval->getPowerStepType();
                double startFTP = interval->getFTP_start() * 100;
                double endFTP = interval->getFTP_end() * 100;
                int range = interval->getFTP_range();
            
                widgetTarget->stepComboBox->setCurrentIndex(targetStepPower);
                widgetTarget->targetStartValue->setValue(startFTP);
                widgetTarget->targetEndValue->setValue(endFTP);
                widgetTarget->targetRangeValue->setValue(range);
            
                painter->save();
                widgetTarget->resize( option.rect.size() );
                painter->translate(option.rect.topLeft());
                widgetTarget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );
                painter->restore();
            
            }
            
            /// Target Cadence
            else if (index.column() == 4) {
            
            
                EditTargetPowerWidget *widgetTarget = new EditTargetPowerWidget(ptrParent, "CADENCE");
                std::shared_ptr<Interval> interval(qvariant_cast<std::shared_ptr<Interval>>( index.model()->data(index, Qt::DisplayRole) ));
            
                int targetStepCadence = interval->getCadenceStepType();
                int startCadence = interval->getCadence_start();
                int endCadence = interval->getCadence_end();
                int range = interval->getCadence_range();
            
                widgetTarget->stepComboBox->setCurrentIndex(targetStepCadence);
                widgetTarget->targetStartValue->setValue(startCadence);
                widgetTarget->targetEndValue->setValue(endCadence);
                widgetTarget->targetRangeValue->setValue(range);
            
                painter->save();
                widgetTarget->resize( option.rect.size() );
                painter->translate(option.rect.topLeft());
                widgetTarget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );
                painter->restore();
            
            }
            
            /// Target Cadence
            else if (index.column() == 5) {
            
            
                EditTargetPowerWidget *widgetTarget = new EditTargetPowerWidget(ptrParent, "HR");
                std::shared_ptr<Interval> interval(qvariant_cast<std::shared_ptr<Interval>>( index.model()->data(index, Qt::DisplayRole) ));
            
                int targetStepHR = interval->getHRStepType();
                double startHR = interval->getHR_start() *100;
                double endHR = interval->getHR_end() *100;
                int range = interval->getHR_range();
            
                widgetTarget->stepComboBox->setCurrentIndex(targetStepHR);
                widgetTarget->targetStartValue->setValue(startHR);
                widgetTarget->targetEndValue->setValue(endHR);
                widgetTarget->targetRangeValue->setValue(range);
            
                painter->save();
                widgetTarget->resize( option.rect.size() );
                painter->translate(option.rect.topLeft());
                widgetTarget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );
                painter->restore();
            
            }
            
            
            /// Standard delegate display - Display Message
            else {
                QStyleOptionViewItem viewOption(option);
                viewOption.palette.setColor(QPalette::Text, QColor(Qt::white));
                QStyledItemDelegate::paint(painter, viewOption, index);
            }
            

            }@


            Free Indoor Cycling Software - https://maximumtrainer.com

            1 Reply Last reply
            0
            • M Offline
              M Offline
              maximus
              wrote on last edited by
              #10

              something wrong with the line
              @widgetTarget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );@
              i comment this and don't get memory leak.. i'll post if I find a solution

              [Edit: The function paint of my delegate is being called non-stop when the TableView is active.. still investigating why]


              Free Indoor Cycling Software - https://maximumtrainer.com

              1 Reply Last reply
              0
              • M Offline
                M Offline
                maximus
                wrote on last edited by
                #11

                Finally I used drawText as it is easier and more versatile, doesn't have the memory problem I had with QWidget.render()
                needs more coding but at least what you code is what you get
                Thanks for your help again! :)

                @ else if (index.column() == 3 && paint) {

                    painter->save();
                    EditTargetPowerWidget *widgetTarget = new EditTargetPowerWidget(ptrParent, "POWER");
                    std::shared_ptr<Interval> interval(qvariant_cast<std::shared_ptr<Interval>>( index.model()->data(index, Qt::DisplayRole) ));
                
                    int targetStepPower = interval->getPowerStepType();
                    double startFTP = interval->getFTP_start() * 100;
                    double endFTP = interval->getFTP_end() * 100;
                    int range = interval->getFTP_range();
                
                    widgetTarget->stepComboBox->setCurrentIndex(targetStepPower);
                    widgetTarget->targetStartValue->setValue(startFTP);
                    widgetTarget->targetEndValue->setValue(endFTP);
                    widgetTarget->targetRangeValue->setValue(range);
                

                // widgetTarget->resize( option.rect.size() );
                // painter->translate(option.rect.topLeft());
                // widgetTarget->render(painter, QPoint(), QRegion(), QWidget::DrawWindowBackground );

                    QString targetStep_str = Interval::getStepTypeFromInt(targetStepPower);
                    QString target_str = "["+ QString::number(startFTP)  + " - " + QString::number(endFTP) + "]";
                    QString range_str = "±" + QString::number(range);
                    QString target1 = tr("Target: ");
                    QString range1 = tr("Range: ");
                    QString watts = tr(" Watts");
                    QString pFtp = tr(" % FTP");
                
                
                    painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter,
                                      targetStep_str + "\n" +
                                      target1 +  target_str + pFtp + "\n" +
                                      range1 + range_str + watts);
                
                
                    painter->restore();
                
                
                }@
                

                Free Indoor Cycling Software - https://maximumtrainer.com

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  maximus
                  wrote on last edited by
                  #12

                  I modified my code to improve memory and find where is the problem. I think it is a memory leak with the createEditor() that doesn't get deleted after each use.

                  I would like to know if there is an example of this technique
                  "source":http://qt-project.org/doc/qt-5.0/qtwidgets/itemviews-spinboxdelegate.html
                  Furthermore it is also possible to reuse (and avoid deleting) the editor widget by reimplementing the destroyEditor() function

                  I tried but the createEditor and setEditorData are "const" function and I can't store any pointer there..
                  [EDIT: I removed the const in createEditor but now the function is now longer called, I wanted to create all my editor in the Constructor and reuse the same.. this technique doesn't work -_-]

                  I changed the way I change my model using a pointer in Qvariant rather than passing the whole object in a Qvariant, it helps but the memory used is still too high,

                  @//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                  void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {

                  /// Type
                  if (index.column() == 0) {
                      IntervalComboBox *comboBox = static_cast<IntervalComboBox*>(editor);
                      int value = comboBox->currentIndex();
                      model->setData(index, value, Qt::EditRole);
                  }
                  
                  /// Duration
                  else if (index.column() == 1) {
                      QTimeEdit *timeEdit = static_cast<QTimeEdit*>(editor);
                      QTime time1 = timeEdit->time();
                      model->setData(index, time1, Qt::EditRole);
                  }
                  
                  /// Display Message
                  else if (index.column() == 2) {
                      QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
                      QString msg = lineEdit->text();
                      model->setData(index, msg, Qt::EditRole);
                  }
                  
                  /// Target Power
                  else if (index.column() == 3) {
                      
                      EditTargetPowerWidget *targetWidget = static_cast<EditTargetPowerWidget*>(editor);
                      
                      int targetStepPower = targetWidget->stepComboBox->currentIndex();
                      Interval::StepType stepType = static_cast<Interval::StepType>( targetStepPower );
                      double startFTP = targetWidget->targetStartValue->value()/100;
                      double endFTP = targetWidget->targetEndValue->value()/100;
                      int range = targetWidget->targetRangeValue->value();
                      
                      
                      Interval *interval = (Interval*) index.model()->data(index, Qt::DisplayRole).value<void *>();
                      interval->setPowerData(stepType, startFTP, endFTP, range);
                      
                      /// MEMORY STILL INCREASE BY 2MB EACH EDIT, pointer *targetWidget not deleted?
                      
                      /// Break model/view architecture here...
                      ///        model->setData(index, variant, Qt::EditRole);
                  }
                  

                  @


                  Free Indoor Cycling Software - https://maximumtrainer.com

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    maximus
                    wrote on last edited by
                    #13

                    Found the problem!

                    In the paint(), I was using a Widget and not deleting it after using it..

                    @ else if (index.column() == 3 && paint) {

                        painter->save();
                        EditTargetPowerWidget *targetWidget = new EditTargetPowerWidget(ptrParent, "POWER");
                    
                    
                        Interval *interval = (Interval*) index.model()->data(index, Qt::DisplayRole).value<void *>();
                    
                        int targetStepPower = interval->getPowerStepType();
                        double startFTP = interval->getFTP_start() * 100;
                        double endFTP = interval->getFTP_end() * 100;
                        int range = interval->getFTP_range();
                    
                        targetWidget->stepComboBox->setCurrentIndex(targetStepPower);
                        targetWidget->targetStartValue->setValue(startFTP);
                        targetWidget->targetEndValue->setValue(endFTP);
                        targetWidget->targetRangeValue->setValue(range);
                    
                    
                        targetWidget->resize( option.rect.size() );
                        painter->translate(option.rect.topLeft());
                        targetWidget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );
                    
                    
                        painter->restore();
                        delete targetWidget;
                    
                    
                    }@
                    

                    Free Indoor Cycling Software - https://maximumtrainer.com

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      maximus
                      wrote on last edited by
                      #14

                      Found the problem!

                      I forgot to delete a pointer of my QWidget in the paint() function. this was increasing the memory usage each time.

                      @
                      else if (index.column() == 3 && paint) {

                          painter->save();
                          EditTargetPowerWidget *targetWidget = new EditTargetPowerWidget(ptrParent, "POWER");
                      
                          Interval *interval = (Interval*) index.model()->data(index, Qt::DisplayRole).value<void *>();
                      
                          int targetStepPower = interval->getPowerStepType();
                          double startFTP = interval->getFTP_start() * 100;
                          double endFTP = interval->getFTP_end() * 100;
                          int range = interval->getFTP_range();
                      
                          targetWidget->stepComboBox->setCurrentIndex(targetStepPower);
                          targetWidget->targetStartValue->setValue(startFTP);
                          targetWidget->targetEndValue->setValue(endFTP);
                          targetWidget->targetRangeValue->setValue(range);
                      
                          targetWidget->resize( option.rect.size() );
                          painter->translate(option.rect.topLeft());
                          targetWidget->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );
                      
                      
                          painter->restore();
                          delete targetWidget;
                      
                      }@
                      

                      Free Indoor Cycling Software - https://maximumtrainer.com

                      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