2015-07-28 5 views
5

Я пишу всплывающее меню для виджета кнопки Qt, всякий раз, когда нажимается кнопка, появляется всплывающее меню (под кнопкой).Задать позицию (справа) всплывающего меню Qt PushButton

По умолчанию всплывающее меню по умолчанию левое. Есть ли способ, чтобы всплывающее меню всплывало с правой стороны под кнопкой?

Нет установленной функции позиции ... так что я задаюсь вопросом, есть ли какой-то сложный способ сделать это?

Вот некоторый код (для всплывающего меню):

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 

Большого спасибо за какие-либо указания и рекомендации.

ответ

5

Это может быть сделано путем создания подклассов 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()); 
} 

mainwindow.cpp

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

Это выглядит следующим образом:

enter image description here

+0

Спасибо, я работаю над этим! Могу ли я спросить, почему в классе 'PopupMenu' есть' QPushButton * b'? И будет ли функция 'showEvent' вызываться каждый раз, когда я нажимаю кнопку PushupMenu? – Ryan

+0

Кроме того, я наткнулся на эти ошибки: '' popupmenu.obj: ошибка LNK2001: неразрешенный внешний символ "public: virtual struct QMetaObject const * __cdecl PopupMenu :: metaObject (void) const" 'popupmenu.obj: ошибка LNK2001: неразрешенный внешний символ" public: virtual void * __cdecl PopupMenu :: qt_metacast (символ сопз *)»' ' ' popupmenu.obj: ошибка LNK2001: неразрешенный внешний символ "общественности: виртуальный ИНТ __cdecl PopupMenu :: qt_metacall (перечисление QMetaObject :: Вызов, INT, аннулируются *)" ' I натолкнулся на подобные ошибки раньше, но я также не знаю, почему это связано с QMetaObject – Ryan

+0

@Ryan 'QPushButton * b' используется, чтобы сообщить PopupMenu, какой экземпляр кнопки он должен выровнять. yes, 'showEvent' будет вызываться каждый раз, когда нажимается кнопка. о ваших ошибках: взгляните на [этот вопрос и ответы] (http://stackoverflow.com/questions/14170770/unresolved-external-symbol-public-virtual-struct-qmetaobject-const-thiscal) –

1

Вы должны ввести eventFilter для вашего QMenu. В методе eventFilter вам необходимо рассчитать позицию, в которой будет отображаться ваше меню.

Вот вам пример:

.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; 
} 
0

Другой (имхо) более простой подход был бы:

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