Qt窗?是通過QMainWindow類來實現的。
QMainWindow是?個為??提供主窗?程序的類,繼承?QWidget類,并且提供了?個預定義的布局。QMainWindow包含?個菜單欄(menu bar)、多個?具欄(tool bars)、多個浮動窗?(鉚接部件)(dock widgets)、?個狀態欄(status bar) 和?個中?部件(central widget),它是許多應?程序的基礎,如?本編輯器,圖?編輯器等。如下圖為QMainwindow中各組件所處的位置:
菜單欄
Qt中的菜單欄是通過QMenuBar這個類來實現的。?個主窗?最多只有?個菜單欄。位于主窗?頂部、主窗?標題欄下?。
菜單欄中包含菜單.菜單中包含菜單項.
菜單:QMenu
菜單欄:QMenuBar
菜單項:QAction
可以通過圖形方式添加菜單欄和菜單項
對象樹
創建菜單欄
?式?:菜單欄的創建可以借助于QMainWindow類提供的menuBar()函數來實現。menubar()函數原型如下:
QMenuBar* menuBar = new QMenuBar();
this->setMenuBar(menuBar);
?式?:在堆上動態創建;
QMenuBar* menuBar = new QMenuBar(this);
this->setMenuBar(menuBar);
使? setMenuBar 把菜單欄放到窗?中.
在菜單欄中添加菜單
創建菜單,并通過 QMenu 提供的 addMenu() 函數來添加菜單。
//創建一個菜單欄
QMenuBar* menuBar = new QMenuBar();
this->setMenuBar(menuBar);//創建菜單
QMenu* menu1 = new QMenu("文件");
QMenu* menu2 = new QMenu("編輯");
QMenu* menu3 = new QMenu("視圖");menuBar->addMenu(menu1);
menuBar->addMenu(menu2);
menuBar->addMenu(menu3);
創建菜單項
在Qt中,并沒有專?的菜單項類,可以通過 QAction 類,抽象出公共的動作。如在菜單中添加菜單項.
QAction可以給菜單欄使?,也可以給?具欄使?.
//添加菜單項
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);
在菜單項之間添加分割線
在菜單項之間可以添加分割線。分割線如下圖所?,添加分割線是通過 QMenu 類提供的 addSeparator() 函數來實現;
menu1->addAction(action1);
menu1->addAction(action2);
menu1->addAction(action3);
menu1->addAction(action4);
menu1->addSeparator(); //在另存為和退出中間添加分割線
menu1->addAction(action5);
整體代碼
#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* menu1 = new QMenu("文件");QMenu* menu2 = new QMenu("編輯");QMenu* menu3 = new QMenu("視圖");menuBar->addMenu(menu1);menuBar->addMenu(menu2);menuBar->addMenu(menu3);//添加菜單項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->addSeparator(); //在另存為和退出中間添加分割線menu1->addAction(action5);
}
添加快捷鍵
給菜單和菜單項設置快捷鍵
設置好的快捷鍵就可以搭配alt來進行使用了,("文件(&F)")
;
通過給文本中添加&F這樣的操作,就是添加了快捷鍵alt+F
&這個符號并不會在界面上顯示
//創建菜單
QMenu* menu1 = new QMenu("文件 (&F)");
QMenu* menu2 = new QMenu("編輯 (&E)");
QMenu* menu3 = new QMenu("視圖 (&V)");
QMenu* menu4 = new QMenu("關于 (&A)");menuBar->addMenu(menu1);
menuBar->addMenu(menu2);
menuBar->addMenu(menu3);
menuBar->addMenu(menu4);
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menu1 = new QMenu("文件 (&F)");QMenu* menu2 = new QMenu("視圖 (&V)");menuBar->addMenu(menu1);menuBar->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);
}
添加子菜單
#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);
}
添加圖標
#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("新建");action1->setIcon(QIcon(":/new.png"));QAction* action2 = new QAction("保存");action2->setIcon(QIcon(":/save.png"));menu->addAction(action1);menu->addAction(action2);
}
內存泄漏
QMenuBar* menuBar = new QMenuBar();
this->setMenuBar(menuBar);
如果創建的項目,沒有勾選自動生成ui文件,此時上述代碼是ok的
如果勾選了自動生成ui文件,上述代碼則會引起內存泄露·
Qt已經給你生成了一個QMenuBar了.
之前程序自己已經創建好了一個QMenuBar
當設置新的QMenuBar進來的時候,就會導致l舊的
QMenuBar脫離了Qt的對象樹了.意味著后續就無法對這個對象進行釋放了
上述程序如果窗口關閉,對象樹釋放,此時進程也就結束了.進程結束,自然所有內存都回收給系統,上述內存泄露也不會造成影響.
但是如果這樣的代碼是出現在一個多窗口的程序中~如果涉及到窗口的頻繁跳轉切換(窗口的頻繁創建銷毀),上述內存泄露就會更嚴重一些
但是實際上由于現在的計算機內存都比較充裕上述內存泄露都還好
服務器程序相比于客戶端程序更害怕內存泄露
- 服務器要處理很多請求,每個請求泄露一點,請求積累下來就會泄露很多
- 服務器要
7*24
小時運行
QMenuBar* menuBar = this->menuBar();
//1.如果QMenuBar已經存在,直接獲取并返回
//2.如果QMenuBar不存在,就先創建一個新的,再返回.
this->setMenuBar(menuBar);
//如果是獲取到已經存在的QMenuBar,這里的設置就是自己替換自己,還是自己
//仍然在對象樹上
綜合示例
1、在"mainwindow.cpp"?件中創建菜單和中央控件
- 創建?個菜單欄,?個菜單.
- 兩個菜單項:保存,加載
- 創建?個 QTextEdit 作為窗?的中央控件.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextEdit>
#include <QFileDialog>
#include <QDebug>
#include <fstream>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//設置標題this->setWindowTitle("我的記事本");//創建菜單欄QMenuBar* menubar = this->menuBar();this->setMenuBar(menubar);//創建菜單QMenu* menu = new QMenu("文件");menuBar()->addMenu(menu);//創建菜單項QAction* action1 = new QAction("保存");QAction* action2 = new QAction("加載");menu->addAction(action1);menu->addAction(action2);//創建中央控件edit = new QTextEdit(this);this->setCentralWidget(edit);edit->setPlaceholderText("此處編寫文本內容...");
}
3、給action添加?些動作
//連接信號槽, 點擊 action 時觸發?定的效果
connect(action1, &QAction::triggered, this, &MainWindow::save);
connect(action2, &QAction::triggered, this, &MainWindow::load);
- 使? QFileDialog 來實現選擇?件的效果.
- getSaveFileName ?于保存?件的場景.此時的對話框可以輸??件名.
- getOpenFileName ?于打開?件的場景.此時的對話框可以獲取到?標選擇的?件名.
- 搭配C++標準庫的?件操作實現?件讀寫.
void MainWindow::save()
{// 彈出對話框, 選擇寫??件的路徑QFileDialog* dialog = new QFileDialog(this);QString fileName = dialog->getSaveFileName(this, "保存文件", "F:/Qt/");qDebug() << "fimeName: " << fileName;// 寫??件std::ofstream file(fileName.toStdString().c_str());if (!file.is_open()) {qDebug() << "文件保存失敗";return;}const QString& text = edit->toPlainText();file << text.toStdString();file.close();
}void MainWindow::load()
{// 彈出對話框, 選擇打開的?件QFileDialog* dialog = new QFileDialog(this);QString fileName = dialog->getOpenFileName(this, "加載文件", "F:Qt/");qDebug() << "fileName: " << fileName;// 讀取?件std::ifstream file(fileName.toStdString().c_str());if (!file.is_open()) {qDebug() << "文件加載失敗";return;}std::string content;std::string line;while (std::getline(file, line)) {content += line;content += "\n";}file.close();// 顯?到界?上QString text = QString::fromStdString(content);edit->setPlainText(text);
}
執?程序,可以看到此時就可以通過程序來保存/加載?件了.并且對?件進?編輯.