qaction - Qt에서 메뉴의 동작을 반복하는 방법은 무엇입니까?




qt5 qmenu (3)

나는 QMenuBar의 항목을 자동으로 (표시 또는 팝업) 열어야하는 프로젝트에서 작업하고 있습니다.

다음 메뉴 막대가 있다고 가정 해 보겠습니다.

 File     Edit      Help
   -op1     -op1      -op1
   -op2     -op2      -op2

동작을 설정하려면 (해당 동작과 관련된 메뉴 표시) 다음을 사용합니다.

menuBar->setActiveAction(mymenuactionpointer);

내가 아는 한, 다음 중 하나를 사용하여 QMenuBar의 요소에 대한 포인터 목록을 얻을 수 있습니다.

QMenuBar::actions();

또는

QList<Object*> lst1 = QMenuBar::findChildren<QObject*>();

QList<Object*> lst2 = QMenuBar::findChildren<QAction*>();

QMenuBar::findChildren<QAction*>() 또는 MenuBar::actions() 를 사용하면 menubar에서 메뉴 목록을 얻었습니다. 내 QMenuBar에서 "File, Edit, Help" 를 얻었습니다. 이 경우 QList는 3입니다.

QMenuBar::findChildren<QObject*>() 를 사용하면 메뉴 모음에있는 올바른 항목 수 인 크기가 6 인 QObject 목록을 얻었습니다. 그러나 QAction *으로 캐스팅을 시도했습니다.

QAction *a = (QAction *)lst1.at(0);
QAction *a = qobject_cast<QAction*>(lst1.at(0));
QAction *a = dynamic_cast<QAction*>(lst1.at(0));

이 모든 경우에 a 는 NULL이 아니지만 작업 이름 QAction::title() 을 얻으려고하면 항상 세그먼트 오류가 발생합니다.

나는 검색 QAction::menu() menubar 액션 목록을 얻은 후에 항목이 QMenu인지 알기 위해 QAction::menu() (항목이 메뉴 인 경우 올바른 QMenu 포인터를 반환 함 QAction::menu() 요청할 수 있음을 알았습니다. if 예, 해당 메뉴의 작업 목록을 반복하여 반복 할 수 있으며 계속 반복 할 수 있습니다. 그러나 이것은 나를 위해 작동하지 않습니다.

QList<Object*> lst2 = QMenuBar::findChildren<QAction*>();

각 요소 "파일, 도움말 편집" QAction::menu() 는 유효한 메뉴 포인터를 반환하므로 각 메뉴의 동작 목록을 얻을 수 있지만이 기능은 전혀 작동하지 않습니다.

시간과 도움에 정말 감사드립니다.이 질문이 더 많은 사람들을 돕기를 바랍니다. 나는이 일로 정말 어려움을 겪고있다.

미리 감사드립니다.


qobject_cast가 실패하는 이유는 부모로 QMenuBar가있는 QAction이 세 개 뿐이 기 때문입니다. 나머지 3 개는 다른 QObject (내 생각 엔 3 개의 QMenus 임)이므로 캐스트가 실패합니다. 그 메뉴와 관련된 QActions는 루트 QMenuBar가 아닌 해당 메뉴 아래에 있습니다. QMenus를 반복적으로 반복하여 QActions의 마스터 목록을 만들 수없는 이유를 알 수 없습니다.

상위 메뉴를 트리거하지 않을 수도있는 알려진 메뉴를 사용한 경우 UI 정의에서 QAction 포인터를 사용할 있습니다. 테스트를 자동화하려는 경우 원하는 QAction의 trigger ()가 필요한만큼 자세하게 설명됩니다. 사용자 작업에 대한 응답으로 작업을 수행하려는 경우 툴바를 수정하면 포커스를 잃지 않으므로 상황에 맞는 피드백 도구로 사용할 수 있습니다. 실제로 성취하고자하는 것에 대한 자세한 내용이 도움이 될 것입니다.


아래는 메뉴 막대의 모든 메뉴 항목을 반복하는 방법입니다. 또한 여기에있는 모든 메뉴를 찾아서 여기에서 재귀 호출을 할 필요가 없습니다.

// assuming you have a private QActionGroup* actions; defined in the header..
// ...and a slot named 'onAction(QAction*)' as well... this should work:
QList<QMenu*> lst;
lst = ui->menuBar->findChildren<QMenu*>();
actions = new QActionGroup(this);
foreach (QMenu* m, lst)
{
    foreach (QAction* a, m->actions())
    {
        actions->addAction(a);
    }
}
connect(actions,SIGNAL(triggered(QAction*)),this,SLOT(onAction(QAction*)));

보시다시피, 당신은 마스터 슬롯을 연결하여 액션이 발생할 수있는 다양한 이벤트를 처리 할 수 ​​있습니다. (여기서 방아쇠를 당긴 것처럼 보이지만 아이디어를 얻을 수 있습니다.) 희망이 .. 누군가 .. .. 도움이 Logged

Notes 나는 QActionGroup을 반복적으로 사용할 수있는 목록을 사용하는 것을 목적으로 사용했지만, 그 이후로 라디오 그룹을 다루지 않는다면 정말로 사용해서는 안됩니다. 둘째, 모든 항목을 처리하는 단일 메서드로 링크 할 계획이므로 작업을 원할 경우 QMenu의 트리거 / 호버링 신호를 사용하거나 메뉴가 팝업 될시기를 알아야 할 경우에는 QMenuBar의 aboutToShow () 신호. 슬롯에 QAction *이 전달 된 이후로 신호에서 필요한 것을 수행 할 수 없다는 이유 (나에게 어쨌든)를 생각할 수 없습니다. 그러나 만약 당신이 그것을 반드시해야한다면, 위에서 설명한대로 할 수 있습니다. QActionGroup을 사용하기를 원하지 않을 수도 있습니다. 왜냐하면 라디오 그룹핑은 그것이 설계된 것이기 때문입니다. (그룹에 '확인 가능한'항목을 추가하지 않으면이 문제를 해결할 수 있습니다.


QMenu 를 열거하는 올바른 방법은 actions() 함수를 사용하는 것입니다.하지만 catch가 있습니다. 일부 작업은 하위 메뉴이며 재귀 적으로 반복해야합니다. 사실, 각 QMenuQAction 과 연관되어 있으며, 둘 다 서로에 대한 포인터를 보유합니다. QMenu::menuAction()QAction::menu() .

각 QMenu가 QAction과 연관되어 있음을 이해하는 것이 중요합니다. 따라서 알맞은 구현은 다음과 같습니다.

void enumerateMenu(QMenu *menu)
{
    foreach (QAction *action, menu->actions()) {
        if (action->isSeparator()) {
            qDebug("this action is a separator");
        } else if (action->menu()) {
            qDebug("action: %s", qUtf8Printable(action->text()));
            qDebug(">>> this action is associated with a submenu, iterating it recursively...");
            enumerateMenu(action->menu());
            qDebug("<<< finished iterating the submenu");
        } else {
            qDebug("action: %s", qUtf8Printable(action->text()));
        }
    }
}