Reputation: 2418
In my project, I have a QMenu with a submenu item. The submenu has a lot of items so it's height is relatively large.
I want to vertically center the submenu relative to the item that executed the submenu.
I have already subclassed the submenu I want to reposition and tried changing the geometry on "aboutToShow" just to test things, but this has no effect:
class MySubMenu : public QMenu
{
Q_OBJECT
public:
QuickMod();
~QuickMod();
private slots:
void centerMenu();
};
MySubMenu::MySubMenu()
{
connect(this, SIGNAL(aboutToShow()), this, SLOT(centerMenu()));
}
MySubMenu::~MySubMenu()
{
}
void MySubMenu::centerMenu()
{
qDebug() << x() << y() << width() << height();
setGeometry(x(), y()-(height()/2), width(), height());
}
Here is an image I quickly MS Painted that I hope visually explains what I'm trying to achieve: (Before and After)
Thanks for your time!
Upvotes: 1
Views: 1371
Reputation: 243897
aboutToShow
is emited before the geometry is updated so the changes are overwritten later. The solution is to change the position an instant after they are displayed, for this we can use a QTimer
with a small time.
Example:
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QTimer>
class CenterMenu: public QMenu{
Q_OBJECT
public:
CenterMenu(QWidget *parent = Q_NULLPTR):QMenu{parent}{
connect(this, &CenterMenu::aboutToShow, this, &CenterMenu::centerMenu);
}
CenterMenu(const QString &title, QWidget *parent = Q_NULLPTR): QMenu{title, parent}{
connect(this, &CenterMenu::aboutToShow, this, &CenterMenu::centerMenu);
}
private slots:
void centerMenu(){
QTimer::singleShot(0, [this](){
move(pos() + QPoint(0, -height()/2));
});
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow w;
auto fileMenu = new QMenu("Menu1");
w.menuBar()->addMenu(fileMenu);
fileMenu->addAction("action1");
fileMenu->addAction("action2");
auto children_menu = new CenterMenu("children menu");
children_menu->addAction("action1");
children_menu->addAction("action2");
children_menu->addAction("action3");
children_menu->addAction("action4");
children_menu->addAction("action5");
children_menu->addAction("action6");
fileMenu->addMenu(children_menu);
w.show();
return a.exec();
}
#include "main.moc"
Upvotes: 1