C++ Qt開發:ToolBar與MenuBar菜單組件

Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程序,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹ToolBar工具欄組件以及與之類似的MenuBar菜單欄組件的常用方法及靈活運用。

1.1 QToolBar 工具欄

QToolBar 是 Qt 中用於創建工具欄的組件,它爲用戶提供了一個方便的方式來組織和訪問應用程序中的各種工具和操作。工具欄通常用於快速訪問常用的功能,提高用戶體驗。

1.1.1 主要特點

  1. 工具按鈕: QToolBar 主要由工具按鈕組成,每個工具按鈕代表一個功能或操作。工具按鈕可以包含文本、圖標,也可以與相應的槽函數關聯,實現用戶點擊按鈕時觸發相應的操作。
  2. 分組和彈出菜單: 工具欄支持將工具按鈕分組,使界面更加清晰。還可以爲工具按鈕添加彈出菜單,以提供額外的選項。
  3. 可調整性: 用戶可以在工具欄上自由拖動工具按鈕,重新排列它們的位置。這增加了用戶定製界面的靈活性。
  4. 自定義小部件: 除了工具按鈕,工具欄還支持添加自定義的小部件,例如搜索框、進度條等,以滿足特定需求。
  5. 樣式和佈局: 可以通過設置樣式和佈局來定製工具欄的外觀,包括工具按鈕的樣式、大小和排列方式。

以下是 QToolBar 類的一些常用方法的說明和概述,以表格形式列出:

方法 描述
QToolBar(QWidget *parent = nullptr) 構造函數,創建一個 QToolBar 對象。
addAction(QAction *action) 向工具欄中添加一個動作。
addWidget(QWidget *widget) 向工具欄中添加一個小部件。
addSeparator() 向工具欄中添加一個分隔符。
clear() 清除工具欄上的所有動作和小部件。
setOrientation(Qt::Orientation orientation) 設置工具欄的方向,可以是水平 (Qt::Horizontal) 或垂直 (Qt::Vertical)。
setMovable(bool movable) 設置工具欄是否可以被用戶移動。
setIconSize(const QSize &size) 設置工具欄中動作的圖標大小。
setToolButtonStyle(Qt::ToolButtonStyle style) 設置工具按鈕的樣式,可以是文本和圖標一起顯示、只顯示圖標、只顯示文本等。
toggleViewAction() 返回一個切換工具欄可見性的動作。
addWidget(QWidget *widget) 在工具欄中添加一個自定義小部件。
clear() 清除工具欄上的所有動作和小部件。
setAllowedAreas(Qt::ToolBarAreas areas) 設置工具欄允許停靠的區域,可以是上、下、左、右、所有區域的組合。
setFloatable(bool floatable) 設置工具欄是否可以浮動。
setWindowTitle(const QString &title) 設置工具欄的標題。
addWidget(QWidget *widget) 在工具欄中添加一個自定義小部件。
widgetForAction(QAction *action) const 返回與給定動作相關聯的小部件。

這些方法提供了對 QToolBar 進行動作、小部件和外觀等方面的控制,使其適應不同的應用場景。你可以根據具體需求使用這些方法,定製工具欄的外觀和行爲。

1.2 QMenuBar 菜單欄

QMenuBar 是 Qt 中用於創建菜單欄的組件,它提供了一種方便的方式來組織和管理應用程序的菜單。菜單欄通常用於將應用程序的功能劃分爲不同的菜單,使用戶可以輕鬆訪問各種操作。

1.2.1 主要特點

  1. 菜單項: QMenuBar 主要由菜單項組成,每個菜單項代表一個功能或操作。菜單項可以包含子菜單,形成層級關係,用於更好地組織功能。
  2. 快捷鍵: 每個菜單項可以關聯一個快捷鍵,用戶可以通過鍵盤快捷鍵來觸發相應的操作。
  3. 分組和分割線: 菜單欄支持在菜單項之間添加分組和分割線,用於更好地區分不同的功能模塊。
  4. 動作關聯: 菜單項通常與具體的動作(QAction)關聯,點擊菜單項時觸發相應的動作。
  5. 上下文菜單: QMenuBar 也可以用作上下文菜單(右鍵菜單),在特定區域點擊右鍵時顯示相應的菜單項。

