2015-07-28 27 views
5

Sto scrivendo un menu a comparsa per un widget pulsante Qt, ogni volta che si fa clic sul pulsante, un menu a comparsa (sotto il pulsante).Impostare la posizione (a destra) del menu a comparsa Qt PushButton

Il menu di scelta rapida è di lato sinistro di seguito per impostazione predefinita. Ci sono modi per aprire il menu a comparsa sul lato destro sotto il pulsante?

Non esiste una funzione di posizione impostata ... quindi mi chiedo se esiste un modo sofisticato per farlo?

Ecco alcuni codice (per il menu a comparsa):

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 

La ringrazio molto per qualsiasi orientamento e consulenza.

risposta

5

Questo può essere fatto da sottoclassi QMenu e spostando il menu a comparsa in cui si desidera avere 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); 

Ecco come si presenta:

enter image description here

+0

Grazie, ci sto lavorando! Posso chiedere perché c'è 'QPushButton * b' nella classe' PopupMenu'? Ed è la funzione 'showEvent' che verrà chiamata ogni volta che clicco il pulsante per il PopupMenu? – Ryan

+0

Inoltre, mi sono imbattuto in questi errori: '' popupmenu.obj: errore LNK2001: simbolo esterno non risolto "public: virtual struct QMetaObject const * __cdecl PopupMenu :: metaObject (void) const" 'popupmenu.obj: errore LNK2001: simbolo esterno non risolto" public: virtual void * __cdecl PopupMenu :: qt_metacast (const char *)"' '' popupmenu.obj: errore LNK2001: simbolo esterno "public: virtual int __cdecl PopupMenu :: qt_metacall (enum QMetaObject :: chiamata, int, void * *)" ' I mi sono imbattuto in errori di questo tipo, ma non so perché si riferisca a QMetaObject – Ryan

+0

@Ryan 'QPushButton * b' è usato per dire al PopupMenu a quale istanza del pulsante deve essere allineato. sì, 'showEvent' verrà chiamato ogni volta che si fa clic sul pulsante. sui tuoi errori: dai un'occhiata a [questa domanda e risposta SO] (http://stackoverflow.com/questions/14170770/unresolved-external-symbol-public-virtual-struct-qmetaobject-const-thiscal) –

1

È necessario implementare un eventFilter per il proprio QMenu. Nel metodo eventFilter, è necessario calcolare la posizione in cui verrà visualizzato il menu.

Ecco un esempio:

.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

Altro (imho) approccio più semplice sarebbe:

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