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. QComboxBox different sizes for button and popup
Qt 6.11 is out! See what's new in the release blog

QComboxBox different sizes for button and popup

Scheduled Pinned Locked Moved Solved General and Desktop
qcombobox
12 Posts 3 Posters 7.1k 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.
  • pablolitoP pablolito

    Hi guys !

    I looking for some help about the QComboBox Widget.

    I'm trying to build a QComboBox with checkboxes (to allow user to select multiple option easily) and in order to save some space on my user interface, I would like to fix the size of the button, and to allow the popup to expand to fit the size of its contents.

    The code I have for now is :

     QComboBox * combo;
     QStandardItem *  item1, * item2;
    
    combo = new QComboBox(ui->tabWidget->widget(0));
    
    this->model = new QStandardItemModel;
    item1 = new QStandardItem;
    item2 = new QStandardItem;
    
    this->model->insertRow(0, item1);
    
    item1->setText("test");
    item1->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
    item1->setData(Qt::Unchecked, Qt::CheckStateRole);
    
    
    item2->setText("test2 long text aha ah ");
    item2->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
    item2->setData(Qt::Unchecked, Qt::CheckStateRole);
    this->model->insertRow(1, item2);
    
    
    combo->setModel(this->model);
    
    combo->view()->setTextElideMode(Qt::ElideNone);
    combo->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
    combo->setMaximumWidth(50);
    
    combo->show();
    
    

    This does the job, except for the size of the popup list.

    So with this code I have a 50 pixels wide button, but I have no clue on how I can make the popup to expand (I tried to access it by calling combo->view() but without any success).

    If someone know how to do this, I would really appreciate some help :)

    Thanks in advance !!
    Pablo

    RatzzR Offline
    RatzzR Offline
    Ratzz
    wrote on last edited by
    #2

    @pablolito
    Are you looking for this http://doc.qt.io/qt-4.8/qcombobox.html#showPopup ?

    --Alles ist gut.

    1 Reply Last reply
    2
    • pablolitoP Offline
      pablolitoP Offline
      pablolito
      wrote on last edited by
      #3

      Actually yes ! thanks a lot ! But I still have a little work to do to get the result I want I guess.

      In the showPopup() method I did a :

      view()->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
      view()->setMinimumWidth(150);
      QComboBox::showPopup();
      

      But I think the setSizeAdjustPolicy() call is not taken into account because the SetMinimumWidth is mandatory if I want the popup list to be resized. is this because of the setMaximumWidth(50); I do previously ?

      Also, if possible I looking to have an automatic resize (150 px is just an example, I would like the popup to fit its content size).

      Do you know how can I achieve this ?

      RatzzR 1 Reply Last reply
      0
      • pablolitoP pablolito

        Actually yes ! thanks a lot ! But I still have a little work to do to get the result I want I guess.

        In the showPopup() method I did a :

        view()->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
        view()->setMinimumWidth(150);
        QComboBox::showPopup();
        

        But I think the setSizeAdjustPolicy() call is not taken into account because the SetMinimumWidth is mandatory if I want the popup list to be resized. is this because of the setMaximumWidth(50); I do previously ?

        Also, if possible I looking to have an automatic resize (150 px is just an example, I would like the popup to fit its content size).

        Do you know how can I achieve this ?

        RatzzR Offline
        RatzzR Offline
        Ratzz
        wrote on last edited by Ratzz
        #4

        @pablolito
        Can you just test with combo->showPopup(); without setting any size .

        --Alles ist gut.

        pablolitoP 1 Reply Last reply
        0
        • RatzzR Ratzz

          @pablolito
          Can you just test with combo->showPopup(); without setting any size .

          pablolitoP Offline
          pablolitoP Offline
          pablolito
          wrote on last edited by
          #5

          @Ratzz

          In this case the button take the size of the popup list, even when the popup is hidden.

          RatzzR 1 Reply Last reply
          0
          • pablolitoP pablolito

            @Ratzz

            In this case the button take the size of the popup list, even when the popup is hidden.

            RatzzR Offline
            RatzzR Offline
            Ratzz
            wrote on last edited by
            #6

            @pablolito
            I did not get exactly what problem you are facing .can you explain your screenshot or so?

            --Alles ist gut.

            1 Reply Last reply
            0
            • pablolitoP Offline
              pablolitoP Offline
              pablolito
              wrote on last edited by
              #7

              Okay.

              I modified a little the code, here is what I have now:

              CheckBoxList::CheckBoxList( QMap<uint32_t, QString> values, QWidget * parent):
                  QComboBox(parent)
              {
                  QMapIterator<uint32_t, QString> it(values);
              
                  QStandardItem *  item1, * item2;
              
                  this->model = new QStandardItemModel;
                  item1 = new QStandardItem;
                  item2 = new QStandardItem;
              
                  this->model->insertRow(0, item1);
              
                  item1->setText("test");
                  item1->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
                  item1->setData(Qt::Unchecked, Qt::CheckStateRole);
              
              
                  item2->setText("test2 long text aha ah ");
                  item2->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
                  item2->setData(Qt::Unchecked, Qt::CheckStateRole);
                  this->model->insertRow(1, item2);
              
              
                  this->setModel(this->model);
              
                  this->view()->setTextElideMode(Qt::ElideNone);
                  this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
                  this->setMaximumWidth(50);
                  setModel(this->model);
              }
              
              void CheckBoxList::showPopup()
                  {
                      view()->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
                      view()->setMinimumWidth(150);
                      QComboBox::showPopup();
              
                  }
              
              void CheckBoxList::paintEvent(QPaintEvent *)
                  {
                      QStylePainter painter(this);
                      painter.setPen(palette().color(QPalette::Text));
              
                      // draw the combobox frame, focusrect and selected etc.
                      QStyleOptionComboBox opt;
                      initStyleOption(&opt);
              
                      // if no display text been set , use "..." as default
                      if(m_DisplayText.isNull())
                          opt.currentText = "...";
                      else
                          opt.currentText = m_DisplayText;
                      painter.drawComplexControl(QStyle::CC_ComboBox, opt);
              
                      // draw the icon and text
                      painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
                  }
              

              This code give me this result :
              image

              This is what I want : a button which is 50px wide and a popup which is wide enough to display all the items. But for now the popup list is 150px wide (fixed) and I would like to have the width to fit the content of the list.

              Is it clearer ?

              RatzzR 1 Reply Last reply
              0
              • pablolitoP pablolito

                Okay.

                I modified a little the code, here is what I have now:

                CheckBoxList::CheckBoxList( QMap<uint32_t, QString> values, QWidget * parent):
                    QComboBox(parent)
                {
                    QMapIterator<uint32_t, QString> it(values);
                
                    QStandardItem *  item1, * item2;
                
                    this->model = new QStandardItemModel;
                    item1 = new QStandardItem;
                    item2 = new QStandardItem;
                
                    this->model->insertRow(0, item1);
                
                    item1->setText("test");
                    item1->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
                    item1->setData(Qt::Unchecked, Qt::CheckStateRole);
                
                
                    item2->setText("test2 long text aha ah ");
                    item2->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
                    item2->setData(Qt::Unchecked, Qt::CheckStateRole);
                    this->model->insertRow(1, item2);
                
                
                    this->setModel(this->model);
                
                    this->view()->setTextElideMode(Qt::ElideNone);
                    this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
                    this->setMaximumWidth(50);
                    setModel(this->model);
                }
                
                void CheckBoxList::showPopup()
                    {
                        view()->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
                        view()->setMinimumWidth(150);
                        QComboBox::showPopup();
                
                    }
                
                void CheckBoxList::paintEvent(QPaintEvent *)
                    {
                        QStylePainter painter(this);
                        painter.setPen(palette().color(QPalette::Text));
                
                        // draw the combobox frame, focusrect and selected etc.
                        QStyleOptionComboBox opt;
                        initStyleOption(&opt);
                
                        // if no display text been set , use "..." as default
                        if(m_DisplayText.isNull())
                            opt.currentText = "...";
                        else
                            opt.currentText = m_DisplayText;
                        painter.drawComplexControl(QStyle::CC_ComboBox, opt);
                
                        // draw the icon and text
                        painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
                    }
                

                This code give me this result :
                image

                This is what I want : a button which is 50px wide and a popup which is wide enough to display all the items. But for now the popup list is 150px wide (fixed) and I would like to have the width to fit the content of the list.

                Is it clearer ?

                RatzzR Offline
                RatzzR Offline
                Ratzz
                wrote on last edited by
                #8

                @pablolito
                You can try with http://doc.qt.io/qt-4.8/qsizepolicy.html#setHorizontalPolicy setting to QSizePolicy::MinimumExpanding .

                --Alles ist gut.

                pablolitoP 1 Reply Last reply
                0
                • RatzzR Ratzz

                  @pablolito
                  You can try with http://doc.qt.io/qt-4.8/qsizepolicy.html#setHorizontalPolicy setting to QSizePolicy::MinimumExpanding .

                  pablolitoP Offline
                  pablolitoP Offline
                  pablolito
                  wrote on last edited by
                  #9

                  @Ratzz

                  view()->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
                  

                  Does the trick :

                  image

                  But the list is a bit too wide and a bit too long... But it wiil be enough for now !

                  Thanks a lot

                  raven-worxR RatzzR 2 Replies Last reply
                  0
                  • pablolitoP pablolito

                    @Ratzz

                    view()->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
                    

                    Does the trick :

                    image

                    But the list is a bit too wide and a bit too long... But it wiil be enough for now !

                    Thanks a lot

                    raven-worxR Offline
                    raven-worxR Offline
                    raven-worx
                    Moderators
                    wrote on last edited by
                    #10

                    @pablolito
                    this should do the calculation you want:

                    void MyComboBox::showPopup()
                    {
                        //calculate width of all items
                        int width = 0;
                        const int iconWidth = this->iconSize().width() + 4;
                        const QFontMetrics &fontMetrics = this->fontMetrics();
                    
                        for( int i = 0; i < this->count(); ++i )
                        {
                            const int textWidth = fontMetrics.width(this->itemText(i));
                            if (this->itemIcon(i).isNull())
                                width = (qMax(width, textWidth));
                            else
                                width = (qMax(width, textWidth + iconWidth));
                        }
                    
                        QStyleOptionComboBox opt;
                        this->initStyleOption(&opt);
                        QSize tmpSize(width, 0);
                        tmpSize = this->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, tmpSize, this);
                    
                        // add width of scrollbar
                        int scrollBarWidth = 0;
                        if( QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(this->view()) )
                        {
                            QScrollBar* vScrollBar = scrollArea->verticalScrollBar();
                            vScrollBar->ensurePolished();
                    
                            QStyleOptionSlider option;
                                option.initFrom(vScrollBar);
                                option.subControls = QStyle::SC_None;
                                option.activeSubControls = QStyle::SC_None;
                                option.orientation = Qt::Vertical;
                                option.minimum = vScrollBar->minimum();;
                                option.maximum = vScrollBar->maximum();
                                option.sliderPosition = vScrollBar->sliderPosition();
                                option.sliderValue = vScrollBar->value();
                                option.singleStep = vScrollBar->singleStep();
                                option.pageStep = vScrollBar->pageStep();
                                option.upsideDown = vScrollBar->invertedAppearance();
                    
                            scrollBarWidth = vScrollBar->style()->pixelMetric( QStyle::PM_ScrollBarExtent, &option, vScrollBar );
                        }
                    
                        // set the width to the popup
                        this->view()->window()->setFixedWidth( qMax(this->width(),tmpSize.width()+scrollBarWidth) );
                    
                        QComboBox::showPopup();
                    }
                    

                    --- 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

                    pablolitoP 1 Reply Last reply
                    5
                    • pablolitoP pablolito

                      @Ratzz

                      view()->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
                      

                      Does the trick :

                      image

                      But the list is a bit too wide and a bit too long... But it wiil be enough for now !

                      Thanks a lot

                      RatzzR Offline
                      RatzzR Offline
                      Ratzz
                      wrote on last edited by
                      #11

                      @pablolito said:

                      QSizePolicy::MinimumExpanding, QSizePolicy::Preferred

                      Even i have tried in win7 for long text . does not work here .

                          item2->setText("test2 long text aha 123456789012345678901234567890");
                          ui->comboBox->view()->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);

                      --Alles ist gut.

                      1 Reply Last reply
                      0
                      • raven-worxR raven-worx

                        @pablolito
                        this should do the calculation you want:

                        void MyComboBox::showPopup()
                        {
                            //calculate width of all items
                            int width = 0;
                            const int iconWidth = this->iconSize().width() + 4;
                            const QFontMetrics &fontMetrics = this->fontMetrics();
                        
                            for( int i = 0; i < this->count(); ++i )
                            {
                                const int textWidth = fontMetrics.width(this->itemText(i));
                                if (this->itemIcon(i).isNull())
                                    width = (qMax(width, textWidth));
                                else
                                    width = (qMax(width, textWidth + iconWidth));
                            }
                        
                            QStyleOptionComboBox opt;
                            this->initStyleOption(&opt);
                            QSize tmpSize(width, 0);
                            tmpSize = this->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, tmpSize, this);
                        
                            // add width of scrollbar
                            int scrollBarWidth = 0;
                            if( QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(this->view()) )
                            {
                                QScrollBar* vScrollBar = scrollArea->verticalScrollBar();
                                vScrollBar->ensurePolished();
                        
                                QStyleOptionSlider option;
                                    option.initFrom(vScrollBar);
                                    option.subControls = QStyle::SC_None;
                                    option.activeSubControls = QStyle::SC_None;
                                    option.orientation = Qt::Vertical;
                                    option.minimum = vScrollBar->minimum();;
                                    option.maximum = vScrollBar->maximum();
                                    option.sliderPosition = vScrollBar->sliderPosition();
                                    option.sliderValue = vScrollBar->value();
                                    option.singleStep = vScrollBar->singleStep();
                                    option.pageStep = vScrollBar->pageStep();
                                    option.upsideDown = vScrollBar->invertedAppearance();
                        
                                scrollBarWidth = vScrollBar->style()->pixelMetric( QStyle::PM_ScrollBarExtent, &option, vScrollBar );
                            }
                        
                            // set the width to the popup
                            this->view()->window()->setFixedWidth( qMax(this->width(),tmpSize.width()+scrollBarWidth) );
                        
                            QComboBox::showPopup();
                        }
                        
                        pablolitoP Offline
                        pablolitoP Offline
                        pablolito
                        wrote on last edited by
                        #12

                        @raven-worx
                        Thanks a lot !

                        This does exactly what I want !

                        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