2013-10-07 1 views
1

내 응용 프로그램에는 USB 펜 드라이브와 관련된 QToolButton이 있습니다. 펜 드라이브를 삽입하면 QToolButton을 표시하고 펜 드라이브의 내용과 관련된 상황에 맞는 메뉴를 만들고 싶습니다. 다른 메뉴가 동적으로 만들어져 Button에 할당되었습니다.도구 상자와 연결된 QT에서 상황에 맞는 메뉴를 동적으로 생성합니다.

내 코드는 처음에는 잘 작동하지만 새 메뉴를 만들면 나타나지 않습니다. 이 코드의 마지막 버전에서는 두 번째 버튼을 표시 할 때 이전 메뉴가 나타납니다 (Dismount가 유일한 항목 임). 항목을 클릭하면 아무 것도하지 않습니다.

편집 : QWidgetAction 대신 QAction을 사용하면 코드가 정상적으로 작동합니다. 그래서 그것의 내부에서 사용되는 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 유형의 두 멤버 변수를 사용했습니다. QLabel은 포인터가 아닙니다. 조치를 삭제하면 QLabel이 조치를 삭제할 수 없습니다. 나는 그것이 QWidgetAction에 연결된 QWidget을 파괴하는 removeAction(d->menuAction); 함수와 관련이 있다고 가정합니다. 이 함수는 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 속성이 필요합니다. –

관련 문제