以下是 QMenuBar 類的一些常用方法的說明和概述,以表格形式列出:

方法 描述
QMenuBar(QWidget *parent = nullptr) 構造函數,創建一個 QMenuBar 對象。
addMenu(const QString &title) 添加一個具有給定標題的菜單,並返回一個指向新菜單的指針。
addMenu(QMenu *menu) 添加給定的菜單。
addSeparator() 在菜單欄上添加一個分隔符。
addActions(QList<QAction*> actions) 添加給定的動作列表到菜單欄。
clear() 清除菜單欄上的所有菜單和分隔符。
setNativeMenuBar(bool nativeMenuBar) 設置是否使用本地菜單欄,如果爲 true,則菜單欄將使用本地系統的菜單欄實現。
setCornerWidget(QWidget *widget, Qt::Corner corner = Qt::TopLeftCorner) 在指定的角落放置一個小部件。
addMenu(QMenu *menu) 添加給定的菜單。
setActiveAction(QAction *action) 設置活動動作,該動作將在菜單欄上顯示爲活動狀態。
addMenu(const QString &title) 添加一個具有給定標題的菜單,並返回一個指向新菜單的指針。
setCornerWidget(QWidget *widget, Qt::Corner corner = Qt::TopLeftCorner) 在指定的角落放置一個小部件。
clear() 清除菜單欄上的所有菜單和分隔符。
setNativeMenuBar(bool nativeMenuBar) 設置是否使用本地菜單欄,如果爲 true,則菜單欄將使用本地系統的菜單欄實現。
setActiveAction(QAction *action) 設置活動動作,該動作將在菜單欄上顯示爲活動狀態。
setCornerWidget(QWidget *widget, Qt::Corner corner = Qt::TopLeftCorner) 在指定的角落放置一個小部件。

這些方法提供了對 QMenuBar 進行菜單管理、外觀設置以及與其他小部件的交互等方面的控制。你可以根據具體需求使用這些方法,定製菜單欄的外觀和行爲。

1.3 使用菜單組件

通常情況下ToolBarMenuBar兩者會配合使用,在5.14.2版本中,窗體創建後會默認包含一個MenuBar組件,對於老版本的Qt則會自帶一個ToolBar組件,ToolBar工具欄組件與MenuBar菜單欄組件,在所有窗體應用程序中都廣泛被使用,使用這兩種組件可以很好的規範菜單功能分類,用戶可根據菜單欄來選擇不同的功能,實現靈活的用戶交互。

頂部工具欄ToolBar組件的定義有多種方式,我們可以直接通過代碼生成,也可以使用圖形界面UI添加,當需要使用UI實現時,只需要在MainWindow中選擇添加工具來新增,默認會在窗口頂部增加,如果想要在四面增加可以使用Add Tool Bar to Other Area選項實現;

1.3.1 應用菜單組件

通常情況下我們不會使用UI的方式來使用工具欄,通過代碼將很容易的實現創建,如下代碼中我們通過屬性setAllowedAreas()可以實現將ToolBar組件放置到上下左右四個不同的方位上,通過代碼的方式實現一個頂部菜單欄,該菜單欄中可以通過SetIcon(QIcon("://image/.ico"));指定圖標,也可以使用setShortcut(Qt::CTRL | Qt::Key_C);爲其指定特殊的快捷鍵。

