柚子快報邀請碼778899分享:java QT概述簡介
柚子快報邀請碼778899分享:java QT概述簡介
一、QT
1、什么是QT
是一個跨平臺的C++應用程序開發(fā)框架
具有短平快的優(yōu)秀特質: 投資少、周期短、見效快、效益高
幾乎支持所有的平臺, 可用于桌面程序開發(fā)以及嵌入式開發(fā)
有屬于自己的事件處理機制
可以高效率的開發(fā)基于窗口的應用程序。
Qt是標準 C++ 的擴展, C++的語法在Qt中都是支持的
良好封裝機制使得 Qt 的模塊化程度非常高,可重用性較好,可以快速上手。
Qt 提供了一種稱為 signals/slots 的安全類型來替代 callback(回調函數),這使得各個元件 之間的協(xié)同工作變得十分簡單。
2、QT的特點
廣泛用于開發(fā)GUI程序,也可用于開發(fā)非GUI程序。
GUI = Graphical User Interface ----> 也就是基于窗口的應用程序開發(fā)。
有豐富的 API
Qt 包括多達 250 個以上的 C++ 類
可以處理正則表達式。
支持 2D/3D 圖形渲染,支持 OpenGL
Qt給程序猿提供了非常詳細的官方文檔
支持XML,Json
框架底層模塊化, 使用者可以根據需求選擇相應的模塊來使用
可以輕松跨平臺 ---> 和Java的跨平臺方式不同
在不同的平臺使用的是相同的上層接口,但是在底層封裝了不同平臺對應的API(暗度陳倉)。
3、QT的模塊
Qt類庫里大量的類根據功能分為各種模塊,這些模塊又分為以下幾大類:
Qt 基本模塊(Qt Essentials):提供了 Qt 在所有平臺上的基本功能。
Qt 附加模塊(Qt Add-Ons):實現(xiàn)一些特定功能的提供附加價值的模塊。
增值模塊(Value-AddModules):單獨發(fā)布的提供額外價值的模塊或工具。
技術預覽模塊(Technology Preview Modules):一些處于開發(fā)階段,但是可以作為技術預覽使用的模塊。
Qt 工具(Qt Tools):幫助應用程序開發(fā)的一些工具。
Qt官網或者幫助文檔的“All Modules”頁面可以查看所有這些模塊的信息。以下是官方對Qt基本模塊的描述。關于其他模塊感興趣的話可以自行查閱。于其他模塊感興趣的話可以自行查閱。
模塊 描述 Qt Core Qt 類庫的核心,所有其他模塊都依賴于此模塊 Qt GUI 設計 GUI 界面的基礎類,包括 OpenGL Qt Multimedia 音頻、視頻、攝像頭和廣播功能的類 Qt Multimedia Widgets 實現(xiàn)多媒體功能的界面組件類 Qt Network 使網絡編程更簡單和輕便的類 Qt QML 用于 QML 和 JavaScript語言的類 Qt Quick 用于構建具有定制用戶界面的動態(tài)應用程序的聲明框架 Qt Quick Controls 創(chuàng)建桌面樣式用戶界面,基于 Qt Quick 的用戶界面控件 Qt Quick Dialogs 用于 Qt Quick 的系統(tǒng)對話框類型 Qt Quick Layouts 用于 Qt Quick 2 界面元素的布局項 Qt SQL 使用 SQL 用于數據庫操作的類 Qt Test 用于應用程序和庫進行單元測試的類 Qt Widgets 用于構建 GUI 界面的 C++ 圖形組件類
4、QT案例
Qt發(fā)展至今已經是一個非常成熟的框架,基于這個框架許多公司開發(fā)出了很多優(yōu)秀的軟件,下邊給大家介紹幾款我們常見到的軟件:
VirtualBox:虛擬機軟件。
VLC多媒體播放器:一個體積小巧、功能強大的開源媒體播放器。
YY語音:又名“歪歪語音”,是一個可以進行在線多人語音聊天和語音會議的免費軟件。
咪咕音樂:咪咕音樂是中國移動傾力打造的正版音樂播放器
WPS Office:金山公司(Kingsoft)出品的辦公軟件,與微軟Office兼容性良好,個人版免費。
Skype:一個使用人數眾多的基于P2P的VOIP聊天軟件。
5、QtCreator
QtCreator是編寫Qt程序默認使用的一款 IDE,使用VS寫Qt程序也是可以的,在此不做介紹。
使用QtCreator創(chuàng)建的項目目錄中不能包含中文QtCreator默認使用Utf8格式編碼對文件字符進行編碼
字符必須編碼后才能被計算機處理為了處理漢字,程序員設計了用于簡體中文的GB2312和用于繁體中文的big5。GB2312 支持的漢字太少,1995年的漢字擴展規(guī)范GBK1.0,支持了更多的漢字。2000年的 GB18030取代了GBK1.0成為了正式的國家標準。Unicode 也是一種字符編碼方法,不過它是由國際組織設計,可以容納全世界所有語言文字的編碼方案
utf8utf16
vs寫Qt程序默認使用的本地編碼 -> gbk修改QtCreator的編碼, 菜單欄 -> 工具
關于這些編譯套件跟大家做一個介紹,安裝過程中根據自己的情況酌情選擇即可。
MSVC2015 64-bit: Visual Studio 2015 使用的64位編譯套件
MSVC2017 32-bit: Visual Studio 2017 使用的32位編譯套件
MSVC2017 64-bit: Visual Studio 2017 使用的64位編譯套件
MinGW7.3.0 32-bit: QtCreator 使用的32位編譯套件
MinGW7.3.0 64-bit: QtCreator 使用的64位編譯套件
UWP –> Universal Windows Platform: 用于window平臺應用程序開發(fā)的編譯套件
UWP 即Windows通用應用平臺,在Windows 10 Mobile/Surface(Windows平板電腦)/ PC/Xbox/HoloLens等平臺上運行,uwp不同于傳統(tǒng)pc上的exe應用,也跟只適用于手機端的app有本質區(qū)別。它并不是為某一個終端而設計,而是可以在所有Windows10設備上運行。
在這個窗口中除了選擇必要的編譯套件,還有一些非必要組件,常用的有以下兩個:
Source: Qt源碼, 另外Qt的一些模塊運行需要的驅動沒有提供現(xiàn)成的動態(tài)庫需要自己編譯, 建議安裝
Qt Charts: 用于繪制統(tǒng)計數據對應的圖表, 比如: 折線圖/曲線圖等
默認的編譯套件
MinGW -> Minimalist GNU for Windows
MinGW 提供了一套簡單方便的Windows下的基于GCC 程序開發(fā)環(huán)境。MinGW 收集了一系列免費的Windows 使用的頭文件和庫文件;整合了GNU的工具集,特別是GNU 程序開發(fā)工具,如經典gcc, g++, make等。MinGW是完全免費的自由軟件,它在Windows平臺上模擬了Linux下GCC的開發(fā)環(huán)境,為C++ 的跨平臺開發(fā)提供了良好基礎支持,為了在Windows下工作的程序員熟悉Linux下的C++工程組織提供了條件。
二、創(chuàng)建第一個QT工程
1、創(chuàng)建項目
創(chuàng)建基于窗口的QT應用程序
指定項目的存儲路徑
注意: 項目名稱根據需求自己指定即可
在指定項目的存儲路徑的時候, 路徑中不能包含中文, 不能包含中文, 不能包含中文
指定默認的窗口類的名字以及窗口的類型
2、工程詳解
(1).pro文件
QT += core gui
# 用的模塊QT基本模塊 core 和 GUI模塊
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# CONFIG += c++11 ----> 告訴qmake 應用程序 相關的配置信息
# ----- 我的工程使用 c++ 11 的標準和特性
# += -----> 在原有的基礎上進行添加的意思
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
(2) mainwindow.h
聲明?。。?/p>
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
QT_BEGIN_NAMESPACE
// mainwindow.ui 文件中也有一個類叫 MainWindow, 將這個類放到命名空間 Ui 中
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT // 這個宏是為了能夠使用Qt中的信號槽機制
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui; // 定義指針指向窗口的 UI 對象
};
#endif // MAINWINDOW_H
(3)mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
//會自動調用該類的 構造函數
//這個就是窗口的構造函數 ---> 實現(xiàn)整個UI
// 將 mainwindow.ui 的實例對象和 當前類的對象進行關聯(lián)
// 這樣同名的連個類對象就產生了關聯(lián), 合二為一了
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
(4)main.cpp
#include "mainwindow.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
(5)mainwindow.ui
三、QT中的窗口類
我們在通過Qt向導窗口基于窗口的應用程序的項目過程中倒數第二步讓我們選擇跟隨項目創(chuàng)建的第一個窗口的基類, 下拉菜單中有三個選項,
分別為: QMainWindow、QDialog、QWidget如下圖:
1、基礎窗口類
常用的窗口類有3個
在創(chuàng)建Qt窗口的時候, 需要讓自己的窗口類繼承上述三個窗口類的其中一個
QWidget
所有窗口類的基類Qt中的控件(按鈕, 輸入框, 單選框…)也屬于窗口, 基類都是QWidget可以內嵌到其他窗口中: 沒有邊框可以不內嵌單獨顯示: 獨立的窗口, 有邊框
QDialog
對話框類, 后邊的章節(jié)會具體介紹這個窗口不能內嵌到其他窗口中
QMainWindow
有工具欄, 狀態(tài)欄, 菜單欄, 后邊的章節(jié)會具體介紹這個窗口不能內嵌到其他窗口中
2、窗口的顯示
內嵌窗口
依附于某一個大的窗口, 作為了大窗口的一部分大窗口就是這個內嵌窗口的父窗口父窗口顯示的時候, 內嵌的窗口也就被顯示出來了
不內嵌窗口
這類窗口有邊框, 有標題欄需要調用函數才可以顯示
// QWidget是所有窗口類的基類, 調用這個提供的 show() 方法就可以顯示將任何窗口顯示出來
// 非模態(tài)顯示
void QWidget::show(); // 顯示當前窗口和它的子窗口
// 對話框窗口的非模態(tài)顯示: 還是調用show() 方法
// 對話框窗口的模態(tài)顯示
[virtual slot] int QDialog::exec();
四、坐標體系
1、窗口的坐標原點
所有坐標的確定都需要先找到坐標原點, Qt的坐標原點在窗口的左上角
x軸向右遞增 y軸向下遞增
2、窗口的相對坐標
在一個Qt窗口中一般都有很多子窗口內嵌到這個父窗口中,其中每個窗口都有自己的坐標原點,子窗口的位置也就是其使用的坐標點就是它的父窗口坐標體系中的坐標點。
在Qt的某一個窗口中有可能有若干個控件, 這個控件都是嵌套的關系
A窗口包含B窗口, B窗口包含C窗口
每個窗口都有坐標原點, 在左上角
子窗口的位置是基于父窗口的坐標體系來確定的, 也就是說通過父窗口左上角的坐標點來確定自己的位置
Qt中窗口顯示的時候使用的相對坐標, 相對于自己的父窗口將子窗口移動到父窗口的某個位置
// 所有窗口類的基類: QWidget
// QWidget中提供了移動窗口的 API函數
// 參數 x, y是要移動的窗口的左上角的點, 窗口的左上角移動到這個坐標點
void QWidget::move(int x, int y);
void QWidget::move(const QPoint &);
五、內存回收 了解
在Qt中創(chuàng)建對象的時候會提供一個 Parent對象指針(可以查看類的構造函數),下面來解釋這個parent到底是干什么的。
QObject是以對象樹的形式組織起來的。當你創(chuàng)建一個QObject對象時,會看到QObject的構造函數接收一個QObject指針作為參數,這個參數就是 parent,也就是父對象指針。
這相當于,在創(chuàng)建QObject對象時,可以提供一個其父對象,我們創(chuàng)建的這個QObject對象會自動添加到其父對象的children()列表。當父對象析構的時候,這個列表中的所有對象也會被析構。(注意,這里的父對象并不是繼承意義上的父類?。? ----> C++ 虛析構?。?!
QWidget是能夠在屏幕上顯示的一切組件的父類。QWidget繼承自QObject,因此也繼承了這種對象樹關系。一個孩子自動地成為父組件的一個子組件。因此,它會顯示在父組件的坐標系統(tǒng)中,被父組件的邊界剪裁。例如,當用戶關閉一個對話框的時候,應用程序將其刪除,那么,我們希望屬于這個對話框的按鈕、圖標等應該一起被刪除。事實就是如此,因為這些都是對話框的子組件。
Qt 引入對象樹的概念,在一定程度上解決了內存問題。
當一個QObject對象在堆上創(chuàng)建的時候,Qt 會同時為其創(chuàng)建一個對象樹。不過,對象樹中對象的順序是沒有定義的。這意味著,銷毀這些對象的順序也是未定義的。
任何對象樹中的 QObject對象 delete 的時候,如果這個對象有 parent,則自動將其從 parent 的children()列表中刪除;如果有孩子,則自動 delete 每一個孩子。Qt 保證沒有QObject會被 delete 兩次,這是由析構順序決定的。
綜上所述, 我們可以得到一個結論: Qt中有內存回收機制, 但是不是所有被new出的對象被自動回收, 滿足條件才可以回收, 如果想要在Qt中實現(xiàn)內存的自動回收, 需要滿足以下兩個條件:
創(chuàng)建的對象必須是QObject類的子類(間接子類也可以)
QObject類是沒有父類的, Qt中有很大一部分類都是從這個類派生出去的
Qt中使用頻率很高的窗口類和控件都是 QObject 的直接或間接的子類其他的類可以自己查閱Qt幫助文檔
創(chuàng)建出的類對象, 必須要指定其父對象是誰, 一般情況下有兩種操作方式:
// 方式1: 通過構造函數
// parent: 當前窗口的父對象, 找構造函數中的 parent 參數即可
QWidget::QWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
QTimer::QTimer(QObject *parent = nullptr);
// 方式2: 通過setParent()方法
// 假設這個控件沒有在構造的時候指定符對象, 可以調用QWidget的api指定父窗口對象
void QWidget::setParent(QWidget *parent);
void QObject::setParent(QObject *parent);
六、數據類型
因為Qt是一個C++ 框架, 因此C++中所有的語法和數據類型在Qt中都是被支持的, 但是Qt中也定義了一些屬于自己的數據類型, 下邊給大家介紹一下這些基礎的數類型。
QT基本數據類型定義在#include 中,QT基本數據類型有:
類型名稱 注釋 備注 qint8 signed char 有符號8位數據 qint16 signed short 16位數據類型 qint32 signed int 32位有符號數據類型 qint64 long long int 或(__int64) 64位有符號數據類型,Windows中定義為__int64 qintptr qint32 或 qint64 指針類型 根據系統(tǒng)類型不同而不同,32位系統(tǒng)為qint32、64位系統(tǒng)為qint64 qlonglong long long int 或(__int64) Windows中定義為__int64 qptrdiff qint32 或 qint64 根據系統(tǒng)類型不同而不同,32位系統(tǒng)為qint32、64位系統(tǒng)為qint64 qreal double 或 float 除非配置了-qreal float選項,否則默認為double quint8 unsigned char 無符號8位數據類型 quint16 unsigned short 無符號16位數據類型 quint32 unsigned int 無符號32位數據類型 quint64 unsigned long long int 或 (unsigned __int64) 無符號64比特數據類型,Windows中定義為unsigned __int64 quintptr quint32 或 quint64 根據系統(tǒng)類型不同而不同,32位系統(tǒng)為quint32、64位系統(tǒng)為quint64 qulonglong unsigned long long int 或 (unsigned __int64) Windows中定義為__int64 uchar unsigned char 無符號字符類型 uint unsigned int 無符號整型 ulong unsigned long 無符號長整型 ushort unsigned short 無符號短整型
雖然在Qt中有屬于自己的整形或者浮點型, 但是在變成過程中這些一般不用, 常用的類型關鍵字還是 C/C++中的 int, float, double 等。
七、log日志
1 在調試窗口中輸入日志
在Qt中進行l(wèi)og輸出, 一般不使用c中的printf, 也不是使用C++中的cout, Qt框架提供了專門用于日志輸出的類, 頭文件名為 QDebug, 使用方法如下:
#include
// 包含了QDebug頭文件, 直接通過全局函數 qDebug() 就可以進行日志輸出了
qDebug() << " abcdefg" << endl;
qDebug() << "Date:" << QDate::currentDate();
qDebug() << "Types:" << QString("String") << QChar('x');
// 和全局函數 qDebug() 類似的日志函數還有: qWarning(), qInfo(), qCritical()
int num = 666;
float i = 11.11f;
qWarning() << "num = " << num << " i = " << i;
qInfo() << "num = " << num << " i = " << i;
qCritical() << "num = " << num << " i = " << i;
八、字符串類型
在Qt中不僅支持C, C++中的字符串類型, 而且還在框架中定義了專屬的字符串類型, 我們必須要掌握在Qt中關于這些類型的使用和相互之間的轉換。
語言類型 字符串類型 C char * C++ std::string, char * Qt QByteArray, QString 等
1、QByteArray
在Qt中QByteArray可以看做是c語言中 char*的升級版本。
我們在使用這種類型的時候可通過這個類的構造函數申請一塊動態(tài)內存,用于存儲我們需要處理的字符串數據。
下面給大家介紹一下這個類中常用的一些API函數,大家要養(yǎng)成遇到問題主動查詢幫助文檔的好習慣。
(1)構造
// 構造一個空字符串對象
QString::QString();
// 將 char* 字符串 轉換為 QString 類型
QString::QString(const char *str);
// 將 QByteArray 轉換為 QString 類型
QString::QString(const QByteArray &ba);
// 其他重載的同名構造函數可參考Qt幫助文檔, 此處略
(2)數據操作
// 尾部追加數據
// 其他重載的同名函數可參考Qt幫助文檔, 此處略
QString &QString::append(const QString &str);
QString &QString::append(const char *str);
QString &QString::append(const QByteArray &ba);
void QString::push_back(const QString &other);
// 頭部添加數據
// 其他重載的同名函數可參考Qt幫助文檔, 此處略
QString &QString::prepend(const QString &str);
QString &QString::prepend(const char *str);
QString &QString::prepend(const QByteArray &ba);
void QString::push_front(const QString &other);
// 插入數據, 將 str 插入到字符串第 position 個字符的位置(從0開始)
// 其他重載的同名函數可參考Qt幫助文檔, 此處略
QString &QString::insert(int position, const QString &str);
QString &QString::insert(int position, const char *str);
QString &QString::insert(int position, const QByteArray &str);
// 刪除數據
// 從大字符串中刪除len個字符, 從第pos個字符的位置開始刪除
QString &QString::remove(int position, int n);
// 從字符串的尾部刪除 n 個字符
void QString::chop(int n);
// 從字節(jié)串的 position 位置將字符串截斷 (前邊部分留下, 后邊部分被刪除)
void QString::truncate(int position);
// 將對象中的數據清空, 使其為null
void QString::clear();
// 字符串替換
// 將字節(jié)數組中的 子字符串 before 替換為 after
// 參數 cs 為是否區(qū)分大小寫, 默認區(qū)分大小寫
// 其他重載的同名函數可參考Qt幫助文檔, 此處略
QString &QString::replace(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
(3)子字符串查找和判斷
// 參數 cs 為是否區(qū)分大小寫, 默認區(qū)分大小寫
// 其他重載的同名函數可參考Qt幫助文檔, 此處略
// 判斷字符串中是否包含子字符串 str, 包含返回true, 否則返回false
bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
// 判斷字符串是否以字符串 ba 開始, 是返回true, 不是返回false
bool QString::startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
// 判斷字符串是否以字符串 ba 結尾, 是返回true, 不是返回false
bool QString::endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
(4)遍歷
// 使用迭代器
iterator QString::begin();
iterator QString::end();
// 使用數組的方式進行遍歷
// i的取值范圍 0 <= position < size()
const QChar QString::at(int position) const
const QChar QString::operator[](int position) const;
(5)查看字節(jié)數
// 返回字節(jié)數組對象中字符的個數 (字符個數和字節(jié)個數是不同的概念)
int QString::length() const;
int QString::size() const;
int QString::count() const;
// 返回字節(jié)串對象中 子字符串 str 出現(xiàn)的次數
// 參數 cs 為是否區(qū)分大小寫, 默認區(qū)分大小寫
int QString::count(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
(6)類型轉換
// 將int, short, long, float, double 轉換為 QString 類型
// 其他重載的同名函數可參考Qt幫助文檔, 此處略
QString &QString::setNum(int n, int base = 10);
QString &QString::setNum(short n, int base = 10);
QString &QString::setNum(long n, int base = 10);
QString &QString::setNum(float n, char format = 'g', int precision = 6);
QString &QString::setNum(double n, char format = 'g', int precision = 6);
[static] QString QString::number(long n, int base = 10);
[static] QString QString::number(int n, int base = 10);
[static] QString QString::number(double n, char format = 'g', int precision = 6);
// 將 QString 轉換為 int, short, long, float, double 類型
int QString::toInt(bool *ok = Q_NULLPTR, int base = 10) const;
short QString::toShort(bool *ok = Q_NULLPTR, int base = 10) const;
long QString::toLong(bool *ok = Q_NULLPTR, int base = 10) const
float QString::toFloat(bool *ok = Q_NULLPTR) const;
double QString::toDouble(bool *ok = Q_NULLPTR) const;
// 將標準C++中的 std::string 類型 轉換為 QString 類型
[static] QString QString::fromStdString(const std::string &str);
// 將 QString 轉換為 標準C++中的 std::string 類型
std::string QString::toStdString() const;
// QString -> QByteArray
// 轉換為本地編碼, 跟隨操作系統(tǒng)
QByteArray QString::toLocal8Bit() const;
// 轉換為 Latin-1 編碼的字符串 不支持中文
QByteArray QString::toLatin1() const;
// 轉換為 utf8 編碼格式的字符串 (常用)
QByteArray QString::toUtf8() const;
// 所有字符轉換為大寫
QString QString::toUpper() const;
// 所有字符轉換為小寫
QString QString::toLower() const;
(7)字符串格式
// 其他重載的同名函數可參考Qt幫助文檔, 此處略
QString QString::arg(const QString &a,
int fieldWidth = 0,
QChar fillChar = QLatin1Char( ' ' )) const;
QString QString::arg(int a, int fieldWidth = 0,
int base = 10,
QChar fillChar = QLatin1Char( ' ' )) const;
// 示例程序
int i; // 假設該變量表示當前文件的編號
int total; // 假設該變量表示文件的總個數
QString fileName; // 假設該變量表示當前文件的名字
// 使用以上三個變量拼接一個動態(tài)字符串
QString status = QString("Processing file %1 of %2: %3")
.arg(i).arg(total).arg(fileName);
九、QVariant
QVariant這個類很神奇,或者說方便。很多時候,需要幾種不同的數據類型需要傳遞,如果用結構體,又不大方便,容器保存的也只是一種數據類型,而QVariant則可以統(tǒng)統(tǒng)搞定。
QVariant 這個類型充當著最常見的數據類型的聯(lián)合。QVariant 可以保存很多Qt的數據類型,包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、 QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize和QString,并且還有C++基本類型,如 int、float等。
1、標準類型
將標準類型轉換為QVariant類型
// 這類轉換需要使用QVariant類的構造函數, 由于比較多, 大家可自行查閱Qt幫助文檔, 在這里簡單寫幾個
QVariant::QVariant(int val);
QVariant::QVariant(bool val);
QVariant::QVariant(double val);
QVariant::QVariant(const char *val);
QVariant::QVariant(const QByteArray &val);
QVariant::QVariant(const QString &val);
......
// 使用設置函數也可以將支持的類型的數據設置到QVariant對象中
// 這里的 T 類型, 就是QVariant支持的類型
void QVariant::setValue(const T &value);
// 該函數行為和 setValue() 函數完全相同
[static] QVariant QVariant::fromValue(const T &value);
// 例子:
#if 1
QVariant v;
v.setValue(5);
#else
QVariant v = QVariant::fromValue(5);
#endif
int i = v.toInt(); // i is now 5
QString s = v.toString(); // s is now "5"
判斷 QVariant中封裝的實際數據類型
// 該函數的返回值是一個枚舉類型, 可通過這個枚舉判斷出實際是什么類型的數據
Type QVariant::type() const;
將QVariant對象轉換為實際的數據類型
// 如果要實現(xiàn)該操作, 可以使用QVariant類提供的 toxxx() 方法, 全部轉換可以參考Qt幫助文檔
// 在此舉列舉幾個常用函數:
bool QVariant::toBool() const;
QByteArray QVariant::toByteArray() const;
double QVariant::toDouble(bool *ok = Q_NULLPTR) const;
float QVariant::toFloat(bool *ok = Q_NULLPTR) const;
int QVariant::toInt(bool *ok = Q_NULLPTR) const;
QString QVariant::toString() const;
......
十、位置和尺寸
在QT中我們常見的 點, 線, 尺寸, 矩形 都被進行了封裝, 下邊依次為大家介紹相關的類。
1、QPoint
QPoint類封裝了我們常用用到的坐標點 (x, y), 常用的 API如下:
// 構造函數
// 構造一個坐標原點, 即(0, 0)
QPoint::QPoint();
// 參數為 x軸坐標, y軸坐標
QPoint::QPoint(int xpos, int ypos);
// 設置x軸坐標
void QPoint::setX(int x);
// 設置y軸坐標
void QPoint::setY(int y);
// 得到x軸坐標
int QPoint::x() const;
// 得到x軸坐標的引用
int &QPoint::rx();
// 得到y(tǒng)軸坐標
int QPoint::y() const;
// 得到y(tǒng)軸坐標的引用
int &QPoint::ry();
// 直接通過坐標對象進行算術運算: 加減乘除
QPoint &QPoint::operator*=(float factor);
QPoint &QPoint::operator*=(double factor);
QPoint &QPoint::operator*=(int factor);
QPoint &QPoint::operator+=(const QPoint &point);
QPoint &QPoint::operator-=(const QPoint &point);
QPoint &QPoint::operator/=(qreal divisor);
// 其他API請自行查詢Qt幫助文檔
2、QLine
QLine是一個直線類, 封裝了兩個坐標點 (兩點確定一條直線)
常用API如下:
// 構造函數
// 構造一個空對象
QLine::QLine();
// 構造一條直線, 通過兩個坐標點
QLine::QLine(const QPoint &p1, const QPoint &p2);
// 從點 (x1, y1) 到 (x2, y2)
QLine::QLine(int x1, int y1, int x2, int y2);
// 給直線對象設置坐標點
void QLine::setPoints(const QPoint &p1, const QPoint &p2);
// 起始點(x1, y1), 終點(x2, y2)
void QLine::setLine(int x1, int y1, int x2, int y2);
// 設置直線的起點坐標
void QLine::setP1(const QPoint &p1);
// 設置直線的終點坐標
void QLine::setP2(const QPoint &p2);
// 返回直線的起始點坐標
QPoint QLine::p1() const;
// 返回直線的終點坐標
QPoint QLine::p2() const;
// 返回值直線的中心點坐標, (p1() + p2()) / 2
QPoint QLine::center() const;
// 返回值直線起點的 x 坐標
int QLine::x1() const;
// 返回值直線終點的 x 坐標
int QLine::x2() const;
// 返回值直線起點的 y 坐標
int QLine::y1() const;
// 返回值直線終點的 y 坐標
int QLine::y2() const;
// 用給定的坐標點平移這條直線
void QLine::translate(const QPoint &offset);
void QLine::translate(int dx, int dy);
// 用給定的坐標點平移這條直線, 返回平移之后的坐標點
QLine QLine::translated(const QPoint &offset) const;
QLine QLine::translated(int dx, int dy) const;
// 直線對象進行比較
bool QLine::operator!=(const QLine &line) const;
bool QLine::operator==(const QLine &line) const;
// 其他API請自行查詢Qt幫助文檔
3、QSize
在QT中QSize類用來形容長度和寬度, 常用的API如下:
// 構造函數
// 構造空對象, 對象中的寬和高都是無效的
QSize::QSize();
// 使用寬和高構造一個有效對象
QSize::QSize(int width, int height);
// 設置寬度
void QSize::setWidth(int width)
// 設置高度
void QSize::setHeight(int height);
// 得到寬度
int QSize::width() const;
// 得到寬度的引用
int &QSize::rwidth();
// 得到高度
int QSize::height() const;
// 得到高度的引用
int &QSize::rheight();
// 交換高度和寬度的值
void QSize::transpose();
// 交換高度和寬度的值, 返回交換之后的尺寸信息
QSize QSize::transposed() const;
// 進行算法運算: 加減乘除
QSize &QSize::operator*=(qreal factor);
QSize &QSize::operator+=(const QSize &size);
QSize &QSize::operator-=(const QSize &size);
QSize &QSize::operator/=(qreal divisor);
// 其他API請自行查詢Qt幫助文檔
4、QRect
在Qt中使用 QRect類來描述一個矩形, 常用的API如下:
// 構造函數
// 構造一個空對象
QRect::QRect();
// 基于左上角坐標, 和右下角坐標構造一個矩形對象
QRect::QRect(const QPoint &topLeft, const QPoint &bottomRight);
// 基于左上角坐標, 和 寬度, 高度構造一個矩形對象
QRect::QRect(const QPoint &topLeft, const QSize &size);
// 通過 左上角坐標(x, y), 和 矩形尺寸(width, height) 構造一個矩形對象
QRect::QRect(int x, int y, int width, int height);
// 設置矩形的尺寸信息, 左上角坐標不變
void QRect::setSize(const QSize &size);
// 設置矩形左上角坐標為(x,y), 大小為(width, height)
void QRect::setRect(int x, int y, int width, int height);
// 設置矩形寬度
void QRect::setWidth(int width);
// 設置矩形高度
void QRect::setHeight(int height);
// 返回值矩形左上角坐標
QPoint QRect::topLeft() const;
// 返回矩形右上角坐標
// 該坐標點值為: QPoint(left() + width() -1, top())
QPoint QRect::topRight() const;
// 返回矩形左下角坐標
// 該坐標點值為: QPoint(left(), top() + height() - 1)
QPoint QRect::bottomLeft() const;
// 返回矩形右下角坐標
// 該坐標點值為: QPoint(left() + width() -1, top() + height() - 1)
QPoint QRect::bottomRight() const;
// 返回矩形中心點坐標
QPoint QRect::center() const;
// 返回矩形上邊緣y軸坐標
int QRect::top() const;
int QRect::y() const;
// 返回值矩形下邊緣y軸坐標
int QRect::bottom() const;
// 返回矩形左邊緣 x軸坐標
int QRect::x() const;
int QRect::left() const;
// 返回矩形右邊緣x軸坐標
int QRect::right() const;
// 返回矩形的高度
int QRect::width() const;
// 返回矩形的寬度
int QRect::height() const;
// 返回矩形的尺寸信息
QSize QRect::size() const;
十一、日期和時間
1、QDate
QDate類可以封裝日期信息也可以通過這個類得到日期相關的信息, 包括:年, 月, 日。
// 構造函數
QDate::QDate();
QDate::QDate(int y, int m, int d);
// 公共成員函數
// 重新設置日期對象中的日期
bool QDate::setDate(int year, int month, int day);
// 給日期對象添加 ndays 天
QDate QDate::addDays(qint64 ndays) const;
// 給日期對象添加 nmonths 月
QDate QDate::addMonths(int nmonths) const;
// 給日期對象添加 nyears 月
QDate QDate::addYears(int nyears) const;
// 得到日期對象中的年/月/日
int QDate::year() const;
int QDate::month() const;
int QDate::day() const;
void QDate::getDate(int *year, int *month, int *day) const;
// 日期對象格式化
/*
d - The day as a number without a leading zero (1 to 31)
dd - The day as a number with a leading zero (01 to 31)
ddd - The abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses the system locale to localize the name, i.e. QLocale::system().
dddd - The long localized day name (e.g. 'Monday' to 'Sunday'). Uses the system locale to localize the name, i.e. QLocale::system().
M - The month as a number without a leading zero (1 to 12)
MM - The month as a number with a leading zero (01 to 12)
MMM - The abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses the system locale to localize the name, i.e. QLocale::system().
MMMM - The long localized month name (e.g. 'January' to 'December'). Uses the system locale to localize the name, i.e. QLocale::system().
yy - The year as a two digit number (00 to 99)
yyyy - The year as a four digit number. If the year is negative, a minus sign is prepended, making five characters.
*/
QString QDate::toString(const QString &format) const;
// 操作符重載 ==> 日期比較
bool QDate::operator!=(const QDate &d) const;
bool QDate::operator<(const QDate &d) const;
bool QDate::operator<=(const QDate &d) const;
bool QDate::operator==(const QDate &d) const;
bool QDate::operator>(const QDate &d) const;
bool QDate::operator>=(const QDate &d) const;
// 靜態(tài)函數 -> 得到本地的當前日期
[static] QDate QDate::currentDate();
2、QTime
QTime類可以封裝時間信息也可以通過這個類得到時間相關的信息, 包括:時, 分, 秒, 毫秒。
// 構造函數
QTime::QTime();
/*
h ==> 取值范圍: 0 ~ 23
m and s ==> 取值范圍: 0 ~ 59
ms ==> 取值范圍: 0 ~ 999
*/
QTime::QTime(int h, int m, int s = 0, int ms = 0);
// 公共成員函數
// Returns true if the set time is valid; otherwise returns false.
bool QTime::setHMS(int h, int m, int s, int ms = 0);
QTime QTime::addSecs(int s) const;
QTime QTime::addMSecs(int ms) const;
// 示例代碼
QTime n(14, 0, 0); // n == 14:00:00
QTime t;
t = n.addSecs(70); // t == 14:01:10
t = n.addSecs(-70); // t == 13:58:50
t = n.addSecs(10 * 60 * 60 + 5); // t == 00:00:05
t = n.addSecs(-15 * 60 * 60); // t == 23:00:00
// 從時間對象中取出 時/分/秒/毫秒
// Returns the hour part (0 to 23) of the time. Returns -1 if the time is invalid.
int QTime::hour() const;
// Returns the minute part (0 to 59) of the time. Returns -1 if the time is invalid.
int QTime::minute() const;
// Returns the second part (0 to 59) of the time. Returns -1 if the time is invalid.
int QTime::second() const;
// Returns the millisecond part (0 to 999) of the time. Returns -1 if the time is invalid.
int QTime::msec() const;
// 時間格式化
/*
-- 時 --
h ==> The hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
hh ==> The hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
H ==> The hour without a leading zero (0 to 23, even with AM/PM display)
HH ==> The hour with a leading zero (00 to 23, even with AM/PM display)
-- 分 --
m ==> The minute without a leading zero (0 to 59)
mm ==> The minute with a leading zero (00 to 59)
-- 秒 --
s ==> The whole second, without any leading zero (0 to 59)
ss ==> The whole second, with a leading zero where applicable (00 to 59)
-- 毫秒 --
zzz ==> The fractional part of the second, to millisecond precision,
including trailing zeroes where applicable (000 to 999).
-- 上午或者下午
AP or A ==> 使用AM/PM(大寫) 描述上下午, 中文系統(tǒng)顯示漢字
ap or a ==> 使用am/pm(小寫) 描述上下午, 中文系統(tǒng)顯示漢字
*/
QString QTime::toString(const QString &format) const;
// 階段性計時
// 過時的API函數
// 開始計時
void QTime::start();
// 計時結束
int QTime::elapsed() const;
// 重新計時
int QTime::restart();
// 推薦使用的API函數
// QElapsedTimer 類
void QElapsedTimer::start();
qint64 QElapsedTimer::restart();
qint64 QElapsedTimer::elapsed() const;
// 操作符重載 ==> 時間比較
bool QTime::operator!=(const QTime &t) const;
bool QTime::operator<(const QTime &t) const;
bool QTime::operator<=(const QTime &t) const;
bool QTime::operator==(const QTime &t) const;
bool QTime::operator>(const QTime &t) const;
bool QTime::operator>=(const QTime &t) const;
// 靜態(tài)函數 -> 得到當前時間
[static] QTime QTime::currentTime();
3、QDateTime
QDateTime類可以封裝日期和時間信息也可以通過這個類得到日期和時間相關的信息, 包括:年, 月, 日, 時, 分, 秒, 毫秒。其實這個類就是QDate 和 QTime 這兩個類的結合體。
// 構造函數
QDateTime::QDateTime();
QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec = Qt::LocalTime);
// 公共成員函數
// 設置日期
void QDateTime::setDate(const QDate &date);
// 設置時間
void QDateTime::setTime(const QTime &time);
// 給當前日期對象追加 年/月/日/秒/毫秒, 參數可以是負數
QDateTime QDateTime::addYears(int nyears) const;
QDateTime QDateTime::addMonths(int nmonths) const;
QDateTime QDateTime::addDays(qint64 ndays) const;
QDateTime QDateTime::addSecs(qint64 s) const;
QDateTime QDateTime::addMSecs(qint64 msecs) const;
// 得到對象中的日期
QDate QDateTime::date() const;
// 得到對象中的時間
QTime QDateTime::time() const;
// 日期和時間格式, 格式字符參考QDate 和 QTime 類的 toString() 函數
QString QDateTime::toString(const QString &format) const;
// 操作符重載 ==> 日期時間對象的比較
bool QDateTime::operator!=(const QDateTime &other) const;
bool QDateTime::operator<(const QDateTime &other) const;
bool QDateTime::operator<=(const QDateTime &other) const;
bool QDateTime::operator==(const QDateTime &other) const;
bool QDateTime::operator>(const QDateTime &other) const;
bool QDateTime::operator>=(const QDateTime &other) const;
// 靜態(tài)函數
// 得到當前時區(qū)的日期和時間(本地設置的時區(qū)對應的日期和時間)
[static] QDateTime QDateTime::currentDateTime();
十二、UI界面介紹
1、窗口組件介紹
2、屬性介紹
十三、QT的第一個界面設計程序
1、widget.h和widget.cpp
這兩個文件 就是 為了設計窗口的 ,封裝了窗口類
所以我們 設置窗口的屬性、功能 在這兩個文件里面去添加?。?!
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
// 窗口的布局 或者 設置 在這里 手寫代碼?。?!
ui->setupUi(this);
//這個函數 是窗口的構造函數 this 表示指向自己 ---> 主窗口的地址
}
Widget::~Widget()
{
delete ui;
}
2、窗口大小設置
// 設置窗口大小
resize(800,800); -------> 這種窗口支持縮放?。?!
// 設置固定的窗口大小
this->setFixedSize(400,300);
3、添加按鈕
#include "widget.h"
#include
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
// 設置窗口大小
//resize(400,300);
// 設置固定的窗口大小
this->setFixedSize(400,300);
//創(chuàng)建Button對象
QPushButton *btn = new QPushButton;
//設置btn文本
btn->setText("第一個按鈕");
// 設置btn大小
//btn->resize(100,100);
btn->setFixedSize(100,100);
// btn 按鈕 認父親 設置當前窗口 setParent
btn->setParent(this);
//創(chuàng)建Button對象
QPushButton *btn1 = new QPushButton;
//設置btn文本
btn1->setText("第二個按鈕");
// 設置btn大小
//btn->resize(100,100);
btn1->setFixedSize(100,100);
// btn 按鈕 認父親 設置當前窗口 setParent
btn1->setParent(this);
//移動顯示位置 要不然會重疊??!
btn1->move(100,0);
//ui->setupUi(this);
//這個函數 是窗口的構造函數 this 表示指向自己 ---> 主窗口的地址
}
//設置btn文本
btn->setText("第一個按鈕");
//字體設置
QFont font1; // 創(chuàng)建字體對象
font1.setFamily("Arial"); // 選擇 字體族
font1.setPointSize(12); //大小
font1.setBold(true); // 粗細?。?!
btn->setFont(font1);
3、補充 --- 設置窗口標題
this->setWindowTitle("第一個UI程序");
4、完整代碼
#include "widget.h"
#include
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//這個函數 是窗口的構造函數 this 表示指向自己 ---> 主窗口的地址
// 設置窗口大小
//resize(400,300);
// 設置固定的窗口大小
this->setFixedSize(400,300);
//創(chuàng)建Button對象
QPushButton *btn = new QPushButton;
//設置btn文本
btn->setText("第一個按鈕");
//字體設置
QFont font1;
font1.setFamily("Arial");
font1.setPointSize(12);
font1.setBold(true);
btn->setFont(font1);
// 設置btn大小
//btn->resize(100,100);
btn->setFixedSize(100,100);
// btn 按鈕 認父親 設置當前窗口 setParent
btn->setParent(this);
//創(chuàng)建Button對象
QPushButton *btn1 = new QPushButton;
//設置btn文本
btn1->setText("第二個按鈕");
// 設置btn大小
//btn->resize(100,100);
btn1->setFixedSize(100,100);
// btn 按鈕 認父親 設置當前窗口 setParent
btn1->setParent(this);
//移動顯示位置 要不然會重疊??!
btn1->move(100,0);
// 設置UI窗口標題
this->setWindowTitle("第一個UI程序");
}
Widget::~Widget()
{
delete ui;
}
十四、信號和槽
1、信號和槽的概述
信號和槽是 Qt 框架引以為豪的機制之一。
所謂信號槽,實際就是觀察者模式(發(fā)布-訂閱模式)。
當某個事件發(fā)生之后,比如,按鈕檢測到自己被點擊了一下,它就會發(fā)出一個信號(signal)。
這種發(fā)出是沒有目的的,類似廣播。如果有對象對這個信號感興趣,它就會使用連接(connect)函數,意思是,將想要處理的信號和自己的一個函數(稱為槽(slot))綁定來處理這個信號。
也就是說,當信號發(fā)出時,被連接的槽函數會自動被回調。
這就類似觀察者模式:當發(fā)生了感興趣的事件,某一個操作就會被自動觸發(fā)。
eg:
2、信號 signal
信號是由于用戶對窗口或控件進行了某些操作,導致窗口或控件產生了某個特定事件,這時候Qt對應的窗口類會發(fā)出某個信號,以此對用戶的挑選做出反應。
因此根據上述的描述我們得到一個結論 – 信號的本質就是事件,比如:
按鈕單擊、雙擊窗口刷新鼠標移動、鼠標按下、鼠標釋放鍵盤輸入
那么在Qt中信號是通過什么形式呈現(xiàn)給使用者的呢?
我們對哪個窗口進行操作, 哪個窗口就可以捕捉到這些被觸發(fā)的事件。對于使用者來說觸發(fā)了一個事件我們就可以得到Qt框架給我們發(fā)出的某個特定信號。信號的呈現(xiàn)形式就是函數, 也就是說某個事件產生了, Qt框架就會調用某個對應的信號函數, 通知使用者。
在QT中信號的發(fā)出者是某個實例化的類對象,對象內部可以進行相關事件的檢測。
3、槽函數
在Qt中槽函數是一類特殊的功能的函數,在編碼過程中也可以作為類的普通成員函數來使用。之所以稱之為槽函數是因為它們還有一個職責就是對Qt框架中產生的信號進行處理。
eg:
女朋友: 肚子餓了??! ---------> 帶她出去吃飯!!
女朋友 對象 ----> 發(fā)出一個信號 ----> 肚子餓了?。?!
我 收到信號 -----> 處理信號(槽函數) -----> 帶她出去吃飯?。?/p>
我 ----> 信號接收者??! 也是一個對象??! ------> QT中 槽函數 的所有者 也是某個類的實例化對象!??!
4、信號和槽的關系
在Qt中信號和槽函數都是獨立的個體,本身沒有任何聯(lián)系,但是由于某種特性需求我們可以將二者連接到一起,好比牛郎和織女想要相會必須要有喜鵲為他們搭橋一樣。
在Qt中我們需要使用QOjbect類中的connect函數進二者的關聯(lián)。
連接信號和槽的connect()函數原型如下, 其中PointerToMemberFunction是一個指向函數地址的指針
QMetaObject::Connection QObject::connect(
const QObject *sender, PointerToMemberFunction signal,
const QObject *receiver, PointerToMemberFunction method,
Qt::ConnectionType type = Qt::AutoConnection);
參數:
- sender: 發(fā)出信號的對象
- signal: 屬于sender對象, 信號是一個函數, 這個參數的類型是函數
指針, 信號函數地址
- receiver: 信號接收者
- method: 屬于receiver對象, 當檢測到sender發(fā)出了signal信號,
receiver對象調用method方法,信號發(fā)出之后的處理動作
// 參數 signal 和 method 都是函數地址, 因此簡化之后的 connect() 如下:
connect(const QObject *sender, &QObject::signal, const QObject *receiver, &QObject::method);
使用connect()進行信號槽連接的注意事項:
connect函數相對于做了信號處理動作的注冊調用conenct函數的sender對象的信號并沒有產生, 因此receiver對象的method也不會被調用method槽函數本質是一個回調函數, 調用的時機是信號產生之后, 調用是Qt框架來執(zhí)行的connect中的sender和recever兩個指針必須被實例化了, 否則conenct不會成功
5、標準的信號和槽的使用
(1) 通過QT creator 幫助查找
首先我們可以在Contents中尋找關鍵字 signals,信號的意思,但是我們發(fā)現(xiàn)并沒有找到,這時候我們應該看當前類從父類繼承下來了哪些信號
因此我們去他的父類QAbstractButton中就可以找到該關鍵字,點擊signals索引到系統(tǒng)自帶的信號有如下幾個
(2)QT助手查詢
(3) 點擊退出按鈕 實現(xiàn) 窗口關閉
第一種實現(xiàn)
第二種實現(xiàn)
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//QT4 信號和槽
// connect(發(fā)送者,SIGNAL(發(fā)送者發(fā)出的信號),接受者,SLOT(執(zhí)行的對應操作));
//connect(ui->btn_exit,SIGNAL(clicked(bool)),this,SLOT(close()));
//QT5
connect(ui->btn_exit,&QPushButton::clicked,this,&MainWindow::close);
}
MainWindow::~MainWindow()
{
delete ui;
}
(4)總結
connect() -----> 這個函數就是實現(xiàn)連接的功能 -----> 將信號 和 槽函數進行連接綁定
connect(sender,signal,receiver,slot)
參數說明:
sender -----> 發(fā)出信號的對象
signal -----> 發(fā)送對象發(fā)出的信號
receiver -----> 接收信號的對象
slot -----> 接收對象 在 收到信號后 需要調用的函數(槽函數)
qt4 的連接方法
//qt4 ----> SIGNAL() SLOT()
connect(btn,SIGNAL(clicked(bool)),this,SLOT(close()));
//qt5 &QPushButton::clicked &widget::選擇信號和槽
connect(btn,&QPushButton::clicked,this,&Widget::close);
注意,注意,注意:
信號也可以連接信號
6、自定義信號和槽
如果我們想要使用自定義的信號和槽。首先要編寫新的類---->這個類一般繼承QT某些標準類
我們自己編寫的類想要在Qt中使用使用信號槽機制,那么必須要滿足的如下條件:
-這個類必須從QObject類或者是其子類進行派生
-在定義類的頭文件中加入Q_OBJECT宏
(1) 自定義信號
* 1.信號是類的成員函數
* 2.返回值是void類型
* 3.信號的名字可以根據實際情況進行指定
* 4.參數可以隨意指定,信號也支持重載
* 5.信號需要使用signals 關鍵字進行聲明,使用方法類似于public等關鍵字
* 6.信號函數只需要聲明,不需要定義(沒有函數體實現(xiàn))
* 7.在程序中發(fā)送自定義信號:發(fā)送信號的本質就是調用信號函數
* - 習慣性在信號函數前加關鍵字:emit
* - emit只是顯示的聲明一下信號要被發(fā)送,沒有特殊含義-底層emit == #define emit
* 舉例:信號重載
* Qt中的類想要使用信號槽機制必須要從QObject類派生(直接或間接派生都可以)
* 1.信號是類的成員函數
* 2.返回值是void類型
* 3.信號的名字可以根據實際情況進行指定
* 4.參數可以隨意指定,信號也支持重載
* 5.信號需要使用signals 關鍵字進行聲明,使用方法類似于public等關鍵字
* 6.信號函數只需要聲明,不需要定義(沒有函數體實現(xiàn))
* 7.在程序中發(fā)送自定義信號:發(fā)送信號的本質就是調用信號函數
* - 習慣性在信號函數前加關鍵字:emit
* - emit只是顯示的聲明一下信號要被發(fā)送,沒有特殊含義-底層emit == #define emit
* 舉例:信號重載
* Qt中的類想要使用信號槽機制必須要從QObject類派生(直接或間接派生都可以)
(2)槽函數
1.返回值是void類型
2.槽也是函數,因此也支持重載
-槽函數需要指定多少個參數,需要看連接的信號的參數個數
-槽函數的參數是用來接收信號發(fā)送的數據的,信號發(fā)送的數據就是信號的參數
-舉例:
-信號函數:void testsig( int a,double b);
-槽函數: void testslot ( int a,double b);
總結:
-槽函數的參數應該和對應的信號的參數個數,類型一一對應
-信號的參數可以大于等于槽函數的參數個數 == 信號傳遞的數據被忽略了
-信號函數: void testsig(int a, double b);
-槽函數: void testslot(int a);
3. Qt中槽函數的類型:
-類的成員函數
-全局函數
-靜態(tài)函數
- lambda表達式(匿名函數)
4.槽函數可以使用關鍵字進行聲明: slots (Qt5中slots可以省略不寫)
- public slots:
- private slots:
- protected slots:
(3)實現(xiàn)一下自定義信號和槽
eg: 女朋友 -----> 餓了
117 ------> 吃火鍋
兩個對象 -----> 添加兩個文件
我的類一樣的方法添加??!
1、主窗口 添加 這個兩個類的頭文件
2、明確指針指向的對象
3、設計信號和槽
(4)帶參數的信號和槽 ------ 重載
(5)總結
總結
Qt4的信號槽連接方式因為使用了宏函數, 宏函數對用戶傳遞的信號槽不會做錯誤檢測, 容易出bugQt5的信號槽連接方式, 傳遞的是信號槽函數的地址, 編譯器會做錯誤檢測, 減少了bug的產生當信號槽函數被重載之后, Qt4的信號槽連接方式不受影響當信號槽函數被重載之后, Qt5中需要給被重載的信號或者槽定義函數指針
應用舉例
場景描述:
- 我肚子餓了, 我要吃東西。
分析:
- 信號的發(fā)出者是我自己, 信號的接收者也是我自己
我們首先定義出一個Qt的類。
class Me : public QObject
{
Q_OBJECT
// Qt4中的槽函數必須這樣聲明, qt5中的關鍵字 slots 可以被省略
public slots:
void eat();
void eat(QString somthing);
signals:
void hungury();
void hungury(QString somthing);
};
// 基于上邊的類寫出解決方案
// 處理如下邏輯: 我餓了, 我要吃東西
// 分析: 信號的發(fā)出者是我自己, 信號的接收者也是我自己
Me m;
// Qt4處理方式
connect(&m, SIGNAL(eat()), &m, SLOT(hungury()));
connect(&m, SIGNAL(eat(QString)), &m, SLOT(hungury(QString)));
// Qt5處理方式
connect(&m, &Me::eat, &m, &Me::hungury); // error
void (Me::*func1)(QString) = &Me::eat; // func1指向帶參的信號
void (Me::*func2)() = &Me::hungury; // func2指向不帶參的槽函數
// 定義函數指針指向重載的某一個具體的信號地址
void (Me::*mysignal)(QString) = &Me::eat;
// 定義函數指針指向重載的某一個具體的槽函數地址
void (Me::*myslot)(QString) = &Me::hungury;
// 使用定義的函數指針完成信號槽的連接
connect(&m, mysignal, &m, myslot);
7、Lambda 表達式
(1) 作用
Lambda表達式是 C++ 11 最重要也是最常用的特性之一,是現(xiàn)代編程語言的一個特點,簡潔,提高了代碼的效率并且可以使程序更加靈活,Qt是完全支持c++語法的, 因此在Qt中也可以使用Lambda表達式。
[capture](params) opt -> ret {body;};
- capture: 捕獲列表
- params: 參數列表
- opt: 函數選項
- ret: 返回值類型
- body: 函數體
捕獲列表: 捕獲一定范圍內的變量
[] - 不捕捉任何變量[&] - 捕獲外部作用域中所有變量, 并作為引用在函數體內使用 (按引用捕獲)[=] - 捕獲外部作用域中所有變量, 并作為副本在函數體內使用 (按值捕獲)
拷貝的副本在匿名函數體內部是只讀的
[=, &foo] - 按值捕獲外部作用域中所有變量, 并按照引用捕獲外部變量 foo[bar] - 按值捕獲 bar 變量, 同時不捕獲其他變量[&bar] - 按引用捕獲 bar 變量, 同時不捕獲其他變量[this] - 捕獲當前類中的this指針
讓lambda表達式擁有和當前類成員函數同樣的訪問權限如果已經使用了 & 或者 =, 默認添加此選項
參數列表: 和普通函數的參數列表一樣opt 選項 –> 可以省略
mutable: 可以修改按值傳遞進來的拷貝(注意是能修改拷貝,而不是值本身)exception: 指定函數拋出的異常,如拋出整數類型的異常,可以使用throw();
返回值類型:
標識函數返回值的類型,當返回值為void,或者函數體中只有一處return的地方(此時編譯器可以自動推斷出返回值類型)時,這部分可以省略
函數體:
函數的實現(xiàn),這部分不能省略,但函數體可以為空。
(2)定義和調用
// 匿名函數的定義, 程序執(zhí)行這個匿名函數是不會被調用的
[](){
qDebug() << "hello, 我是一個lambda表達式...";
};
// 匿名函數的定義+調用:
int ret = [](int a) -> int
{
return a+1;
}(100); // 100是傳遞給匿名函數的參數
(3) 信號和槽中的使用
十五、QMainWindow
1、菜單欄
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
//ui->setupUi(this);
// 設置窗口標題
this->setWindowTitle("我的主窗口");
this->resize(400,300);
//創(chuàng)建菜單欄
//QMenuBar *menubar = new QMenuBar;
//menubar->setParent(this);
QMenuBar *menubar = new QMenuBar(this);
// 把 菜單欄加入當前窗口
this->setMenuBar(menubar);
//創(chuàng)建菜單
QMenu *file_menu = new QMenu("file",this);
QMenu *edit_menu = new QMenu("edit",this);
// 把菜單加入菜單欄
menubar->addMenu(file_menu);
menubar->addMenu(edit_menu);
//創(chuàng)建菜單項
QAction *open_file = new QAction("open",this);
QAction *save_file = new QAction("save",this);
//加入菜單
file_menu->addAction(open_file);
file_menu->addAction(save_file);
// 給菜單創(chuàng)建快捷鍵
open_file->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));
save_file->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
connect(open_file,&QAction::triggered,[](){
qDebug() << "文件已打開" << endl;
});
connect(save_file,&QAction::triggered,[](){
qDebug() << "文件已保存" << endl;
});
}
MainWindow::~MainWindow()
{
delete ui;
}
2、工具欄
//工具欄
QToolBar *tool=new QToolBar("tool",this);
this->addToolBar(tool);
tool->addAction(New);
tool->addAction(open);
tool->setFloatable(false);//false:不允許,true:允許
tool->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);
3、狀態(tài)欄 在最下面
狀態(tài)欄 一般是顯示信息的
//狀態(tài)欄
QStatusBar *stBar=new QStatusBar(this);
this->setStatusBar(stBar);
QLabel *lab1=new QLabel("left",this);
QLabel *lab2=new QLabel("right",this);
//將lab1顯示在狀態(tài)欄的左側
stBar->addWidget(lab1);
//將lab2顯示在狀態(tài)欄的右側
stBar->addPermanentWidget(lab2);
4、資源文件 ---- 所有的QT工程都可以添加
QT的資源機制 ---->將程序運行的所需要的資源 以 二進制的形式存儲在可執(zhí)行的文件內部
eg: 如果程序中需要用到的資源(圖片、圖標,文本資源、動畫等),就要把這些資源放在資源文件中,這樣就不用擔心資源丟失,資源找不到。
------> QT的資源是以二進制編譯在可執(zhí)行文件內部!!
------> 便于移植,這樣就可以防止因為資源路徑等問題 導致資源不可用!
(1)QT資源文件的創(chuàng)建
(2)資源刪除
要刪除資源 ----> 必須在資源文件中去刪除
進入資源文件的編輯者模式
(3)資源文件使用
背景圖片自動縮放
label 標簽顯示圖片
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->label->resize(800,600);
// 標簽文本顯示
//ui->label->setText("hello world!");
#if 0
// 構建圖片的對象
QPixmap *img = new QPixmap(":/image/mangsheng.jpg");
// 將圖片設置到標簽里面去
ui->label->setPixmap(*img);
#else
QPixmap img(":/image/mangsheng.jpg");
//Qt::KeepAspectRatio ----> 保持寬高比
// Qt::SmoothTransformation 平滑處理
//ui->label->setPixmap(img.scaled(ui->label->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
// 將圖片設置為 label 標簽的大?。?!
ui->label->setPixmap(img.scaled(ui->label->size()));
#endif
}
(4)圖片的縮放 窗口縮放----> label -----> 圖片
窗口 和label 同比例縮放
圖片和label框的縮放
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//定義圖片對象
QPixmap img(":/image/mangsheng.jpg");
ui->label->setPixmap(img);
// 設置label 里面的內容 根據label大小自動縮放
ui->label->setScaledContents(true); // 圖片自適應
}
柚子快報邀請碼778899分享:java QT概述簡介
推薦閱讀
本文內容根據網絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。