2013-10-07 3 views
1

В моем приложении у меня есть QToolButton, связанный с наличием USB Pen Drive. Когда диск Pen вставлен, я хотел бы показать QToolButton и создать контекстное меню, связанное с содержимым ручного накопителя. У меня есть другое меню, динамически созданное для назначения Button.Динамическое создание контекстного меню в QT, связанное с панелью инструментов

Мой код работает хорошо в первый раз, но когда я создаю новое меню, он не появляется. В этой последней версии кода, когда я показываю кнопку во второй раз, я получаю предыдущее меню (Dismount - это единственный предмет), и когда я нажимаю на элемент, он ничего не делает.

EDIT: Если я использую QAction вместо QWidgetAction, код работает нормально. Таким образом, кажется, что-то связано с QWidgetAction QLabel, используемым внутри него.

Ниже представлена ​​упрощенная версия моего кода:

/* 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);, которая разрушает 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(); 
} 
2

Полезный шаблон для динамического заполнения меню, связанное с QToolButton будет сначала создать меню и прикрепить его к кнопке , но не заполняют его. Затем подключите слот к сигналу QMenu::aboutToShow(). В реализации слота очистите содержимое меню и заполните его по мере необходимости для текущего состояния приложения.

+0

Я попытаюсь реализовать его таким образом. Теперь я изменил код, чтобы всегда сохранять созданное меню (я не вызываю удаление QMenu), вызывается из меню и затем присоединяет действие, но поведение такое же. когда я вызываю exec меню contais действий, но он не может показать. –

+0

По умолчанию для 'QToolButton :: popupMode' установлено значение' DelayedPopup', что означает, что меню отображается после небольшого удержания мыши. Попробуйте изменить это свойство на 'InstantPopup'. Кроме того, вам не нужно беспокоиться о политике пользовательского контекстного меню или методе showUSBCM(), поскольку 'QToolButton' будет обрабатывать отображение меню самостоятельно. – Jason

+0

Спасибо, мне нужно свойство InstantPopup –

Смежные вопросы