#include <iostream>
#include <QMenuBar>
#include <QToolBar>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // ----------------------------------------------------------
    // 創建菜單欄
    // ----------------------------------------------------------
    QMenuBar *bar = menuBar();
    this->setMenuBar(bar);                      // 將菜單欄放入主窗口
    QMenu * fileMenu = bar->addMenu("文件");     // 創建父節點

    // 添加子菜單
    QAction *newAction = fileMenu->addAction("新建文件");      // 設置名字
    newAction->setIcon(QIcon("://image/file.ico"));          // 設置可用圖標
    newAction->setShortcut(Qt::CTRL | Qt::Key_A);            // 設置快捷鍵ctrl+a

    fileMenu->addSeparator();                                // 添加分割線
    QAction *openAction = fileMenu->addAction("打開文件");     // 設置名字
    openAction->setIcon(QIcon("://image/lock.ico"));         // 設置可用圖標
    openAction->setShortcut(Qt::CTRL | Qt::Key_C);           // 設置快捷鍵ctrl+c

    // ----------------------------------------------------------
    //創建工具欄 (可屏蔽掉 屏蔽掉後底部將失去控件欄位)
    // ----------------------------------------------------------
    QToolBar *toolBar = new QToolBar(this);    // 創建工具欄
    addToolBar(Qt::BottomToolBarArea,toolBar); // 設置默認停靠範圍 [默認停靠底部]

    toolBar->setAllowedAreas(Qt::TopToolBarArea |Qt::BottomToolBarArea);   // 允許上下拖動
    toolBar->setAllowedAreas(Qt::LeftToolBarArea |Qt::RightToolBarArea);   // 允許左右拖動

    toolBar->setFloatable(false);       // 設置是否浮動
    toolBar->setMovable(false);         // 設置工具欄不允許移動

    // 工具欄添加菜單項
    toolBar->addAction(newAction);
    toolBar->addSeparator();
    toolBar->addAction(openAction);

    // ----------------------------------------------------------
    // 綁定槽函數
    // ----------------------------------------------------------
    connect(newAction,&QAction::triggered,this,[=](){
        QMessageBox::information(nullptr,"提示","觸發新建文件",QMessageBox::Ok);
    });

    connect(openAction,&QAction::triggered,this,[=](){
        QMessageBox::information(nullptr,"提示","觸發打開文件",QMessageBox::Ok);
    });
}

由於通過connect綁定到了每一個Action上,所以當用戶點擊不同的菜單時將會觸發不同的匿名槽函數,代碼中實現了彈窗提示,此處也可以替換成任意代碼,運行效果圖如下所示;

1.3.2 二級菜單聯動

如上所示的生成案例實現了單一菜單的生成,其實QMenuBar組件同樣可實現二級菜單的聯動,二級頂部菜單與一級菜單完全一致,只是在一級菜單的基礎上進行了延申,當然只要遵循菜單的嵌套規則理論上我們可以無限延伸下去,當然爲了開發代碼邏輯清晰,筆者並不建議菜單層級超過三級。

#include <iostream>
#include <QMenuBar>
#include <QToolBar>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // ----------------------------------------------------------
    // 多層菜單導航欄
    // ----------------------------------------------------------
    QMenuBar *MainMenu = new QMenuBar(this);
    this->setMenuBar(MainMenu);

    // 1.定義父級菜單
    QMenu *EditMenu = MainMenu->addMenu("文件編輯");

    // 1.1 定義 EditMemu 下面的子菜單
    QAction *text = new QAction(EditMenu);
    text->setText("編輯文件");                     // 設置文本內容
    text->setShortcut(Qt::CTRL | Qt::Key_A);      // 設置快捷鍵ctrl+a
    text->setIcon(QIcon(":/image/about.ico"));    // 增加圖標
    EditMenu->addAction(text);

    // 在配置模式與編輯文件之間增加虛線
    EditMenu->addSeparator();

    QAction *option = new QAction(EditMenu);
    option->setText("配置模式");
    option->setIcon(QIcon(":/image/file.ico"));
    EditMenu->addAction(option);

    // 1.1.2 定義Option配置模式下的子菜單
    QMenu *childMenu = new QMenu();
    QAction *set_file = new QAction(childMenu);
    set_file->setText("設置文件內容");
    set_file->setIcon(QIcon(":/image/lock.ico"));
    set_file->setShortcut(Qt::CTRL | Qt::Key_B);

    childMenu->addAction(set_file);

    QAction *read_file = new QAction(childMenu);
    read_file->setText("讀取文件內容");
    read_file->setIcon(QIcon(":/image/about.ico"));
    childMenu->addAction(read_file);
    read_file->setShortcut(Qt::CTRL | Qt::Key_C);

    // ----------------------------------------------------------
    // 註冊菜單到窗體中
    // ----------------------------------------------------------
    // 首先將childMenu註冊到option中
    option->setMenu(childMenu);
    // 然後再將childMenu加入到EditMenu中
    EditMenu->addMenu(childMenu);

    // ----------------------------------------------------------
    // 綁定信號和槽
    // ----------------------------------------------------------
    connect(text,&QAction::triggered,this,[=](){
       QMessageBox::information(nullptr,"提示","觸發編輯文件",QMessageBox::Ok);
    });

    connect(set_file,&QAction::triggered,this,[=](){
       QMessageBox::information(nullptr,"提示","觸發設置文件",QMessageBox::Ok);
    });

    connect(read_file,&QAction::triggered,this,[=](){
      QMessageBox::information(nullptr,"提示","觸發讀取文件",QMessageBox::Ok);
    });
}

