文章目錄
- 前言
- 1. 什么是Main Window?
- 2. 詳細了解一下其中的 菜單欄:
- 2.1. 創建菜單欄
- 2.2. 添加快捷鍵
- 2.3. 添加子菜單
- 2.4. 添加分割線
- 2.5. 添加圖標
- 3. 內存泄漏問題:
- 總結
前言
在現代軟件開發中,用戶界面的設計對于提升用戶體驗至關重要。Qt框架作為功能強大的跨平臺開發工具,提供了豐富的組件和工具來幫助開發者構建復雜的應用程序。本文將深入探討Qt中的主窗口(QMainWindow
)及其菜單欄(QMenuBar
)的創建和使用,包括菜單欄的創建、菜單項的添加、快捷鍵的設置、子菜單的嵌套、分割線的使用以及圖標的添加。此外,文章還將討論內存泄漏問題,以及如何在Qt中避免這類問題,確保應用程序的穩定性和性能。
前面學習的所有代碼,都是基于 QWidget
(控件),QWidget
更多的是作為別的窗口的一個部分。
1. 什么是Main Window?
QMainWindow
是?個為用戶提供主窗口程序的類,繼承自 QWidget
類,并且提供了?個預定義的布局。QMainWindow
包含 ?個菜單欄(menu bar)、多個工具欄(tool bars)、多個浮動窗口(鉚接部件)(dock widgets)、?個狀態欄(status bar) 和?個中心部件(central widget),它是許多應用程序的基礎,如文本編輯器,圖片編輯器等。如下圖為 QMainwindow
中 各組件所處的位置:
-
菜單欄(Menu Bar):
Qt 中的菜單欄是通過QMenuBar
這個類來實現的。?個主窗口最多只有?個菜單欄。位于主窗口頂部、主窗口標題欄下面。
-
工具欄(Tool Bar Area):
工具具欄是應用程序中集成各種功能實現快捷鍵使用的?個區域。可以有多個,也可以沒有,它并不是應用程序中必須存在的組件。它是?個可移動的組件,它的元素可以是各種窗口組件,它的元素通常以圖標按鈕的方式存在。如下圖為工具欄的示意圖:
-
鉚接部件/子窗口(Dock Widget Area)
一個主窗口往往可以是由多個子窗口所構成的。
-
中央控件(Central Widget)
窗口最核心的部分
-
狀態欄(Status Bar)
用于顯示一些信息供用戶去參考。
2. 詳細了解一下其中的 菜單欄:
Qt 中的菜單欄是通過 QMenuBar
這個類來實現的。?個主窗口最多只有?個菜單欄。位于主窗口頂部、主窗口標題欄下面。
菜單欄中包含菜單. 菜單中包含菜單項。
一個主窗口最多只有一個菜單欄,工具欄,本質上就是菜單中的一些選項的“快捷方式”
QAction
動作
2.1. 創建菜單欄
“在這里輸入” 可以在這里添加菜單了
菜單欄(
QMenuBar
) -> 菜單(QMenu
) -> 菜單項(QAction
)
由于當前每個菜單都是空著的,點上去沒反應,添加后有反應。
使用代碼去創建菜單結構:
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 1.先創建一個菜單欄QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);// 2. 創建菜單QMenu* menu1 = new QMenu("文件");QMenu* menu2 = new QMenu("編輯");QMenu* menu3 = new QMenu("視圖");menuBar->addMenu(menu1);menuBar->addMenu(menu2);menuBar->addMenu(menu3);// 3. 給菜單添加菜單項QAction* action1 = new QAction("新建");QAction* action2 = new QAction("打開");QAction* action3 = new QAction("保存");QAction* action4 = new QAction("另存為");QAction* action5 = new QAction("退出");menu1->addAction(action1);menu1->addAction(action2);menu1->addAction(action3);menu1->addAction(action4);menu1->addAction(action5);}MainWindow::~MainWindow()
{delete ui;
}
怎樣使它點擊的時候有反應呢?
QAction* action1 = new QAction("新建");
QAction* action2 = new QAction("打開");
QAction* action3 = new QAction("保存");
QAction* action4 = new QAction("另存為");
QAction* action5 = new QAction("退出");
被點擊的時候會觸發一個信號!triggered 觸發
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 1.先創建一個菜單欄QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);// 2. 創建菜單QMenu* menu1 = new QMenu("文件");QMenu* menu2 = new QMenu("編輯");QMenu* menu3 = new QMenu("視圖");menuBar->addMenu(menu1);menuBar->addMenu(menu2);menuBar->addMenu(menu3);// 3. 給菜單添加菜單項QAction* action1 = new QAction("新建");QAction* action2 = new QAction("打開");QAction* action3 = new QAction("保存");QAction* action4 = new QAction("另存為");QAction* action5 = new QAction("退出");menu1->addAction(action1);menu1->addAction(action2);menu1->addAction(action3);menu1->addAction(action4);menu1->addAction(action5);// 4. 給 action 添加信號槽connect(action1, &QAction::triggered, this, &MainWindow::handle);connect(action5, &QAction::triggered, this, &MainWindow::close); // close 是Qt自帶關閉窗口的槽函數}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle()
{qDebug() << "觸發新建操作!";
}
2.2. 添加快捷鍵
給菜單和菜單項設置快捷鍵
設置好的快捷鍵就可以搭配 alt 來進行使用了
QMenu* menu1 = new QMenu("文件(&F)");
通過給文本添加 &F
這樣的操作,就是添加了快捷鍵 alt+F
與,QLabel
,中設置伙伴的方式比較相似,當然使用 QShortcut
也可以實現同樣的效果但是太麻煩了。
給菜單項同樣可以添加快捷鍵:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menBar = new QMenuBar();this->setMenuBar(menBar);QMenu* menu1 = new QMenu("文件(&F)");QMenu* menu2 = new QMenu("視圖(&V)");menBar->addMenu(menu1);menBar->addMenu(menu2);// 創建四個菜單項QAction* action1 = new QAction("action1(&Q)");QAction* action2 = new QAction("action2(&W)");QAction* action3 = new QAction("action3(&E)");QAction* action4 = new QAction("action4(&R)");menu1->addAction(action1);menu1->addAction(action2);menu2->addAction(action3);menu2->addAction(action4);// 如果不綁定槽函數,通過快捷鍵選中也沒啥反應connect(action1, &QAction::triggered, this, &MainWindow::handle1);connect(action2, &QAction::triggered, this, &MainWindow::handle2);connect(action3, &QAction::triggered, this, &MainWindow::handle3);connect(action4, &QAction::triggered, this, &MainWindow::handle4);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle1()
{qDebug() << "handle1" ;
}void MainWindow::handle2()
{qDebug() << "handle2" ;
}void MainWindow::handle3()
{qDebug() << "handle3" ;
}void MainWindow::handle4()
{qDebug() << "handle4" ;
}
2.3. 添加子菜單
菜單欄 -> 菜單 -> 菜單項
菜單欄->菜單->子菜單->菜單項
QMenuBar
可以通過 addMenu
添加菜單的,QMenu
也提供了 addMenu
。
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menuParent = new QMenu("父菜單");QMenu* menuChild = new QMenu("子菜單");menuBar->addMenu(menuParent);menuParent->addMenu(menuChild);QAction* action1 = new QAction("菜單項1");QAction* action2 = new QAction("菜單項2");menuChild->addAction(action1);menuChild->addAction(action2);QMenu* menuChild2 = new QMenu("子菜單2");menuChild->addMenu(menuChild2);}MainWindow::~MainWindow()
{delete ui;
}
2.4. 添加分割線
菜單里菜單特別多,就可以通過分割線進行分組
QMenu
中提供了 addSeparator
這樣的函數
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menu = new QMenu("菜單");menuBar->addMenu(menu);QAction* action1 = new QAction("菜單項1");QAction* action2 = new QAction("菜單項2");menu->addAction(action1);menu->addSeparator();menu->addAction(action2);
}MainWindow::~MainWindow()
{delete ui;
}
2.5. 添加圖標
Qlcon 類, qrc
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menu = new QMenu("菜單");menuBar->addMenu(menu);QAction* action1 = new QAction("菜單項1");action1->setIcon(QIcon(":/open.png"));QAction* action2 = new QAction("菜單項2");action2->setIcon(QIcon(":/save.png"));menu->addAction(action1);menu->addAction(action2);
}MainWindow::~MainWindow()
{delete ui;
}
如果給 QMenu
設置圖標,當前 QMenu
是長在 QMenuBar
上的,此時文本就不顯示,圖標就覆蓋了文本。
QMenu
是子菜單,圖標和文本都是能顯示的。
3. 內存泄漏問題:
QMenuBar* menuBar = new QMenuBar();
this->setMenuBar(menuBar);
如果咱們創建項目,沒有勾選生成ui,文件,此時上述代碼是可以的,如果勾選了自動生成 ui 文件,上述代碼則會引起內存泄漏。
自動生成 ui 文件:Qt已經給你生成了一個 QMenuBar
了。
之前程序已經創建好了一個 QMenuBar
, 當設置新的 QMenuBar
進來的時候, 就會導致舊的 QMenuBar
脫離了 Qt 的對象樹了,意味著后續無法對這個對象樹進行釋放了
上訴程序如果窗口關閉,對象樹釋放,此時進程也就介紹了。進程結束,自然所有內存都回收給系統。上述內存泄漏也不會造成影響,但是如果這樣的如果出現在一個多窗口的程序中。如果涉及到窗口的頻繁跳轉切換(窗口的頻繁創建銷毀),上述代碼泄漏會更嚴重一些。但是實際上由于現在的計算機內存都比較充裕上述內存泄漏都還好。
服務器程序相比于客戶端程序相比更害怕內存泄漏。
- 服務器要處理很多請求,每個請求泄漏一點,請求累積下來就會泄漏很多
- 服務器要 7 * 24 小時運行。
當然,即使如此,還是期望代碼寫的更規范一些。
QMenuBar* menuBar = this->menuBar();
- 如果
QMenuBar
已經存在,直接獲取并返回 - 如果
QMenuBar
不存在,就先創建一個新的,再返回。
this->setMenuBar(menuBar);
如果是活的已經存在的 QMenuBar
, 這里的設置就是自己替換自己,仍然對象樹上
如在嵌入式,設備上內存泄漏的問題就比較重要了。
總結
本文詳細介紹了Qt中主窗口(QMainWindow
)的構成和功能,特別是菜單欄(QMenuBar
)的創建和使用。通過一系列具體的代碼示例,我們學習了如何創建菜單欄、添加菜單和菜單項、設置快捷鍵、嵌套子菜單、使用分割線以及添加圖標,這些都是構建用戶友好界面的關鍵步驟。同時,文章也指出了在Qt開發中可能遇到的內存泄漏問題,并提供了解決方案,強調了在開發過程中遵循良好編程實踐的重要性。通過這些知識點,開發者可以更有效地利用Qt框架,創建出既美觀又實用的應用程序界面。