19

How can I create a "drop down button" in Qt?

For a non-Qt example, see: Combination button/dropdown in office

The key point is that the widget needs an icon for the primary action, and a visually separate "pulldown arrow" to show secondary icons / actions.

Upon clicking the "pulldown arrow" for secondary options, the user should be presented with a grid of other icons to choose from. (All icons, no text.)

Does Qt have a widget that can do this?

If not, how can this be created in Qt? (I'm a new Qt user, so a Qt Designer based solution would be ideal.)

Thank you

Community
  • 1
  • 1
nonot1
  • 2,788
  • 4
  • 25
  • 41

8 Answers8

20

Actually, a QToolButton does this quite well.

http://qt-project.org/forums/viewthread/5377

It appears the OP asked this in a Qt forum and got a better answer. Adding it here for completeness.

bb121622
  • 1,036
  • 11
  • 13
11

You have to use a QToolButton. Then you may want to set an icon instead of button's text, set popupmenu property to menubuttonpopup. This is my code:

//widget.cpp:
#include "widget.h"
#include "ui_widget.h"

#include <QtGui>

Widget::~Widget()
{
    delete ui;
}

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    menu   = new QMenu(this);
    act0 = new QAction("test",this);
    act1 = new QAction("test1",this);
    act0->setObjectName("act0");
    act1->setObjectName("act1");
    menu->addAction(act0);
    menu->addAction(act1);
    ui->toolButton->setMenu(menu);
    connect(ui->toolButton,SIGNAL(clicked()),this,SLOT(slotTest()));
    connect(act0,SIGNAL(triggered()),this,SLOT(slotTest()));
    connect(act1,SIGNAL(triggered()),this,SLOT(slotTest()));
    adjustSize();
}

void Widget::slotTest()
{
    QToolButton *tbtn = qobject_cast<QToolButton*>(sender());
    QAction *act = qobject_cast<QAction*>(sender());
    if(tbtn)
    {
        qDebug() << "event raised by QToolButton: " << tbtn->objectName();
    }
    if(act)
    {
        qDebug() << "event raised by QAction: " << act->objectName();
    }
}

//widget.h:
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
class QMenu;
class QAction;
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void slotTest();
private:
    QMenu *menu;
    QAction *act0;
    QAction *act1;
    Ui::Widget *ui;
};

#endif // WIDGET_H

//widget.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>53</width>
    <height>40</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QToolButton" name="toolButton">
     <property name="text">
      <string/>
     </property>
     <property name="icon">
      <iconset>
       <normaloff>cerca.png</normaloff>cerca.png</iconset>
     </property>
     <property name="popupMode">
      <enum>QToolButton::MenuButtonPopup</enum>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>
Alberto
  • 718
  • 4
  • 20
11

You can just use setMenu() on a regular push button.

QMenu* menu = new QMenu(this);
menu->addAction(tr("Sub-action"));
ui->button->setMenu(menu);

I don't think the menu expansion is facultative though...

Lukas Kalbertodt
  • 79,749
  • 26
  • 255
  • 305
leplatrem
  • 1,005
  • 13
  • 25
  • 1
    See also https://doc.qt.io/qt-5/qtoolbutton.html#ToolButtonPopupMode-enum Setting it to QToolButton::MenuButtonPopup enables the exact behavior described in the question. – Rotsiser Mho Oct 30 '19 at 17:46
4

I created a A firefoxlooking drop down menu from a button for my previous project. Basically i subclass QPushButton and did some custom painting. Then i add a menu to that button using the function (QPushButton.setMenu(Qmenu). The attached image show what it looks like.

Dropbutton

4

A simple python based solution is using 'activated' function:

In qt designer, select a Combo-Box. Then rename it as QComboBoxName or whatever you may like to call. Then in the init function, paste this code:

self.QComboBoxName.activated.connect(self.someFunction)

def someFunction(self): #foo
    text=self.QComboBoxName.currentText()
    #do something with this text string
    if (text=='someString'): #do this 
    else : pass
Ashish Gupta
  • 185
  • 1
  • 12
  • while not exactly the answer to the question, any web search for qt dropdown will lead here. And this is the usual answer that should be given, without OP's specific icon requirements. – Finlay Beaton Nov 27 '18 at 23:09
1

I think you will want to subclass QComboBox and reimplement the needed functionality / look (with paintEvent or something) as its the widget which looks closest to what you are lookin for (I guess).

Good Luck!

snoofkin
  • 8,725
  • 14
  • 49
  • 86
0

I don't actually know if this does what you want... but try it out? http://doc.qt.io/archives/4.6/qtoolbutton.html#arrowType-prop

Christophe Weis
  • 2,518
  • 4
  • 28
  • 32
mpen
  • 272,448
  • 266
  • 850
  • 1,236
-1

Your best bet will be to make your own subclass of QAbstractButton to use. You would want to draw the regular icon in the designated portion, and your own icon in the other area. You would also need to grab the mouse press event to show the popup-menu if it is in the designated area (instead of letting the regular button-handling code take it, which would lead to a button clicked signal when the mouse was released).

Caleb Huitt - cjhuitt
  • 14,785
  • 3
  • 42
  • 49
  • Thank you. Can you recommended any tutorials? I've never sub-classed a widget. Not exactly sure how the drawing is supposed to happen. – nonot1 Apr 21 '11 at 04:16
  • @nonot1: A little late, but try http://doc.trolltech.com/latest/widgets-analogclock.html for a basic overview, and http://doc.trolltech.com/latest/widgets-calculator.html specifically overrides a type of button. They are examples rather than tutorials, but ought to help you out some. – Caleb Huitt - cjhuitt Apr 27 '11 at 21:22
  • 1
    As other answers point out, QToolButton has support built-in. Subclassing QAbstractButton is definitely not the simplest approach. – Rotsiser Mho Oct 30 '19 at 17:45