代碼運行後讀者可看到如下圖所示的效果,在配置模式中增加了兩個子菜單,每個子菜單分別綁定到了一個槽函數上,而其父菜單僅僅只是展示功能此處可以不增加任何實質性的功能。

1.3.3 增加右鍵菜單

Qt中的菜單還可以實現任意位置的彈出,該功能的實現依賴於QMainWindow主窗體中的customContextMenuRequested()事件,該事件是Qt中的一個信號,通常與右鍵菜單(上下文菜單)相關。該信號在用戶請求上下文菜單時觸發,例如通過右鍵單擊某個小部件(如窗口、按鈕、表格等)時。

我們可以將右擊customContextMenuRequested()事件綁定到主窗口中,實現在窗體任意位置右擊都可以彈出菜單欄,讀者可以直接在主界面中點擊右鍵轉到槽,如下圖;

當讀者點擊主窗體中的右鍵時則會觸發on_MainWindow_customContextMenuRequested事件,該事件的內部則實現了創建菜單的功能,並通過pMenu->exec(QCursor::pos())的方式顯示在鼠標點擊位置處,其代碼如下所示;

#include <iostream>
#include <QMenuBar>
#include <QToolBar>
#include <QCursor>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 設置小部件(QWidget)的上下文菜單策略
    this->setContextMenuPolicy(Qt::CustomContextMenu);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 觸發右鍵創建菜單
void MainWindow::on_MainWindow_customContextMenuRequested(const QPoint &pos)
{

    // 創建菜單對象
    QMenu *pMenu = new QMenu(this);

    QAction *pNewTask = new QAction(tr("新建菜單"), this);
    QAction *pEditTask = new QAction(tr("編輯菜單"), this);
    QAction *pDeleteTask = new QAction(tr("刪除菜單"), this);

    // 設置屬性值編號: 1=>新建 2=>設置 3=>刪除
    pNewTask->setData(1);
    pEditTask->setData(2);
    pDeleteTask ->setData(3);

    // 把QAction對象添加到菜單上
    pMenu->addAction(pNewTask);
    pMenu->addAction(pEditTask);
    pMenu->addAction(pDeleteTask);

    // 增加圖標
    pNewTask->setIcon(QIcon(":/image/about.ico"));
    pEditTask->setIcon(QIcon(":/image/file.ico"));
    pDeleteTask->setIcon(QIcon(":/image/lock.ico"));

    // 連接鼠標右鍵點擊信號
    connect(pNewTask, SIGNAL(triggered()), this, SLOT(onTaskBoxContextMenuEvent()));
    connect(pEditTask, SIGNAL(triggered()), this, SLOT(onTaskBoxContextMenuEvent()));
    connect(pDeleteTask, SIGNAL(triggered()), SLOT(onTaskBoxContextMenuEvent()));

    // 在鼠標右鍵點擊的地方顯示菜單
    pMenu->exec(QCursor::pos());

    //釋放內存
    QList<QAction*> list = pMenu->actions();
    foreach (QAction* pAction, list) delete pAction;
    delete pMenu;
}

