2

在我的应用程序中,我有一个与 USB 笔驱动器存在相关的 QToolButton。当插入笔式驱动器时,我想显示 QToolButton 并创建一个与笔式驱动器内容相关联的上下文菜单。我有一个动态创建的不同菜单分配给按钮。

我的代码第一次运行良好,但是当我创建一个新菜单时它没有出现。在最后一个版本的代码中,当我第二次显示按钮时,我得到了上一个菜单(卸载是唯一存在的项目),当我单击该项目时它什么也不做。

编辑:如果我使用 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;*/

}

4

2 回答 2

3

动态填充与 a 关联的菜单的一个有用模式QToolButton是首先创建菜单并将其附加到按钮,但不填充它。然后将插槽连接到QMenu::aboutToShow()信号。在插槽实现中,清除菜单的内容并根据应用程序当前状态的需要填充它。

于 2013-10-08T14:19:51.620 回答
1

正如我昨天提到的,问题与QLabels. 在我的代码中,我使用了两个类型的成员变量QLabel。QLabels 不是指针。当我删除操作时,QLabels 无法再次显示它们。我想它与removeAction(d->menuAction);破坏QWidgetQWidgetAction. 调用时调用了该函数ui->tbDriveUSB->setMenu(NULL);。我选择QLabel只使用样式表和大小,但可以在菜单中设置该属性。这对我来说已经足够了。我认为,在创建QLabelQWidgetAction创建一个新的并在删除时删除它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();
}
于 2013-10-09T07:58:46.493 回答