【问题标题】:Set position (to right) of Qt QPushButton popup menu设置 Qt QPushButton 弹出菜单的位置(向右)
【发布时间】:2015-07-28 06:14:46
【问题描述】:

我正在为 Qt 按钮小部件编写弹出菜单。每当单击按钮时,都会弹出一个菜单(在按钮下方)。

弹出菜单默认在左侧下方。

有什么方法可以让弹出菜单在右侧按钮下方弹出?

没有设置位置功能,不知道有没有什么复杂的方法呢?

这是一些代码(用于弹出菜单):

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

【问题讨论】:

    标签: c++ qt popup qpushbutton qmenu


    【解决方案1】:

    这可以通过继承 QMenu 并将弹出菜单移动到您想要在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());
    }
    

    ma​​inwindow.cpp

    ...
    PopupMenu* menu = new PopupMenu(ui->pushButton, this);
    ...
    ui->pushButton->setMenu(menu);
    

    看起来像这样:

    【讨论】:

    • 谢谢,我正在努力!请问PopupMenu类为什么有QPushButton* b?每次单击 PopupMenu 的按钮时都会调用 showEvent 函数吗?
    • 另外,我遇​​到了这些错误:popupmenu.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __cdecl PopupMenu::metaObject(void)const " `popupmenu.obj : error LNK2001: unresolved external symbol "public: virtual void * __cdecl PopupMenu::qt_metacast(char const *)" popupmenu.obj : error LNK2001: unresolved external symbol "public: virtual int __cdecl PopupMenu::qt_metacall(enum QMetaObject::Call,int,void * *)" 我以前遇到过这些错误,但我也不知道为什么它与 QMetaObject 有关
    • @Ryan QPushButton* b 用于告诉 PopupMenu 它应该与哪个按钮实例对齐。是的,每次单击按钮时都会调用showEvent。关于你的错误:看看this SO question and answers
    • 感谢您的链接!我尝试将.h 添加回cmakelist 以生成moc 将解决此LNK2001(受其中一个ans 的启发。)
    【解决方案2】:

    您应该为您的QMenu 实现eventFilter。在eventFilter方法中,你需要计算你的菜单会显示的位置。

    这里有一个例子:

    .pro

    TEMPLATE = app
    
    QT     += widgets
    SOURCES += main.cpp \
               dialog.cpp
    
    HEADERS += dialog.h
    
    FORMS   += dialog.ui
    

    ma​​in.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;
    }
    

    【讨论】:

      【解决方案3】:

      另一种(恕我直言)更简单的方法是:

      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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多