I am writing a popup menu for a Qt push button widget. Whenever the push button is clicked, a menu pops up (below the push button).
The popup menu is left-sided below by default.
Are there any ways to make the popup menu to pop up on the right side below the push button?
There is no set position function, so I wonder if there is some sophisticated way of doing it?
Here is some code (for popup menu):
QMenu *menuMode = new QMenu(this);
min = menu ->addAction("In");
mout = menu ->addAction("out");
ui->pushButtonMode->setMenu(menuMode); //I am writing in MainWindow, that's there is ui
This can be done by subclassing QMenu and moving the popup menu where you want to have it in showEvent
:
popupmenu.h
#ifndef POPUPMENU_H
#define POPUPMENU_H
#include <QMenu>
class QPushButton;
class QWidget;
class PopupMenu : public QMenu
{
Q_OBJECT
public:
explicit PopupMenu(QPushButton* button, QWidget* parent = 0);
void showEvent(QShowEvent* event);
private:
QPushButton* b;
};
#endif // POPUPMENU_H
popupmenu.cpp
#include "popupmenu.h"
#include <QPushButton>
PopupMenu::PopupMenu(QPushButton* button, QWidget* parent) : QMenu(parent), b(button)
{
}
void PopupMenu::showEvent(QShowEvent* event)
{
QPoint p = this->pos();
QRect geo = b->geometry();
this->move(p.x()+geo.width()-this->geometry().width(), p.y());
}
mainwindow.cpp
...
PopupMenu* menu = new PopupMenu(ui->pushButton, this);
...
ui->pushButton->setMenu(menu);
It looks like this:
You should implement an eventFilter
for your QMenu
. In the eventFilter
method, you need to calculate the position where your menu will be shown.
Here you have an example:
.pro
TEMPLATE = app
QT += widgets
SOURCES += main.cpp \
dialog.cpp
HEADERS += dialog.h
FORMS += dialog.ui
main.cpp
#include <QtWidgets/QApplication>
#include "dialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog dia;
return dia.exec();
}
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QtWidgets/QDialog>
#include <QMenu>
#include "ui_dialog.h"
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog();
protected:
bool eventFilter(QObject * obj, QEvent *event);
private:
QMenu *menu;
Ui::Dialog m_ui;
};
#endif
dialog.cpp
#include "dialog.h"
Dialog::Dialog()
{
m_ui.setupUi(this);
menu = new QMenu("menu", this);
menu->installEventFilter(this);
QAction *action = new QAction("action#1", this);
menu->addAction(action);
m_ui.pushButton->setMenu(menu);
}
bool Dialog::eventFilter(QObject * obj, QEvent *event)
{
if (event->type() == QEvent::Show && obj == m_ui.pushButton->menu())
{
int menu_x_pos = m_ui.pushButton->menu()->pos().x();
int menu_width = m_ui.pushButton->menu()->size().width();
int button_width = m_ui.pushButton->size().width();
QPoint pos = QPoint(menu_x_pos - menu_width + button_width,
m_ui.pushButton->menu()->pos().y());
m_ui.pushButton->menu()->move(pos);
return true;
}
return false;
}
Another (imho) simpler approach would be:
void MainFrame::Slot_ShowMenu()
{
auto pMenu = new QMenu(this);
connect(pMenu, &QMenu::aboutToHide, pMenu, &QMenu::deleteLater);
...
// Retrieve a valid width of the menu. (It's not the same as using "pMenu->width()"!)
int menuWidth = pMenu->sizeHint().width();
int x = mUI.myQPushButton->width() - menuWidth;
int y = mUI.myQPushButton->height();
QPoint pos(mUI.myQPushButton->mapToGlobal(QPoint(x, y)));
pMenu->popup(pos);
}
来源:https://stackoverflow.com/questions/31668623/set-position-to-right-of-qt-qpushbutton-popup-menu