Qt QMenuBar和QMenu以及QAction巧妙的使用方法

這裡簡單介紹QMenuBar和QMenu以及QAction是什麼,其詳細功能本文不做介紹,如果還不了解的朋友可以查閱Qt的幫助手冊或瀏覽其它相關部落格。如下圖,軟體中藍色條框是QMenuBar用來承載QMenu,紅色條框中「文件、編輯、構建……」為QMenu,而每個QMenu點擊展開的粉色框內所有可以看到的均為QAction,而點擊粉色框內所產生的動作即是綁定在對應QAction的槽函數(對應訊號為QAction::triggered())。
在這裡插入圖片描述
他們之間的關係用框圖表示大概像這樣子(原諒我的畫圖水平),一個QMenuBar可以有多個QMenu,一個QMenu可以有多個QAction,每個QAction可以對應多個類成員函數(圖中只畫出了對應一個函數的情況)。

在這裡插入圖片描述
OK,簡單的介紹到這裡就結束了,接下來進入正文。QMenuBar雖然好用,但是也有一定的缺陷,它不能像Map、Vector、List等容器一樣可以查找並返回自己的「子節點」。寫這篇文章的目的,第一是為了解決QMenuBar沒有準確定位其中某一個QMenu或QAction的函數介面;第二是做一下筆記,怕自己忘記。廢話不多說了,直接貼程式碼。

1、程式碼關鍵片段

頭文件uart_tools_mainwindow.h有關QMenuBar的關鍵部分程式碼。

//uart_tools_mainwindow.h

class uart_tools_mainwindow;

typedef struct {
    QAction * action_p;
    QString name;
    void (uart_tools_mainwindow::*func) ();
}main_menu_action;

typedef struct {
    QMenu * menu_p;
    QString menu_name;
    QList<main_menu_action> actions_list;
}main_menu;

class uart_tools_mainwindow : public QWidget
{
    Q_OBJECT
    ......
    ......
    ......
private:    
//---------------------------Member--------------------------
//Menu bar
    QMenuBar * mainwindow_menubar;
    QList<main_menu> mainwindow_menu_list;
//---------------------------Functions------------------------
//Init menu bar
    void init_menubar(void);
    void new_action_to_menu(main_menu *menu, QString act_name, void (uart_tools_mainwindow::*func) (void));
    
//Menu bar action funcs
	void show_connect_window(void);
	void connect_c0_reconnect(void);
    void connect_c0_disconnect(void);
};    

源文件uart_tools_mainwindow.cpp的init_menubar()函數實現;

void uart_tools_mainwindow::init_menubar()
{
this->mainwindow_menubar = new QMenuBar();
    this->mainwindow_menubar->setParent(this);

    main_menu tmp_menu;
    main_menu_action tmp_action;
    tmp_menu.menu_name = "Connect";
    tmp_menu.menu_p = this->mainwindow_menubar->addMenu(tmp_menu.menu_name);

    this->new_action_to_menu(&tmp_menu, "Serial", &uart_tools_mainwindow::show_connect_window);
    this->new_action_to_menu(&tmp_menu, "Reconnect", &uart_tools_mainwindow::connect_c0_reconnect);
    this->new_action_to_menu(&tmp_menu, "Disconnect", &uart_tools_mainwindow::connect_c0_disconnect);
    
    this->mainwindow_menu_list.insert(this->mainwindow_menu_list.length() + 1, tmp_menu);

    this->mainwindow_menubar->addSeparator();
//Easy to connect signal and slot
    for (QList<main_menu>::iterator menu_i = this->mainwindow_menu_list.begin(); menu_i < this->mainwindow_menu_list.end(); menu_i++) {
        if ((*menu_i).menu_p) {
            for (int action_i = 0; action_i < (*menu_i).actions_list.size(); action_i++) {
                if ((*menu_i).actions_list.at(action_i).func) {
                    QObject::connect(((*menu_i).actions_list.at(action_i).action_p), &QAction::triggered, this, (*menu_i).actions_list.at(action_i).func);
                }
            }
        }
    }
//End of Easy to connect signal and slot

    //set menubar and menu background color
    this->mainwindow_menubar->setStyleSheet("QMenuBar.item{background-color:#E0E0E0;}QMenuBar{background-color:#E0E0E0;}");
    this->mainwindow_menubar->show();
}    

源文件uart_tools_mainwindow.cpp的new_action_to_menu()函數實現;

void uart_tools_mainwindow::new_action_to_menu(main_menu *menu, QString act_name, void (uart_tools_mainwindow::*func) (void))
{
    main_menu_action tmp_action;

    tmp_action.name = act_name;
    tmp_action.action_p = menu->menu_p->addAction(tmp_action.name);
    tmp_action.func = func;
    menu->actions_list.insert(menu->actions_list.length() + 1, tmp_action);

    return;
}

2、運行結果展示

這個軟體本身是實現了串口連接的功能,即通過串口連接目標板,進入shell命令行並使用shell命令操作。
在這裡插入圖片描述