Reputation: 2828
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
Reputation: 1037
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")
However, note that it's (unfortunately) very dependent upon your application style:
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
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
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
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
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
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.
Upvotes: 4
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
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