How to put pushbutton inside the QMenu or QAction control? - qt

I need to put a QPushButton inside a QMenu. Is it possible and, if so, then how?
I want to achieve something like this:

QWidgetAction is what you are looking for. This is what is on qt docs
The QWidgetAction class extends QAction by an interface for inserting custom widgets into action based containers
So basically it gives a custom UI to QAction according to what QWidget you pass to it.
I have used QWidgetAction to show checkbox as QMenu items.
QCheckBox *chkBox = new QCheckBox(menu);
chkBox ->setText("MyCheckBox");
QWidgetAction *chkBoxAction= new QWidgetAction(menu);
chkBoxAction->setDefaultWidget(chkBox);
menu->addAction(chkBoxAction);
You can then handle signals from checkbox accordingly.

If you only want a menu item to have a state, you may use Checkable property of QAction:
rotateAct = new QAction(QIcon(":/images/Mouse/Rotate.png"), tr("&Rotate"), this);
rotateAct->setCheckable(true);

Related

Assigning actions to QMenu items

I have created a Qt project in which I'm using a widget and it does not support any menu in the designer's class, so it should be done programmatically. I succeeded in creating the menu and adding the items but I'm struggling in assigning any action for the menu items...
That's what I've done so far:
QMenuBar* menuBar = new QMenuBar();
QMenu *fileMenu = new QMenu("File");
menuBar->addMenu(fileMenu);
fileMenu->addAction("Save");
fileMenu->addAction("Exit");
QAction* newAct = new QAction(tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Exit"));
connect(newAct, &QAction::triggered, this, &MainWindow::on_action_triggered);
this->layout()->setMenuBar(menuBar);
But no action is triggered when I press The Exit item
addAction creates QAction and returns pointer to it, you dont need to create it explicitly, but when you do you must add item to menu with addAction, setting parent is not enough fileMenu->addAction(newAct);.

How to add custom QWidget to the QMenubar as action which can be toggled?

I have an Widget class as a QtPlugin. In my main application i want to load this widget and add to menubar as toggledaction, so that later if i close the widget i can open it via the Menu bar. How can this be achieved.
As this is not a docketwidget i cannot use the following:
ui->menuPlugins->addAction(dockedWidget->toggleViewAction());
I have tried something like this:
void MainWindow::addToPluginsMenu(QWidget *const widget) {
ui->menuPlugins->setEnabled(true);
QWidgetAction *ac = new QWidgetAction(this);
ui->menuPlugins->addAction(ac);
}
An action is added but it is empty and cannot be toggled. Could anyone provide me a solution?
Thank you
In order to add toggled actions and keep them visible after an action is toggled.
Use the setDefaultWidget function
For example:
// Create menu
QMenu * poMainMenu = new QMenu(this);
// toggled widget
QCheckBox * poCbTest = new QCheckBox("toggle",this);
// set the toggle widget as menu action
QWidgetAction *ac = new QWidgetAction(this);
ac->setDefaultWidget(poCbTest);
// add the action to the menu
poMainMenu->addAction(ac);

How To Create Tri-state Actions on Menus Using Qt

I have a situation where I need a tri-state checkable action on a QMenu, and the QAction class appears to only support on or off, unless I'm overlooking something obvious. The situation I have is a context menu where multiple objects are selected, but may have different states for a given boolean condition (i.e. for a given property, some objects have a true value and some false). I can leave the action unchecked when there's a mix of values, but I feel that's misleading to the user.
I'm using Qt 5.5.1 and very experienced with Qt, but not seeing a way to achieve what I want in this instance.
There is no direct way to do it from a QAction, but it is possible to subclass the QWidgetAction and create an action that contains a QCheckBox widget.
class CheckBoxAction : public QWidgetAction {
public:
CheckBoxAction (const QString &text) : QWidgetAction(Q_NULLPTR) {
QHBoxLayout *_layout = new QHBoxLayout(Q_NULLPTR);
QWidget *_widget = new QWidget(Q_NULLPTR);
QLabel *_label = new QLabel(text);
mCheckbox = new QCheckBox(Q_NULLPTR);
_label->setAlignment(Qt::AlignLeft);
_layout->addWidget(mCheckbox);
_layout->addWidget(_label);
_layout->addStretch();
_widget->setLayout(_layout);
setDefaultWidget(_widget);
}
QCheckBox *checkbox() {
return mCheckbox;
}
private:
QCheckBox *mCheckbox;
};
Simply use the class to then add to your menu; for instance:
CheckBoxAction *checkAction = new CheckBoxAction(QStringLiteral("My Action"));
checkAction->checkbox()->setCheckState(Qt::PartiallyChecked);
menu->addAction(checkAction);
You can use the checkbox() method in order to connect to signals when it changes; or change the checkbox state. Hope this helps.

Can I decide where a Qaction is added to a Qmenubar

I need to add a QAction directly into a QMenuBar (not an QAction inside a QMenu but a QAction directly in the QMenuBar) I am able to do this with the following command.
ui->menuBar->addAction("VFTP",this, SLOT(VFTPmenuTrigger()) );
My only problem is that when I add it, it is appended to the end of the menu bar that I have built in Qt designer. I would like to be able to put it somewhere in the middle. Seems the only way I could do this is if I generate the menu bar by coding it only. Is there a way to build most of my menuBar in Qt Designer and then add that Qaction in the menu bar where I want? I hope I am clear and I added the QAction programmatically because it is not possible to do so with Qt (I know it sounds countintuitive to put a QAction directly in the menu bar but this is what the customer wants)
If you look at QMenuBar code you'll that it does this:
QAction *QMenuBar::addAction(const QString &text, const QObject *receiver, const char* member)
{
QAction *ret = new QAction(text, this);
QObject::connect(ret, SIGNAL(triggered(bool)), receiver, member);
addAction(ret);
return ret;
}
which basically uses QWidget::addAction(). So it stands to reason that you can use QWidget::insertAction() yourself to do the same thing. insertAction() lets you specify before what QAction you want to add.

On Qt widgets like DoubleSpinBox or ComboBox, how do i have custom right click menu

I have a few combo-boxes and double spin boxes on my Qt Dialog. Now I need a "ResetToDefault" item on a menu that comes up when you right click on the widget (spin box or combo box).
How do i get it. Is there some way I can have a custom menu that comes up on right click or Is there a way i can add items to the menu that comes on right click.
First, for Qt4, the simplest way is to create an action to reset the data, and add it the the widget using the addAction method (or use the designer). Then, set the contextMenuPolicy attribute to Qt::ActionsContextMenu. The context menu will appear and the action will be triggered.
Code example:
QAction *reset_act = new QAction("Reset to default");
mywidget->addAction(reset_act);
mywidget->setContextMenuPolicy(Qt::ActionsContextMenu);
// here connect the 'triggered' signal to some slot
For Qt3, you might have to intercept the context menu event, and thus inherit the QSpinBox and others. Or maybe you can intercept the context menu event from the main window, detect if it occurred above the widget supposed to have a context menu (using the QWidget::childAt method) and show it there. But you'll have to test.
For Qt4, you can do this for an editable QComboBox by using your own QLineEdit. Create a derived QLineEdit class which implements the contextMenuEvent
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
MyLineEdit(QWidget* parent = 0) : QLineEdit(parent){}
void contextMenuEvent(QContextMenuEvent *event)
{
QPointer<QMenu> menu = createStandardContextMenu();
//add your actions here
menu->exec(event->globalPos());
delete menu;
}
};
Then, use the setLineEdit function of QComboBox to set the line edit
MyLineEdit* edit = new MyLineEdit();
comboBox->setLineEdit(edit);
The combo box will now use your line edit class. The createStandardContextMenu function creates the normal context menu and you can add any new actions to it that you like in the contextMenuEvent handler before it is shown.
If the QComboBox is not editable then it doesn't have a default context menu so using the Qt::ActionsContextMenu method is much simpler.
QAbstractSpinBox also has a setLineEdit function so you can use a similar technique. Although, for some reason the setLineEdit function is protected on QAbstractSpinBox but public on QLineEdit.

Resources