接着就需要綁定到特定的槽函數上,用於接收用戶點擊的菜單選項,並根據選項做出相應的判斷,這裏我們定義一個onTaskBoxContextMenuEvent函數,並在MainWindow.h頭文件進行聲明,其實現部分如下所示;

// 處理髮送過來的信號
void MainWindow::onTaskBoxContextMenuEvent()
{
    // this->sender()就是信號發送者 QAction
    QAction *pEven = qobject_cast<QAction *>(this->sender());

    // 獲取編號: 1=>新建 2=>設置 3=>刪除
    int iType = pEven->data().toInt();

    switch (iType)
    {
    case 1:
        QMessageBox::information(nullptr,"提示","觸發新建任務",QMessageBox::Ok);
        break;
    case 2:
        QMessageBox::information(nullptr,"提示","觸發設置任務",QMessageBox::Ok);
        break;
    case 3:
        QMessageBox::information(nullptr,"提示","觸發刪除任務",QMessageBox::Ok);
        break;
    default:
        break;
    }
}

至此當我們再次使用右鍵點擊主頁面時,則會彈出一個個性化菜單欄,如下圖所示;

1.3.4 增加頂部通欄

通常情況下我們需要頂部按鈕的排布,這有助於增加頁面的圖形化顯示效果,爲了讓頁面只保留一個ToolBar組件,通常情況下會將默認的menuBar組件進行隱藏,隱藏的方式是通過調用setVisible(false)來實現,對外只展示出一個ToolBar控件欄位,而在ToolBar控件欄中只保留ICO圖標與底部文字描述,這樣能顯得更加清爽一些。

#include <iostream>
#include <QMenuBar>
#include <QToolBar>
#include <QCursor>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 隱藏菜單欄上的右擊菜單
    this->setContextMenuPolicy(Qt::NoContextMenu);

    // ----------------------------------------------------------
    // 創建menuBar組件
    // ----------------------------------------------------------
    // 創建基礎頂部菜單並讓其隱藏
    QMenuBar *bar = menuBar();
    this->setMenuBar(bar);
    QMenu * fileMenu = bar->addMenu("Ptr");

    // 隱藏菜單
    bar->setVisible(false);

    // 添加子菜單
    QAction *NewAction = fileMenu->addAction("新建文件");
    QAction *OpenAction = fileMenu->addAction("打開文件");
    QAction *ReadAction = fileMenu->addAction("讀入文件");

    // 分別設置圖標
    NewAction->setIcon(QIcon(":/image/about.ico"));
    OpenAction->setIcon(QIcon(":/image/file.ico"));
    ReadAction->setIcon(QIcon(":/image/lock.ico"));

    // 創建工具欄
    QToolBar *toolBar = new QToolBar(this);
    addToolBar(Qt::TopToolBarArea,toolBar);

    // 將菜單項依次添加到工具欄
    toolBar->addAction(NewAction);
    toolBar->addAction(OpenAction);
    toolBar->addAction(ReadAction);

    // 設置禁止移動屬性,工具欄默認貼在上方
    toolBar->setFloatable(false);
    toolBar->setMovable(false);
    toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);

    // ----------------------------------------------------------
    // 綁定槽函數
    // ----------------------------------------------------------
    connect(NewAction,&QAction::triggered,this,[=](){
        QMessageBox::information(nullptr,"提示","觸發新建文件按鈕",QMessageBox::Ok);
    });

    connect(OpenAction,&QAction::triggered,this,[=](){
        QMessageBox::information(nullptr,"提示","觸發打開文件按鈕",QMessageBox::Ok);
    });

    connect(ReadAction,&QAction::triggered,this,[=](){
        QMessageBox::information(nullptr,"提示","觸發讀取文件按鈕",QMessageBox::Ok);
    });
}

運行後讀者可看到如下圖所示的案例,我們只保留了最基本的按鈕欄,這樣看起來更加的清爽。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章