QAction doesn't show QMenu - qt

I'm creating my UI from Qt Designer and it generares this code:
toolBar = new QToolBar(MainWindow);
QIcon icon;
icon.addFile(QStringLiteral(":/main"), QSize(), QIcon::Normal, QIcon::Off);
MainWindow->addToolBar(Qt::TopToolBarArea, toolBar);
actionConvert = new QAction(MainWindow);
actionConvert->setObjectName(QStringLiteral("actionConvert"));
actionConvert->setIcon(icon);
toolBar->addAction(actionConvert);
Now, back in my frame code:
QMenu *menuAdd = new QMenu (this);
menuAdd->addAction (tr("&Files..."));
menuAdd->addAction (tr("&Directory..."));
ui->actionConvert->setMenu (menuAdd);
When I run the application I can see the qaction in the toolbar even the arrow pointing down, which indicates that there is a menu, but when I click it, the menu doesn't appear...any ideas?

There does not seem to be anything wrong with your example code.
It's possible that the reason you aren't seeing the menu is that you need to press and hold the button for a few seconds in order for the menu to appear. A single click will just execute the button's normal action.
See: QToolButton::ToolButtonPopupMode.

You should add menu with menuBar() method as in my case:
void MainWindow::ueInitMenu()
{
this->ueSetCodeRegisterPlacesAction(new QAction(tr("Places"),
this));
this->ueCodeRegisterPlacesAction()->setShortcut(tr("Ctrl+P"));
this->ueCodeRegisterPlacesAction()->setStatusTip(tr("Shows places code register"));
connect(this->ueCodeRegisterPlacesAction(),
SIGNAL(triggered()),
this,
SLOT(ueSlotShowPlacesView()));
this->ueSetCodeRegisterMenu(this->menuBar()->addMenu(tr("Code register")));
this->ueCodeRegisterMenu()->addAction(this->ueCodeRegisterPlacesAction());
} // ueInitMenu
especialy the line:
this->ueSetCodeRegisterMenu(this->menuBar()->addMenu(tr("Code register")));
so in your case:
this->menuBar()->addMenu(tr("System menu");
and then add actions. Also take a look at Menus Example.

Related

QMenu - shortcut is not triggered

What is correct way to use QAction shortcuts? I have QTableView with custom context menu where beside other actions I want to have action Refresh F5:
// Popup
QAction *a;
a = mPopup.addAction(IconsManager::icon(fa::refresh), "Refresh", this, &UserPlaylistsSubWidget::refreshList, QKeySequence(Qt::Key_F5));
a->setShortcutVisibleInContextMenu(true);
First, I had to set setShortcutVisibleInContextMenu to make it visible in context menu but action is still not triggered when press F5 (QTableView is active and focused widget). Tried also different values for QAction::setShortcutContext but still no result.
Qt 5.12. Linux (KDE Neon)
Edit: Here is code which rise popup
connect(ui->list, &QWidget::customContextMenuRequested, this, &UserPlaylistsSubWidget::popUp);
void UserPlaylistsSubWidget::popUp(const QPoint &pos)
{
mPopup.popup(ui->list->viewport()->mapToGlobal(pos));
}
Figured it out. Didn't know that QTableView has own actions list and can show it in own popup with setContextMenuPolicy(Qt::ActionsContextMenu). So here is correct solution and F5 shortcut works as expected:
QAction *a = new QAction(IconsManager::icon(fa::refresh), "Refresh", ui->list);
a->setShortcut(QKeySequence(Qt::Key_F5));
a->setShortcutVisibleInContextMenu(true);
connect(a, &QAction::triggered, this, &UserPlaylistsSubWidget::refreshList);
ui->list->addAction(a);

How to programmatically close QMenu

I have pretty specific situation. I want to place a QAction into QToolbar and reach following behaviour:
Checkable QAction with icon.
Classic arrow on the right side which is used for showing menu
By pressing this arrow my QDialog should appears on screen instead of QMenu-like one
Now I'm a bit confused with implementing all this things together.
For now I've created QAction added it to toolbar and also created an empty QMenubecause I didn't get the idea of how to add the "dropdown" arrow another way.
So, I also connected my slot to QMenu aboutToShow() signal and now, I can create my dialog and exec() it just before QMenu shows. But here's the main problem appears: after I did everything with my dialog an click OK button QMenu trying to appear, but as it is empty it shows nothing and further actions become available only after I left-click somwhere to "close" this menu.
Is there any way to force QMenu not to show or can inherit from QMenu and reimplemnt its behaviour (I've tried to do such trick with exec() show() popup() methods of QMenu after subclassing from it, but none of them are being called when menu appears on the screen) ?
Here's the solution, which worked for me.
class QCustomMenu : public QMenu
{
Q_OBJECT
public:
QCustomMenu(QObject *parent = 0):QMenu(parent){};
};
In code:
QAction* myActionWithMenu = new QAction ( "ActionText", toolbar);
QCustomMenu* myMenu = new QCustomMenu(toolbar);
connect(myMenu, SIGNAL(aboutToShow()), this, SLOT(execMyMenu()));
execMyMenu() implementation:
void execMyMenu(){
m_activeMenu = (QCustomMenu*)sender(); // m_activeMenu -- private member of your head class, needs to point to active custom menu
QMyDialog* dlg = new QMyDialog();
// setup your dialog with needed information
dlg->exec();
// handle return information
m_myTimer = startTimer(10); // m_myTimer -- private member of your head(MainWindow or smth like that) class
}
Now we have to handle timerEvent and close our menu:
void MyHeadClass::timerEvent(QTimerEvent *event)
{
// Check if it is our "empty"-menu timer
if ( event->timerId()==m_myTimer )
{
m_activeMenu->close(); // closing empty menu
killTimer(m_myTimer); // deactivating timer
m_myTimer = 0; // seting timer identifier to zero
m_activeMenu = NULL; // as well as active menu pointer to NULL
}
}
It works great on every platform and does what I wanted.
Hope, this would help someone. I've spent week trying to find this solution.

close button on qDialog only closing on second click

I'm trying to generate a dialog that contains an ad-on tool that is separate from my main program, it its triggered from an action within the menus.
I've got the following code:
void MainWindow::on_actionCalibration_Tool_triggered()
{
QGridLayout *grid = new QGridLayout;
NewDialog.setLayout(grid);
NewDialog.setMinimumHeight(500);
NewDialog.setMinimumWidth(800);
QLabel *label = new QLabel;
QFont sansFont("MS Shell Dlg 2",22, QFont::Bold);
label->setText("Test");
label->setFont(sansFont);
QPushButton *okbutton = new QPushButton;
QPushButton *closebutton = new QPushButton;
okbutton->setText("Ok");
closebutton->setText("Close");
QTimer *timer = new QTimer;
connect(okbutton,SIGNAL(clicked()),this,SLOT(on_ScanpB_clicked()));
connect(closebutton,SIGNAL(clicked()),this,SLOT(CloseDialog()));
grid->addWidget(label);
grid->addWidget(okbutton);
grid->addWidget(closebutton);
NewDialog.exec();
NewDialog.show();
}
void MainWindow::CloseDialog()
{
NewDialog.close();
}
With NewDialog being defined in main window.h as a QDialog.
My issue is when I click the close button, the dialog will close for a split second then reopen, after I click the close button for a second time it closes for good.
Is there any better implementation or way around this?
Thanks
You should not call QDialog::show and QDialog::exec. Instead, pick one to call.
Use exec if you want to block user interaction with the dialog's parent while the dialog is open. The user will not be play with anything else in the application until they dismiss the dialog. This is called a modal.
Use show if you want to allow the user to work with the dialog and the rest of the application at the same time.
Usually you'd choose exec. It is easier to work with. In your case, you displayed the dialog twice by calling both functions.

QMenu exec to return on a QMenu click (instead of QAction)

I am building a menu and I would like to be able to click both on QAction and QMenu items.
When running exec, nothing happens if I click on a QMenu.
Even if I added an action to the QMenu.
Is there a way to do this?
Here is what I tried:
QMenu* menu = new QMenu( "xxx", topMenu );
QAction* action = menu->menuAction();
topMenu->addAction( action );
EDIT:
I do not know why exec() makes it different, but to walk-around it you can create subclass of QMenu to be your topMenu so that it handles mouse release event manually like this:
void CustomMenu::mouseReleaseEvent(QMouseEvent *event) {
QAction *const actionAtEvent = actionAt(event->pos());
if (actionAtEvent)
actionAtEvent->trigger();
QMenu::mouseReleaseEvent(event);
}
Original, not helpfull answer:
It might help you to use QMenu::menuAction() to get associated QAction and connect it's signals.

Qt setting text under tool button

I want to show text for the tool button icons using setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
I can see the text for actions directly added to Toolbar (Close & Save), but not for an action(Load) that is added to a QMenu in a Toolbutton. I have added this action in Qmenu to work it as a toggle with other actions(recent files).
I tried to set the text for the Toolbutton too using setText() and setWindowIconText(), but it doesn't work. This is how it looks right now.
Below is the code snippet for the same.
actionLoad = new QAction(QIcon(QString("%1/cn_open.png").arg(imageDir)),tr("Load"), this);
actionLoad->setShortcut(tr("Ctrl+L"));
actionLoad->setStatusTip(tr("Load the model"));
connect(actionLoad, SIGNAL(triggered()), this, SLOT(loadModelDlg()));
actionClose = new QAction(QIcon(QString("%1/cn_close.png").arg(imageDir)),tr("Close"), this);
actionClose->setShortcut(tr("Ctrl+X"));
actionClose->setStatusTip(tr("Close the Model"));
connect(actionClose, SIGNAL(triggered()), this, SLOT(closeModel()));
actionSave = new QAction(QIcon(QString("%1/cn_save.png").arg(imageDir)),tr("Save"), this);
actionSave->setShortcut(tr("Ctrl+S"));
actionSave->setStatusTip(tr("Save the Model"));
connect(actionSave, SIGNAL(triggered()), this, SLOT(saveModel()));
m_FileToolBar = addToolBar(tr("File"));
// Show text under the icon in toolbar
m_FileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
// Add a menu for recent file items
m_FileMenu = new QMenu();
m_FileMenu->addAction(actionLoad); // Add load button as the first item
for (int i = 0; i < MaxRecentFiles; ++i)
m_FileMenu->addAction(recentFileActions[i]);
updateRecentFileActions();
// Create a tool button. Load button and recent files will be added as a drop down menu
m_FileToolButton = new QToolButton();
m_FileToolButton->setText(tr("Load")); // Not working
m_FileToolButton->setWindowIconText(tr("Load")); // Not working
m_FileToolButton->setMenu(m_FileMenu);
m_FileToolButton->setDefaultAction(actionLoad);
// This creates a dropdown arrow to click.
m_FileToolButton->setPopupMode(QToolButton::MenuButtonPopup);
m_FileToolBar->addWidget(m_FileToolButton);
// These actions show text under the icon
m_FileToolBar->addAction(actionClose);
m_FileToolBar->addAction(actionSave);
Any help to resolve this is appreciated.
Why don't you try something like that:
QToolBar bar;
QToolButton button;
button.setPopupMode(QToolButton::MenuButtonPopup);
button.setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
QAction loadAction(QIcon(":/img/openfile"),"Load",&button);
button.addAction(&loadAction);
button.setDefaultAction(&loadAction);
QAction loadAction2("Load 2",&button);
button.addAction(&loadAction2);
bar.addWidget(&button);
bar.show();
I didn't use a QMenu as you can see above.

Resources