2013-10-07 44 views
1

在我的應用程序中,我有一個與USB Pen Drive相關的QToolButton。插入筆式驅動器時,我想顯示QToolButton並創建與筆式驅動器內容相關的上下文菜單。我有一個動態創建的不同菜單可以分配給按鈕。在QT中動態創建與工具按鈕相關的上下文菜單

我的代碼第一次運行良好,但是當我創建一個新菜單時,它不會出現。 在這最後一個版本的代碼中,當我第二次顯示按鈕時,我會看到上一個菜單(卸載是唯一存在的項目),當我點擊該項目時,它不會執行任何操作。

編輯:如果我使用QAction而不是QWidgetAction代碼工作正常。所以它似乎與QLabel中使用的QWidgetAction有關。

以下是我的代碼的簡化版本:

/* member variables */ 
QMenu *m_pqmConMenUSB; 
QLabel m_MenuItem; 

/* costructor */  
ui->tbDriveUSB->setContextMenuPolicy(Qt::CustomContextMenu); 
m_pqmConMenUSB = NULL; 
QObject::connect(ui->tbDriveUSB, SIGNAL(customContextMenuRequested(const QPoint&)),this, SLOT(showUSBCM(const QPoint&))); 
m_MenuItem.setStyleSheet("QLabel { background-color : black; color : white; }"); 
m_MenuItem.setText("Dismount"); 
QFont fonte = m_MenuItem.font(); 
fonte.setPixelSize(16); 
m_MenuItem.setFont(fonte); 
QPalette ChePalette = m_MenuItem.palette(); 
m_MenuItem.setMinimumSize(0,32); 
ChePalette.setColor(m_MenuItem.backgroundRole(), Qt::black); 
ChePalette.setColor(m_MenuItem.foregroundRole(), Qt::white); 
m_MenuItem.setPalette(ChePalette); 

/*member functions*/ 
void MainWindow::showUSBCM(const QPoint& pos) 
{ 
    // copied from an example 
    if (pos != QPoint(0,0)) { 
     // Execute context menu 
     if (m_pqmConMenUSB!=NULL) m_pqmConMenUSB->exec(pos); 
    } 
} 

void MainWindow::OnUSBMounted() 
{ 
    /* this static boolean is used to simulate a change in the menu content */ 
    static bool tryToChange = false; 
    ui->tbDriveUSB->show(); 
    m_pqmConMenUSB = new QMenu(this); 
    QWidgetAction *menuItemW = new QWidgetAction(this); 
    menuItemW->setDefaultWidget(&m_MenuItem); 
    menuItemW->setText("Dismount"); 
    connect(menuItemW,SIGNAL(triggered()), this, SLOT(DoDismount())); 
    m_pqmConMenUSB->addAction(menuItemW); 
    if (tryToChange) 
    { 
     menuItemW = new QWidgetAction(this); 
     menuItemW->setDefaultWidget(&m_MenuItem); 
     menuItemW->setText("Update"); 
     connect(menuItemW,SIGNAL(triggered()), this, SLOT(Update())); 
     m_pqmConMenUSB->addAction(menuItemW); 
    } 
    tryToChange = !tryToChange; 
    ui->tbDriveUSB->setMenu(m_pqmConMenUSB); 
} 

void MainWindow::OnUSBDismounted() 
{ 
    ui->tbDriveUSB->hide(); 

    /* the first version of the code tries to destroy the menu with the following code, but it doesn't work 
    /*ui->tbDriveUSB->setMenu(NULL); 
    QAction *pAction; 
    foreach (pAction, m_pqmConMenUSB->actions()) 
     pAction->disconnect(this); 
     delete(m_pqmConMenUSB); 
    m_pqmConMenUSB = NULL;*/ 

}

回答

1

正如我昨天提到的,問題與QLabels有關。在我的代碼中,我使用了兩個類型爲QLabel的成員變量。 QLabels不是指針。 當我刪除操作時,QLabels無法再顯示它們。我想這與removeAction(d->menuAction);函數有關,它破壞與QWidgetAction關聯的QWidget。該函數在調用ui->tbDriveUSB->setMenu(NULL);時被調用。 我選擇使用QLabel僅用於樣式表和大小,但可以在菜單中設置該屬性。這對我來說已經足夠了。 我認爲,在創建QWidgetAction時創建新的QLabel,並在刪除QWidgetAction時將其刪除,可以使之成爲以前的代碼。我沒有測試過它。

爲了完成答案,以下是我當前的代碼行之有效

/* member variable */ 
QMenu *m_pqmConMenUSB; 

/* constructor */ 
ui->tbDriveUSB->setContextMenuPolicy(Qt::CustomContextMenu); 
QObject::connect(ui->tbDriveUSB, SIGNAL(customContextMenuRequested(const QPoint&)),this, SLOT(showUSBCM(const QPoint&))); 
m_pqmConMenUSB = new QMenu(this); 
QFont fonte = m_pqmConMenUSB->font(); 
fonte.setPixelSize(16); 
m_pqmConMenUSB->setFont(fonte); 
m_pqmConMenUSB->setStyleSheet("QMenu { background-color : black; color : white; }"); 
m_pqmConMenUSB->setMinimumSize(0,32); 

/*member functions*/ 
void MainWindow::showUSBCM(const QPoint& pos) 
{ 
    if (pos != QPoint(0,0)) 
    { 
     // Execute context menu 
     if (m_pqmConMenUSB!=NULL) m_pqmConMenUSB->exec(pos); 
    } 
} 

void MainWindow::OnUSBMounted() 
{ 
    static bool tryToChange = true; 
    ui->tbDriveUSB->show(); 
    QAction *menuItem = new QAction("Dismount",this); 
    connect(menuItem,SIGNAL(triggered()), this, SLOT(DoDismount())); 
    m_pqmConMenUSB->addAction(menuItem); 
    if (tryToChange) 
    { 
     QAction *menuItem2 = new QAction("upDate",this); 
     connect(menuItem2,SIGNAL(triggered()), this, SLOT(Update())); 
     m_pqmConMenUSB->addAction(menuItem2); 
    } 
    tryToChange = !tryToChange; 
    ui->tbDriveUSB->setMenu(m_pqmConMenUSB); 
} 

void MainWindow::OnUSBDismounted() 
{ 
    printf("SEI UNO SMONTATO\n\r"); 
    ui->tbDriveUSB->setMenu(NULL); 
    QAction *pAction; 
    foreach (pAction, m_pqmConMenUSB->actions()) 
    { 
     pAction->disconnect(this); // receiver 
     delete pAction; 
    } 
    ui->tbDriveUSB->hide(); 
    m_pqmConMenUSB->clear(); 
} 
2

一個有用的圖案動態填充與QToolButton相關聯的菜單被首先創建菜單,並將它附加到按鈕,但不要填充它。然後將一個插槽連接到QMenu::aboutToShow()信號。在插槽實現中,清除菜單的內容並根據需要爲應用程序的當前狀態填充它。

+0

我會盡力實現它以這種方式。現在我改變了代碼,始終保持創建的菜單(我不調用QMenu的刪除),調用清除菜單,然後附加操作,但行爲是相同的。 當我調用exec時,菜單包含操作但無法顯示。 –

+0

默認情況下,'QToolButton :: popupMode'被設置爲'DelayedPopup',這意味着在鼠標按下一會之後顯示菜單。嘗試將此屬性更改爲「InstantPopup」。此外,您不必擔心自定義上下文菜單策略或showUSBCM()方法,因爲「QToolButton」將自行處理菜單的顯示。 – Jason

+0

謝謝,我現在需要InstantPopup屬性 –