nonot1
nonot1

Reputation: 2828

Qt: Drop-down button?

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

Upvotes: 20

Views: 53966

Answers (8)

bb121622
bb121622

Reputation: 1037

Solution

A MenuButtonPopup-style QToolButton does this quite well:

# Initialises the `QToolButton`:
button = PyQt6.QtWidgets.QToolButton()

# Sets the pop-up mode to one that displays a down-arrow:
button.setPopupMode(PyQt6.QtWidgets.QToolButton.ToolButtonPopupMode.MenuButtonPopup)

# For the purpose of this example, enforces that the `DownArrow` be visible:
button.setArrowType(PyQt6.QtCore.Qt.ArrowType.DownArrow)

# Outside of UNIX-based OSes, this may be better set to `ToolButtonTextBesideIcon`:
button.setToolButtonStyle(PyQt6.QtCore.Qt.ToolButtonStyle.ToolButtonFollowStyle)

button.setText("QToolButton")
Examples

However, note that it's (unfortunately) very dependent upon your application style:

  1. Windows 7/8 (OS-Default)

    Screenshot

  2. Breeze on KDE Plasma 6.2 (DE-Default)

    Screenshot

Citation

This was originally from web.archive.org/web/20121229201850/http://qt-project.org/forums/viewthread/5377/#32102 (albeit before visiting the Internet Archive was necessary to view it).

Upvotes: 21

Ashish Gupta
Ashish Gupta

Reputation: 185

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

Upvotes: 4

leplatrem
leplatrem

Reputation: 1025

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

Upvotes: 11

mpen
mpen

Reputation: 283213

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

Upvotes: 0

Alberto
Alberto

Reputation: 728

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>

Upvotes: 12

SaKabmar_Ashna
SaKabmar_Ashna

Reputation: 144

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

Upvotes: 4

Caleb Huitt - cjhuitt
Caleb Huitt - cjhuitt

Reputation: 14941

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

Upvotes: -1

snoofkin
snoofkin

Reputation: 8895

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!

Upvotes: 1

Related Questions