在我的应用程序中,我有一个与USB Pen Drive相关的QToolButton。当插入Pen驱动器时,我想显示QToolButton并创建一个与笔式驱动器内容相关的上下文菜单。我有一个动态创建的不同菜单分配给Button。
我的代码第一次运行良好,但是当我创建一个新菜单时,它不会出现。 在最后一个版本的代码中,当我第二次显示按钮时,我得到上一个菜单(Dismount是唯一存在的项目),当我点击该项目时,它没有做任何事情。
编辑:如果我使用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;*/
}
答案 0 :(得分:2)
动态填充与QToolButton
关联的菜单的有用模式是首先创建菜单并将其附加到按钮,但不填充它。然后将插槽连接到QMenu::aboutToShow()
信号。在插槽实现中,清除菜单的内容并根据需要填充应用程序的当前状态。
答案 1 :(得分:1)
正如我昨天提到的,问题与QLabels
有关。在我的代码中,我使用了QLabel
类型的两个成员变量。 QLabels不是指针。
当我删除动作时,QLabel无法再显示它们。我认为它与removeAction(d->menuAction);
函数有关,该函数会销毁与QWidget
相关联的QWidgetAction
。调用ui->tbDriveUSB->setMenu(NULL);
时调用该函数。
我选择仅将QLabel
用于样式表和大小,但可以在菜单中设置该属性。这对我来说已经足够了。
我认为,在创建QLabel
时创建新QWidgetAction
并在删除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();
}