以下通過編寫一個簡單的記事本程序葛闷,來學(xué)習(xí)如何使用Qt Widgets卫键。
最終效果
創(chuàng)建項目
在菜單欄中選擇 文件 > 新建文件或項目递鹉,打開引導(dǎo)窗口 New File or Project
在 New File or Project 窗口中選擇 Application > Qt Widgets Application 后馏鹤,點擊 Choose... 按鈕進入下一步米绕,填寫項目名稱和項目路徑
點擊 下一步 后垢村,選擇構(gòu)建工具割疾,此處我們選擇 qmake
點擊 下一步 后,生成項目時的類文件信息嘉栓,此處我們將 Class name 修改為 Notepad宏榕,Base class 這一項選擇繼承哪一個基類,可選擇 QMainWindow侵佃、QWidget麻昼、QDialog。
- QMainWindow - 提供一個有菜單條馋辈、錨接窗口(例如工具條)和一個狀態(tài)條的主應(yīng)用程序窗口抚芦,是最常見的窗口形式,可以作為GUI程序的主窗口首有。
- QWidget - 是所有用戶界面對象的基類燕垃。所有窗口或者控件都直接或間接繼承自QWidget類。
-
QDialog - 是對話框窗口的基類井联。主要用于短期任務(wù)以及和用戶進行簡要通訊的頂級窗口卜壕。
類信息
點擊 下一步 后,選擇構(gòu)建套件烙常,在這里我已提前安裝了Qt 5.13.1轴捎,選中即可
最后 下一步 > 完成,項目便創(chuàng)建完成蚕脏。
Qt Widgets Application 向?qū)槲覀儎?chuàng)建好初始的項目文件:
- notepad.pro - 工程文件侦副,用來告訴
qmake
如何創(chuàng)建Makefile
- main.cpp - 應(yīng)用程序主源文件,main函數(shù)便寫在該文件中
- notepad.h - Notepad類的頭文件
- notepad.cpp - Notepad類的源文件
- notepad.ui - UI窗體描述文件驼鞭,該文件是一個xml文件
點擊運行按鈕秦驯,啟動一下
設(shè)計界面
創(chuàng)建完項目后,Qt Creator 為我們生成了一個notepad.ui
文件挣棕,該文件為UI窗體描述文件译隘。
構(gòu)建應(yīng)用時亲桥,Qt Creator會啟動uic
讀取ui文件并創(chuàng)建出一個對應(yīng)的頭文件,本項目中的頭文件是ui_notepad.h
固耘。
在開始設(shè)計界面前题篷,先準備好圖片資源。
首先厅目,我們需要添加圖片資源番枚,在當(dāng)前項目目錄/data/study/notepad
下創(chuàng)建目錄images
并將需要用到的圖片放置在其中。然后切換至編輯模式损敷,在項目名上點擊右鍵選擇 Add New...
在新建文件對話框中選擇 Qt > Qt Resource File 點擊 Choose...葫笼,進入新建資源文件向?qū)?br>
填寫資源文件的名稱res
,并指定路徑為當(dāng)前項目路徑/data/study/notepad
后嗤锉,點擊下一步 > 完成渔欢。
完成資源文件的創(chuàng)建后,在左側(cè)項目瀏覽器中能看到一個名為res.qrc
的文件瘟忱,現(xiàn)在我們打開該文件奥额,將圖片添加進去
下面,雙擊 notepad.ui
進入設(shè)計模式访诱。
先添加一個文本框垫挨,在左側(cè)選擇 Input Widgets > Text Edit 后拖拽至主窗體中
選中主窗體,點擊工具欄中的 垂直布局 或使用快捷鍵 Ctrl + L
雙擊 在這里輸入 触菜,分別輸入 &File
和 &Edit
九榔,創(chuàng)建兩個菜單 File 和 Edit。& 符號緊跟著的字母為快捷鍵涡相,故此處 File 菜單快捷是 F哲泊,Edit 菜單快捷鍵是 E。
為菜單 File 添加子菜單 New催蝗、Open切威、Save、SaveAs丙号、Exit先朦。
為菜單 Edit 添加子菜單 Undo、Redo犬缨、Font喳魏、Copy、Cut怀薛、Paste刺彩。
觀察設(shè)計器底部 Action Editor,這些是菜單的動作
雙擊每個動作,為它們添加圖標(biāo)迂苛,由于我們已經(jīng)將圖片資源加載進來了三热,現(xiàn)在可以在圖標(biāo)一項中使用 選擇資源...
接下來,我們要為記事本添加工具欄三幻。
在菜單與文本框之間的空白處右鍵,并選擇 添加工具欄呐能,下圖中紅色區(qū)域便是添加的工具欄
將 Action Editor 中的動作拖拽至工具欄中念搬。
自此,設(shè)計部分結(jié)束摆出,下面該進行編碼朗徊。
編寫代碼
首先,打開 notepad.h
定義記事本的操作
#ifndef NOTEPAD_H
#define NOTEPAD_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class Notepad; }
QT_END_NAMESPACE
class Notepad : public QMainWindow
{
Q_OBJECT // (1)
public:
Notepad(QWidget *parent = nullptr);
~Notepad();
private slots: // (2)
void newFile();
void open();
void save();
void saveAs();
void exit();
void copy();
void cut();
void paste();
void undo();
void redo();
void selectFont();
private:
Ui::Notepad *ui;
QString currentFile;
};
#endif // NOTEPAD_H
(1) Q_OBJECT
是Qt中定義的宏偎漫,只有直接或間接繼承 QObject
類才可以使用爷恳,只有使用了該宏才具有信號槽機制。當(dāng)前類 Notepad
繼承自 QMainWindow
象踊,而 QMainWindow
繼承自 QWidget
即間接繼承了 QObject
温亲,所有我們才能定義槽函數(shù)
(2) 以下從 void newFile()
至 void selectFont()
均為槽函數(shù)
打開 notepad.cpp
實現(xiàn)操作代碼
#include "notepad.h"
#include "ui_notepad.h"
#include <QFileDialog>
#include <QFontDialog>
#include <QMessageBox>
#include <QTextStream>
Notepad::Notepad(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::Notepad)
{
ui->setupUi(this);
this->setCentralWidget(ui->textEdit);
connect(ui->actionNew, &QAction::triggered, this, &Notepad::newFile); // (1)
connect(ui->actionOpen, &QAction::triggered, this, &Notepad::open);
connect(ui->actionSave, &QAction::triggered, this, &Notepad::save);
connect(ui->actionSaveAs, &QAction::triggered, this, &Notepad::saveAs);
connect(ui->actionExit, &QAction::triggered, this, &Notepad::exit);
connect(ui->actionCopy, &QAction::triggered, this, &Notepad::copy);
connect(ui->actionCut, &QAction::triggered, this, &Notepad::cut);
connect(ui->actionPaste, &QAction::triggered, this, &Notepad::paste);
connect(ui->actionUndo, &QAction::triggered, this, &Notepad::undo);
connect(ui->actionRedo, &QAction::triggered, this, &Notepad::redo);
connect(ui->actionFont, &QAction::triggered, this, &Notepad::selectFont);
}
Notepad::~Notepad()
{
delete ui;
}
void Notepad::newFile()
{
currentFile.clear();
ui->textEdit->setText(QString());
}
void Notepad::open()
{
QString fileName = QFileDialog::getOpenFileName(this, "打開文件");
if (fileName.isEmpty()) {
return;
}
QFile file(fileName);
currentFile = fileName;
if (!file.open(QIODevice::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, "警告", "不能打開: " + file.errorString());
return;
}
setWindowTitle(fileName);
QTextStream in(&file);
QString text = in.readAll();
ui->textEdit->setText(text);
file.close();
}
void Notepad::save()
{
QString fileName;
if (currentFile.isEmpty()) {
fileName = QFileDialog::getSaveFileName(this, "保存");
currentFile = fileName;
} else {
fileName = currentFile;
}
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, "警告", "不能保存: " + file.errorString());
return;
}
setWindowTitle(fileName);
QTextStream out(&file);
QString text = ui->textEdit->toPlainText();
out << text;
file.close();
}
void Notepad::saveAs()
{
QString fileName = QFileDialog::getSaveFileName(this, "另存為...");
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, "警告", "不能保存: " + file.errorString());
return;
}
currentFile = fileName;
setWindowTitle(fileName);
QTextStream out(&file);
QString text = ui->textEdit->toPlainText();
out << text;
file.close();
}
void Notepad::exit()
{
QCoreApplication::quit();
}
void Notepad::copy()
{
ui->textEdit->copy();
}
void Notepad::cut()
{
ui->textEdit->cut();
}
void Notepad::paste()
{
ui->textEdit->paste();
}
void Notepad::undo()
{
ui->textEdit->undo();
}
void Notepad::redo()
{
ui->textEdit->redo();
}
void Notepad::selectFont()
{
bool fontSelected;
QFont font = QFontDialog::getFont(&fontSelected, this);
if (fontSelected)
ui->textEdit->setFont(font);
}
(1) 此處是綁定信號,將 New 菜單的 triggered 信號綁定至當(dāng)前類中的 newFile 槽函數(shù)杯矩,當(dāng)點擊了 New 菜單后栈虚,newFile 函數(shù)便會執(zhí)行。
之后史隆,就可以運行了魂务,當(dāng)然,代碼并不健壯泌射,有興趣的可以自己完善一下粘姜。