????????Qt窗?是通過QMainWindow類來實現的。 QMainWindow是?個為??提供主窗?程序的類,繼承?QWidget類,并且提供了?個預定義的 布局。QMainWindow包含?個菜單欄(menubar)、多個?具欄(toolbars)、多個浮動窗?(鉚 接部件)(dockwidgets)、?個狀態欄(statusbar)和?個中?部件(centralwidget),它是許多應 ?程序的基礎,如?本編輯器,圖?編輯器等。如下圖為QMainwindow中各組件所處的位置:
?1. 菜單欄
????????Qt 中的菜單欄是通過QMenuBar這個類來實現的。?個主窗?最多只有?個菜單欄。位于主窗?頂部、主窗?標題欄下?。 菜單欄中包含菜單.菜單中包含菜單項
?菜單欄(QMenuBar)->菜單(QMenu)->菜單項(QAction)
1.1使用代碼創建菜單結構:
#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);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle()
{qDebug() << "觸發新建操作!";
}
執行效果如下:
1.2 給菜單配置快捷鍵
????????給菜單和菜單項設置快捷鍵,設置好的快捷鍵就可以搭配alt來進行使用了。
(文件(&F));通過給文本中添加&F這樣的操作,就是添加了快捷鍵alt+F
#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("文件 (&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);// 創建菜單項QAction* action1 = new QAction("菜單項1");QAction* action2 = new QAction("菜單項2");QAction* action3 = new QAction("菜單項3");QAction* action4 = new QAction("菜單項4");menu1->addAction(action1);menu2->addAction(action2);menu3->addAction(action3);menu4->addAction(action4);
}MainWindow::~MainWindow()
{delete ui;
}
?
1.3 給qaction創建快捷鍵
#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);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle1()
{qDebug() << "handle1";
}void MainWindow::handle2()
{qDebug() << "handle2";
}void MainWindow::handle3()
{qDebug() << "handle3";
}void MainWindow::handle4()
{qDebug() << "handle4";
}
1.4 菜單欄中添加子菜單
????????菜單欄->菜單->子菜單->子菜單->菜單項
? ? ? ? 通過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("子菜單1");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;
}
執行效果如下所示:
1.5 添加分割線
?菜單里菜單項特別多,就可以通過分割線,進行分組,QMenu中提供了addseparator這樣的函數。
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);
}
1.6 添加圖標
? ? ? ? 使用qrc文件引入icon圖片:
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// QMenuBar* menuBar = new QMenuBar();QMenuBar* menuBar = this->menuBar();this->setMenuBar(menuBar);QMenu* menu = new QMenu("菜單");menu->setIcon(QIcon(":/open.png"));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是子菜單,圖標和文本是都能顯示的
1.7 內存泄漏問題
// QMenuBar* menuBar = new QMenuBar();
如果咱們創建的項目,沒有勾選自動生成ui文件,此時上述代碼是ok的
如果勾選了自動生成ui文件,上述代碼則會引起內存泄露
因為Qt已經給你生成了一個QMenuBar了;之前程序自己已經創建好了一個QMenuBar
當設置新的QMenuBar進來的時候,就會導致舊的
QMenuBar脫離了Qt的對象樹了.意味著后續就無法對這個對象進行釋放了;上述程序如果窗口關閉,對象樹釋放,此時進程也就結束了.
進程結束,自然所有內存都回收給系統,上述內存泄露也不會造成影響
但是如果這樣的代碼是出現在一個多窗口的程序中:
如果涉及到窗口的頻繁跳轉切換(窗口的頻繁創建銷毀),上述內存泄露就會更嚴重一些所以為了防止內存泄漏,修改為如下代碼:
QMenuBar* menuBar = this->menuBar();
1.如果QMenuBar已經存在,直接獲取并返回
2.如果QMenuBar不存在,就先創建一個新的,再返回
如果是獲取到已經存在的QMenuBar,這里的設置就是自己替換自己,
仍然在對象樹上
2.??具欄
????????更用QTooBar表示工具欄對象,一個窗口可以有多個工具欄,也可以沒有。工具欄往往也可以手動移動位置。
?Action如果出現在工具欄上,也會產生圖標覆蓋文本這樣的情況。
如果一個QAction既是QMenu的子元素,又是QToolBar的子元素,釋放的時候,只會釋放一次,不會重復delete。
代碼如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QToolBar>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 創建菜單欄QMenuBar* menuBar = this->menuBar();this->setMenuBar(menuBar);// 創建菜單QMenu* menu = new QMenu("文件");menuBar->addMenu(menu);// 工具欄是需要手動創建出來的. 自身不會自動創建.QToolBar* toolBar = new QToolBar();this->addToolBar(toolBar);// 創建兩個菜單項QAction* action1 = new QAction("保存");QAction* action2 = new QAction("打開");// action1->setToolTip("點擊這里保存文件");action1->setIcon(QIcon(":/save.png"));action2->setIcon(QIcon(":/open.png"));// 菜單項還可以放到菜單中menu->addAction(action1);menu->addAction(action2);// 菜單項放到工具欄中toolBar->addAction(action1);toolBar->addAction(action2);connect(action1, &QAction::triggered, this, &MainWindow::handle1);connect(action2, &QAction::triggered, this, &MainWindow::handle2);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle1()
{qDebug() << "handle1";
}void MainWindow::handle2()
{qDebug() << "handle2";
}
3.狀態欄
????????狀態欄是應?程序中輸出簡要信息的區域。。?般位于主窗?的最底部,?個窗?中最多只能有?個狀 態欄。
代碼如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QLabel>
#include <QProgressBar>
#include <QPushButton>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 存在就獲取, 不存在就創建QStatusBar* statusBar = this->statusBar();// 如果狀態欄沒有被創建, 這樣的設置是必要的.// 如果狀態欄已經在窗口中存在, 這樣的設置其實意義不大, 但是也沒副作用. 仍然保留.this->setStatusBar(statusBar);// 顯示一個臨時的信息.// statusBar->showMessage("這是一個狀態消息");// 給狀態欄中添加子控件QLabel* label = new QLabel("這是一個 QLabel");statusBar->addWidget(label);// QLabel* label2 = new QLabel("這個是另一個 QLabel");
// statusBar->addWidget(label2, 2);QProgressBar* progressBar = new QProgressBar();//這是進度條progressBar->setRange(0, 100);progressBar->setValue(50);statusBar->addWidget(progressBar);QPushButton* button = new QPushButton("按鈕");statusBar->addPermanentWidget(button);
}MainWindow::~MainWindow()
{delete ui;
}
4. 浮動窗口
????????在Qt中是使用QDockWidget來實現的。
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDockWidget>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 給主窗口添加一個子窗口.QDockWidget* dockWidget = new QDockWidget();// 使用 addDockWidget 方法, 把浮動窗口加入到子窗口中.this->addDockWidget(Qt::LeftDockWidgetArea, dockWidget);// 浮動窗口也是可以設置標題的.dockWidget->setWindowTitle("這是浮動窗口");// 給浮動窗口內部, 添加一些其他的控件.// 不能直接給這個浮動窗口添加子控件, 而是需要創建出一個單獨的 QWidget, 把要添加的控件加入到 QWidget 中.// 然后再把這個 QWidget 設置到 dockWidget 中.QWidget* container = new QWidget();dockWidget->setWidget(container);// 創建布局管理器, 把布局管理器設置到 QWidget 中QVBoxLayout* layout = new QVBoxLayout;container->setLayout(layout);// 創建其他控件添加到 layout 中.QLabel* label = new QLabel("這是一個 QLabel");QPushButton* button = new QPushButton("這是按鈕");layout->addWidget(label);layout->addWidget(button);// 設置浮動窗口允許停靠的位置dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::TopDockWidgetArea);
}MainWindow::~MainWindow()
{delete ui;
}
執行效果如下:
5. 對話框
????????Qt中使用QDialog類表示對話框,。Qt常 ?的內置對話框有:QFiledialog(?件對話框)、QColorDialog(顏?對話框)、QFontDialog (字體對話框)、QInputDialog(輸?對話框)和QMessageBox(消息框)。
????????基于QDialog作為父類創建出來的程序窗口和之前通過QWidget創建出來的非常相似的。
????????實際開發中,往往不是直接在創建項目的時候繼承自QDialog.而是在代碼中,創建額外的類,讓額外的類繼承自QDialog。
????????主窗口,一般不會作為一個對話框。主窗口可以再產生出一些其他的對話框。
一個簡單的例子:
????????主窗口中,通過點擊按鈕,彈出一個新的對話框。
????????QDialog其實也是QWidget的子類.QWidget的各種屬性方法,QDialog也能使用。不同于界面上的其他控件.此處QDialog每次按下按鈕,都會創建一個新的QDialog對象,并進行顯示。每次點擊都會創建新的對話框對象。
?????????一個程序運行過程中,可以無數次點擊這個按鈕,進一步的就產生出無數個這樣的對象了=>內存泄露
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{QDialog* dialog = new QDialog(this);dialog->setWindowTitle("對話框的標題");// 設置對話框的尺寸dialog->resize(400, 300);// 通過 show 方法就可以顯示出對話框.dialog->show();// delete dialog;// 正確做法應該是把 delete 和關閉按鈕的點擊信號關聯起來.// 在用戶點擊關閉的時候, 觸發 delete.// Qt 為了讓咱們寫的方便, 直接給 QDialog 設置了一個屬性, 可以通過設置屬性, 完成上述效果.dialog->setAttribute(Qt::WA_DeleteOnClose);//通過設置屬性,在進行關閉對話框操作的時候處罰delete內存的操作
}
5.1 自定義對話框
????????要想自定義對話框,就需要繼承自QDialog創建類:
1)純代碼的方式來自定義QDialog界面
2)通過圖形化的方式
5.2 model(bool)
模態 / 非模態
????????模態:彈出對話框的時候,此時用戶無法操作父窗口.必須得完成對話框內部出的操作,關閉對話框之后。exec
????????非模態:彈出對話框的時候,用戶可以操作父窗口。show
5.3?Qt內置對話框
????????Qt提供了多種可復?的對話框類型,即Qt標準對話框。Qt標準對話框全部繼承于QDialog類。常? 標準對話框如下:
消息對話框QMessageBox:
????????用來顯示一個消息給用戶,并且讓用戶進行一個簡單的選擇;
? ? ? ? 借助靜態函數構造消息對話框
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{int result = QMessageBox::information(this, "對話框標題", "對話框文本", QMessageBox::Ok | QMessageBox::Cancel);if (result == QMessageBox::Ok) {qDebug() << "Ok";} else if (result == QMessageBox::Cancel) {qDebug() << "Cancel";}
}
5.4?顏?對話框QColorDialog
????????顏?對話框的功能是允許??選擇顏?。繼承?QDialog類。
void MainWindow::on_pushButton_clicked()
{
// QColorDialog* dialog = new QColorDialog(this);
// dialog->exec();
// delete dialog;// 函數的返回值就是用戶選擇的顏色.QColor color = QColorDialog::getColor(QColor(0, 255, 0), this, "選擇顏色");qDebug() << color;
// getColor() 這個函數就能夠彈出一個模態對話框.用戶選擇顏色之后,點擊確定,
// 對話框關閉getcolor返回的值就是用戶選擇的顏色值!!
// 靜態函數static.QMessageBoxwarning不必創建對話框對象,就可以直接使用// 可以基于用戶選擇的顏色, 修改窗口的背景色.// 可以通過 QSS 的方式設置背景色.
// QString style = "background-color: rgb(" + QString::number(color.red()) + ", " + QString::number(color.green())
// + ", " + QString::number(color.blue()) + ");";char style[1024] = { 0 };sprintf(style, "background-color: rgb(%d, %d, %d);", color.red(), color.green(), color.blue());this->setStyleSheet(style);
}
上述是對顏色框樣式的設置。
5.5 ?件對話框QFileDialog
????????通過QFileDialog可以選擇一個文件.能夠獲取到這個文件的路徑打開文件/保存文件
void MainWindow::on_pushButton_clicked()
{QString filePath = QFileDialog::getOpenFileName(this);qDebug() << filePath;
}void MainWindow::on_pushButton_2_clicked()
{QString filePath = QFileDialog::getSaveFileName(this);qDebug() << filePath;
}
5.6 字體對話框QFontDialog
bool ok = false;QFont font = QFontDialog::getFont(&ok);qDebug() << "ok = " << ok;// qDebug() << font;qDebug() << font.family();qDebug() << font.pointSize();qDebug() << font.bold();qDebug() << font.italic();ui->pushButton->setFont(font);
5,7?輸?對話框QInputDialog
????????讓用戶輸入一個具體的數據,可以是整數,可以是浮點數,還可以是字符串.(以類似于下拉框)
ps:謝謝觀看!!!