版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
C++程序設(shè)計(jì)第7章QT開(kāi)發(fā)第1節(jié)QT開(kāi)發(fā)環(huán)境搭建第2節(jié)窗體第3節(jié)菜單、工具欄和狀態(tài)欄第4節(jié)鼠標(biāo)與鍵盤第5節(jié)簡(jiǎn)單繪圖第1節(jié)QT開(kāi)發(fā)環(huán)境搭建QT開(kāi)發(fā)環(huán)境搭建HelloWorld程序發(fā)布1.1QT簡(jiǎn)介Qt是一個(gè)1991年由QtCompany開(kāi)發(fā)的跨平臺(tái)C++圖形用戶界面應(yīng)用程序開(kāi)發(fā)框架。它既可以開(kāi)發(fā)GUI程序,也可用于開(kāi)發(fā)非GUI程序,比如控制臺(tái)工具和服務(wù)器。Qt是面向?qū)ο蟮目蚣堋?008年,QtCompany被諾基亞公司收購(gòu),Qt也因此成為諾基亞旗下的編程語(yǔ)言工具。2012年,Qt被Digia收購(gòu)。2014年4月,跨平臺(tái)集成開(kāi)發(fā)環(huán)境QtCreator3.1.0正式發(fā)布,實(shí)現(xiàn)了對(duì)于iOS、Android、WP的全面支持?;旧?,Qt同XWindow上的Motif,Openwin,GTK等圖形界面庫(kù)和Windows平臺(tái)上的MFC,VCL,ATL是同類型的東西。1.2QT下載在線下載器:https://download.qt.io/official_releases/online_installers課程使用版本:6.5.11.3QT安裝……1.4例7-1創(chuàng)建HelloWorld程序新建HelloWorldQT項(xiàng)目路徑中不要有中文編譯,運(yùn)行若遇到LNK1158無(wú)法運(yùn)行rc.exe的錯(cuò)誤,解決辦法見(jiàn)這里。QT框架代碼mainwindow.hMainWindow類定義#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QMainWindow>QT_BEGIN_NAMESPACEnamespaceUi{classMainWindow;}QT_END_NAMESPACEclassMainWindow:publicQMainWindow{Q_OBJECTpublic:MainWindow(QWidget*parent=nullptr);~MainWindow();private:Ui::MainWindow*ui;};#endif//MAINWINDOW_HQT框架代碼mainwindow.cppMainWindow類定義#include"mainwindow.h"#include"ui_mainwindow.h"MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){ui->setupUi(this);}MainWindow::~MainWindow(){deleteui;}QT框架代碼main.cpp主函數(shù)文件#include"mainwindow.h"#include<QApplication>intmain(intargc,char*argv[]){QApplicationa(argc,argv);MainWindoww;w.show();returna.exec();}添加控件拖入一個(gè)標(biāo)簽(Label),修改文字為“HelloWorld!”編譯,運(yùn)行OK!1.5程序發(fā)布成功編譯之后,在項(xiàng)目目錄同級(jí)的目錄下會(huì)多一個(gè)名字形如“build-HelloWorldQT-Desktop_Qt_6_5_1_MinGW_64bit-Debug”的目錄。進(jìn)入到里面的debug的目錄,就會(huì)發(fā)現(xiàn)編譯生成的HelloWorldQT.exe程序。運(yùn)行exe程序,可能會(huì)出現(xiàn)以下缺少dll文件的提示:在QT的安裝目錄找到程序windeployqt.exe。該程序的作用是找到要發(fā)布的程序的所有依賴庫(kù)。在安裝了多個(gè)QT版本和部件時(shí),要注意目錄要找對(duì),和構(gòu)建目錄要對(duì)應(yīng)。在控制臺(tái)中運(yùn)行“windeployqt.exe目標(biāo).exe”。運(yùn)行完畢后,發(fā)布程序的目錄就會(huì)出現(xiàn)所有依賴的庫(kù)文件。至此,HelloWorldQT已可脫離QT運(yùn)行。第2節(jié)窗體編輯窗體彈出窗體信號(hào)和槽純代碼編寫2.1例7-2創(chuàng)建一個(gè)多窗口程序程序的功能:運(yùn)行開(kāi)始出現(xiàn)一個(gè)對(duì)話框,按下登錄主界面按鈕后該對(duì)話框消失并進(jìn)入主窗口。進(jìn)入主窗口后,按下顯示對(duì)話框按鈕,會(huì)彈出一個(gè)對(duì)話框。(1)新建項(xiàng)目打開(kāi)QtCreator,新建QtWidgetsApplication,項(xiàng)目名稱設(shè)置為windows完成項(xiàng)目創(chuàng)建后,雙擊mainwindow.ui文件進(jìn)入設(shè)計(jì)模式,從左側(cè)部件列表中向界面上拖入一個(gè)PushButton,然后雙擊并修改顯示文本為“按鈕”。Ctrl+R運(yùn)行一次程序。(2)使用代碼設(shè)置顯示文本在構(gòu)造函數(shù)MainWindow()中添加一行代碼MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){ui->setupUi(this);
ui->pushButton->setText("新窗口");//將界面上按鈕的顯示文本更改為“新窗口”}若出現(xiàn)錯(cuò)誤“errorC2001:常量中有換行符”的解決辦法(3)添加登錄對(duì)話框往項(xiàng)目中添加新文件。模板選擇Qt分類中的Qt設(shè)計(jì)師界面類,然后界面模板選擇DialogwithoutButtons下一步進(jìn)入類信息界面,這里將類名更改為L(zhǎng)oginDlg完成后會(huì)自動(dòng)跳轉(zhuǎn)到設(shè)計(jì)模式(4)增加按鈕拖入一個(gè)PushButton,更改顯示文本為“登錄到主界面”(5)設(shè)置信號(hào)和槽點(diǎn)擊設(shè)計(jì)模式上方
圖標(biāo),或者按下F4,進(jìn)入信號(hào)和槽編輯模式。按著鼠標(biāo)左鍵,從按鈕上拖向界面,如下圖所示。信號(hào)和槽大家可以把它們都看做是函數(shù),比如這里,當(dāng)單擊了按鈕以后就會(huì)發(fā)射單擊信號(hào),即clicked();然后對(duì)話框接收到信號(hào)就會(huì)執(zhí)行相應(yīng)的操作,即執(zhí)行accept()槽。一般情況下,我們只需要修改槽函數(shù)即可,不過(guò),這里的accept()已經(jīng)實(shí)現(xiàn)了默認(rèn)的功能,它會(huì)將對(duì)話框關(guān)閉并返回QDialog::Accepted標(biāo)識(shí),所以無(wú)需再做更改。下面我們要使用返回的QDialog::Accepted標(biāo)識(shí)來(lái)判斷是否按下了登錄按鈕。完成后,可以按下圖標(biāo)或者F3鍵來(lái)返回控件編輯模式。(6)修改main.cpp#include"mainwindow.h"#include<QApplication>#include"logindlg.h"intmain(intargc,char*argv[]){QApplicationa(argc,argv);MainWindoww;LoginDlgdlg;//建立自己新建的LoginDlg類的實(shí)例dlgif(dlg.exec()==QDialog::Accepted)//利用Accepted返回值判斷按鈕是否被按下
{w.show();//如果被按下,顯示主窗口
returna.exec();//程序一直執(zhí)行,直到主窗口關(guān)閉
}elsereturn0;//如果沒(méi)有被按下,則不會(huì)進(jìn)入主窗口,整個(gè)程序結(jié)束運(yùn)行}(7)再?gòu)棾鲆粋€(gè)對(duì)話框我們計(jì)劃點(diǎn)擊主窗口“新窗口”按鈕時(shí)再?gòu)棾鲆粋€(gè)對(duì)話框。為此:打開(kāi)mainwindow.ui文件進(jìn)入設(shè)計(jì)模式,然后在“按鈕”部件上右擊并選擇轉(zhuǎn)到槽菜單在彈出的轉(zhuǎn)到槽對(duì)話框中選擇第一個(gè)clicked()信號(hào)并按下確定按鈕。這時(shí)會(huì)跳轉(zhuǎn)到編輯模式mainwindow.cpp中的on_pushButton_clicked()
函數(shù)處。添加代碼:#include"ui_mainwindow.h"#include"qdialog.h"……voidMainWindow::on_pushButton_clicked(){QDialog*dlg=newQDialog(this);dlg->show();}編譯,運(yùn)行注意兩種彈出新窗口的方法:一種是舊窗口消失一種是舊窗口不消失OK!2.2例7-3登陸對(duì)話框新建QtWidgetsApplication,項(xiàng)目名稱為login,類名和基類保持MainWindow和QMainWindow不變。完成項(xiàng)目創(chuàng)建后,向項(xiàng)目中添加新的Qt設(shè)計(jì)師界面類,模板選擇DialogwithoutButtons,類名更改為L(zhǎng)oginDlg。完成后向界面上添加兩個(gè)標(biāo)簽Label、兩個(gè)行編輯器LineEdit和兩個(gè)按鈕PushButton。分別更改兩個(gè)行編輯器的objectName屬性為ledUser和ledPassword。分別更改兩個(gè)按鈕的objectName屬性為btnLogin和btnExit。使用信號(hào)和槽編輯器窗口來(lái)關(guān)聯(lián)信號(hào)和槽,設(shè)置退出按鈕。在設(shè)計(jì)模式下方的信號(hào)和槽編輯器(Signals&SlotsEditor)中,先點(diǎn)擊左上角的綠色加號(hào)添加關(guān)聯(lián),然后選擇發(fā)送者為btnExit,信號(hào)為clicked(),接收者為L(zhǎng)oginDlg,槽為close()。這樣,就實(shí)現(xiàn)了當(dāng)單擊退出按鈕時(shí),就關(guān)閉登錄對(duì)話框。右擊登錄按鈕,在彈出的菜單中選擇“轉(zhuǎn)到槽…”,然后選擇clicked()信號(hào)并確定。轉(zhuǎn)到相應(yīng)的槽以后,添加函數(shù)調(diào)用:voidLoginDlg::on_btnLogin_clicked(){accept();}修改main.cpp#include"mainwindow.h"#include<QApplication>#include"logindlg.h"intmain(intargc,char*argv[]){QApplicationa(argc,argv);MainWindoww;LoginDlgdlg;if(dlg.exec()==QDialog::Accepted){w.show();returna.exec();}elsereturn0;}實(shí)現(xiàn)使用用戶名和密碼登錄voidLoginDlg::on_btnLogin_clicked(){//判斷用戶名和密碼是否正確,錯(cuò)誤則彈出警告對(duì)話框
if(ui->ledUser->text()==tr("zhang")&&ui->ledPassword->text()==tr("12345678")){accept();}else{QMessageBox::warning(this,tr("警告!"),tr("用戶名或密碼錯(cuò)誤!"),QMessageBox::Yes);
//清空內(nèi)容并定位光標(biāo)
ui->ledUser->clear();ui->ledPassword->clear();ui->ledUser->setFocus();}}在屬性編輯器中將echoMode屬性選擇為Password,密碼顯示變?yōu)楹邳c(diǎn)兩個(gè)文本框的placeholderText屬性更改為“請(qǐng)輸入用戶名”、“請(qǐng)輸入密碼”。文本框在沒(méi)有輸入前將顯示提示文本OK!2.3斷點(diǎn)調(diào)試嘗試設(shè)置一個(gè)斷點(diǎn),利用調(diào)試運(yùn)行按鈕啟動(dòng)調(diào)試若出現(xiàn)錯(cuò)誤“Unabletocreateadebuggingengine”的解決辦法2.4純代碼編寫QT除了可以使用UI框架編寫程序,還可以用純代碼實(shí)現(xiàn)UI界面。例7-4純代碼編寫的登陸對(duì)話框例子(1)新建工程新建QtWidgetsApplication,項(xiàng)目名稱為CodeLogin,在類信息頁(yè)面保持類名和基類為MainWindow和QMainWindow不變,取消選擇創(chuàng)建界面選項(xiàng)(GenerateForm)
往項(xiàng)目中添加新文件,模板選擇C++分類中的C++Class將類名設(shè)置為L(zhǎng)oginDialog,基類選擇Custom定制,然后手動(dòng)設(shè)置為Qdialog點(diǎn)擊“下一步”直到完成。(2)創(chuàng)建登錄對(duì)話框類(3)設(shè)置完成后,修改代碼。先修改LoginDlg.h文件#ifndefLOGINDIALOG_H#defineLOGINDIALOG_H#include<QDialog>classQLabel;//類的前置聲明classQLineEdit;classQPushButton;classLoginDlg:publicQDialog{//使用信號(hào)和槽等特性必須添加該宏Q_OBJECTpublic:LoginDlg(QWidget*parent=0);~LoginDlg();private:QLabel*labUser;QLabel*labPassword;QLineEdit*ledUser;QLineEdit*ledPassword;QPushButton*btnLogin;QPushButton*btnExit;};#endif修改LoginDlg.cpp文件#include"logindialog.h"#include<QLabel>#include<QLineEdit>#include<QPushButton>#include<QMessageBox>LoginDlg::LoginDlg(QWidget*parent):QDialog(parent){resize(400,280);//重設(shè)窗口大小labUser=newQLabel(this);labUser->move(65,60);labUser->setText(tr("賬號(hào):"));ledUser=newQLineEdit(this);ledUser->move(130,57);ledUser->setPlaceholderText(tr("輸入賬號(hào)名稱"));labPassword=newQLabel(this);labPassword->move(65,120);labPassword->setText(tr("密碼:"));ledPassword=newQLineEdit(this);ledPassword->move(130,117);ledPassword->setPlaceholderText(tr("請(qǐng)輸入密碼"));btnLogin=newQPushButton(this);btnLogin->move(60,190);btnLogin->setText(tr("登錄"));btnExit=newQPushButton(this);btnExit->move(220,190);btnExit->setText(tr("退出"));}LoginDlg::~LoginDlg(){}修改main.cpp文件#include"mainwindow.h"#include<QApplication>#include"logindialog.h"intmain(intargc,char*argv[]){QApplicationa(argc,argv);MainWindoww;
LoginDlgdlg;if(dlg.exec()==QDialog::Accepted){w.show();returna.exec();}elsereturn0;}界面已和前例一樣,但點(diǎn)擊按鈕還無(wú)反應(yīng)若出現(xiàn)錯(cuò)誤“l(fā)ink2001錯(cuò)誤無(wú)法解析外部符號(hào)metaObject”的解決辦法(4)實(shí)現(xiàn)信號(hào)和槽的功能修改LoginDlg.h,聲明一個(gè)槽:……classLoginDlg:publicQDialog{……QPushButton*btnExit;privateslots:voidLogin();};修改LoginDlg.cpp中的構(gòu)造函數(shù),連接槽:LoginDlg::LoginDlg(QWidget*parent):QDialog(parent){……QPushButton*btnExit;connect(btnLogin,&QPushButton::clicked,this,&LoginDlg::Login);connect(btnExit,&QPushButton::clicked,this,&LoginDlg::close);
};在LoginDlg.cpp末尾添加槽函數(shù)Login()的定義voidLoginDlg::Login(){//判斷用戶名和密碼是否正確,
if(ledUser->text()==tr("zhang")&&ledPassword->text()==tr("12345678")){accept();}else//如果錯(cuò)誤則彈出警告對(duì)話框
{QMessageBox::warning(this,tr("警告!"),tr("用戶名或密碼錯(cuò)誤!"),QMessageBox::Yes);ledUser->clear();ledPassword->clear();ledUser->setFocus();}}OK!第3節(jié)菜單、工具欄和狀態(tài)欄菜單工具欄狀態(tài)欄簡(jiǎn)易寫字本例子例7-5一個(gè)帶菜單、工具欄、狀態(tài)欄的簡(jiǎn)易文本編輯器(界面)通過(guò)例子演示菜單、工具欄、狀
態(tài)欄的制作(1)新建項(xiàng)目新建QtWidgetsApplication,項(xiàng)目名稱為mymainwindow,基類選擇QMainWindow,類名為MainWindow。3.1菜單(2)創(chuàng)建菜單創(chuàng)建完項(xiàng)目后,雙擊mainwindow.ui文件進(jìn)入設(shè)計(jì)模式。在這里可以看到界面左上角的“在這里輸入”,我們可以在這里添加菜單。雙擊“在這里輸入”,將其更改為“文件(&F)”,按下回車鍵結(jié)束。&——加速鍵定義字符。使得菜單可以用同時(shí)按Alt和字母快捷訪問(wèn)。顯示為下劃線。按同樣的方法,在文件菜單中添加“新建(&N)”菜單項(xiàng)。(3)添加菜單圖標(biāo)Qt中的一個(gè)菜單被看做是一個(gè)Action,我們?cè)谙旅娴腁ction編輯器(ActionEditor)中可以看到剛才添加的“新建”菜單。雙擊該條目,會(huì)彈出編輯動(dòng)作對(duì)話框,這里可以進(jìn)行各項(xiàng)設(shè)置點(diǎn)擊下拉框可以使用“選擇資源”或“選擇文件”兩種方式添加菜單圖標(biāo)。下面講解“選擇資源”的方式。向項(xiàng)目中添加新文件,模板選擇Qt分類中的Qt資源文件(QtResourceFile)。然后將名稱設(shè)置為MenuIcons。添加完文件后會(huì)自動(dòng)打開(kāi)該資源文件,首先需要添加前綴,點(diǎn)擊“AddPrefix”,默認(rèn)的前綴是“/new/prefix1”,這個(gè)可以隨意修改(不要出現(xiàn)中文字符),修
改為“/MenuImages”在項(xiàng)目目錄中新建一個(gè)文件夾,放入需要的圖標(biāo)文件點(diǎn)擊“AddFiles”,選入要用到的圖標(biāo)。完成后點(diǎn)保存。啟用圖標(biāo)打開(kāi)mainwindow.ui并切換到設(shè)計(jì)視圖,在下面ActionEditor窗口,中雙擊菜單Action,在彈出的對(duì)話框中選擇合適圖標(biāo)編譯運(yùn)行,得到如下效果按上述方法添加完整菜單,并在ActionEditor窗口中指定圖標(biāo)與快捷鍵。如圖3.2工具欄(4)向工具欄添加菜單圖標(biāo)在窗口中添加工具欄將ActionEditor中的Action拖動(dòng)到工具欄中作為快捷圖標(biāo)使用最終工具欄如下圖3.3文本編輯器與布局(5)加入文本編輯器拖入一個(gè)文本編輯器TextEdit部件在窗口空白處右擊,在彈出的快捷菜單中選擇“布局—柵格布局”。文本編輯器就會(huì)充滿中央?yún)^(qū)域。3.4實(shí)現(xiàn)功能代碼(6)本小節(jié)實(shí)現(xiàn)類似記事本的各種文本編輯功能打開(kāi)mainwindow.h,在類定義中添加代碼:classMainWindow:publicQMainWindow{Q_OBJECTpublic:MainWindow(QWidget*parent=nullptr);~MainWindow();public:voidNewFile();//新建文件操作
boolIsNeedSave();//判斷是否需要保存
boolSave();//保存操作
boolSaveAs();//另存為操作
boolSaveFile(constQString&sFileName);//保存文件
boolOpenFile(constQString&sFileName);//加載文件private:Ui::MainWindow*ui;private:boolm_bSaved;//文件是否保存過(guò)
QStringm_sFilePathName;//文件的保存路徑};在MainWindow.cpp頂部加入相關(guān)的頭文件#include"mainwindow.h"#include"ui_mainwindow.h"#include<QMessageBox>#include<QPushButton>#include<QFileDialog>#include<QTextStream>……在構(gòu)造函數(shù)中加入初始化代碼MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){ui->setupUi(this);m_bSaved=false;//初始化文件為未保存狀態(tài)
m_sFilePathName=tr("未命名.txt");//初始化文件名
setWindowTitle(m_sFilePathName);//設(shè)置窗口標(biāo)題}在MainWindow.cpp添加NewFile()定義voidMainWindow::NewFile(){if(IsNeedSave()){m_bSaved=false;m_sFilePathName=tr("未命名.txt");setWindowTitle(m_sFilePathName);ui->textEdit->clear();ui->textEdit->setVisible(true);}}在MainWindow.cpp添加IsNeedSave()定義boolMainWindow::IsNeedSave(){if(ui->textEdit->document()->isModified()){//如果文檔被更改了//定義一個(gè)提示対話框
QMessageBoxMsgBox;MsgBox.setWindowTitle(tr("警告"));MsgBox.setIcon(QMessageBox::Warning);MsgBox.setText(m_sFilePathName+tr("尚未保存,是否保存?"));QPushButton*yesBtn=MsgBox.addButton(tr("是(&Y)"),QMessageBox::YesRole);MsgBox.addButton(tr("否(&N)"),QMessageBox::NoRole);QPushButton*cancelBtn=MsgBox.addButton(tr("取消"),QMessageBox::RejectRole);MsgBox.exec();if(MsgBox.clickedButton()==yesBtn)returnSave();elseif(MsgBox.clickedButton()==cancelBtn)returnfalse;}returntrue;//如果文檔沒(méi)有被更改,則直接返回true}在MainWindow.cpp添加Save()和SaveAs()定義boolMainWindow::Save(){if(!m_bSaved){returnSaveAs();}else{returnSaveFile(m_sFilePathName);}}boolMainWindow::SaveAs(){QStringsFilePathName=QFileDialog::getSaveFileName(this,tr("另存為"),m_sFilePathName);if(sFilePathName.isEmpty())returnfalse;returnSaveFile(sFilePathName);}在MainWindow.cpp添加SaveFile()定義boolMainWindow::SaveFile(constQString&sFilePathName){QFilefile(sFilePathName);if(!file.open(QFile::WriteOnly|QFile::Text)){
//%1和%2分別對(duì)應(yīng)后面arg兩個(gè)參數(shù),/n為換行
QMessageBox::warning(this,tr("多文檔編輯器"),tr("無(wú)法寫入文件%1:/n%2").arg(sFilePathName).arg(file.errorString()));returnfalse;}QTextStreamout(&file);QApplication::setOverrideCursor(Qt::WaitCursor);//鼠標(biāo)指針變?yōu)榈却隣顟B(tài)out<<ui->textEdit->toPlainText();QApplication::restoreOverrideCursor();//鼠標(biāo)指針恢復(fù)原來(lái)的狀態(tài)m_bSaved=true;m_sFilePathName=QFileInfo(sFilePathName).canonicalFilePath();//獲得文件的標(biāo)準(zhǔn)路徑setWindowTitle(m_sFilePathName);returntrue;}3.5菜單響應(yīng)(7)在ActionEditor中設(shè)置菜單響應(yīng)上圖操作后,QT會(huì)為MainWindow類添加on_action_N_triggered()槽函數(shù)為on_action_N_triggered()槽函數(shù)添加代碼//新建動(dòng)作voidMainWindow::on_action_N_triggered()//橙色代碼表示從ActionEditor設(shè)置生成{NewFile();//黃色代碼為手動(dòng)鍵入}(8)同樣操作,為“保存”等各個(gè)菜單項(xiàng)添加槽函數(shù)和代碼//保存動(dòng)作voidMainWindow::on_action_S_triggered(){Save();}//另存為動(dòng)作voidMainWindow::on_action_A_triggered(){SaveAs();}//打開(kāi)動(dòng)作voidMainWindow::on_action_O_triggered(){if(IsNeedSave()){QStringsFilePathName=QFileDialog::getOpenFileName(this);//如果文件名不為空,則加載文件
if(!sFilePathName.isEmpty()){OpenFile(sFilePathName);ui->textEdit->setVisible(true);}}}//關(guān)閉動(dòng)作voidMainWindow::on_action_C_triggered(){
IsNeedSave();//若未存盤則先存盤
NewFile();//新建一個(gè)空白文檔}//撤銷動(dòng)作voidMainWindow::on_action_Z_triggered(){ui->textEdit->undo();//可看到,undo復(fù)制粘貼等功能都直接利用了textEdit自帶的功能}//剪切動(dòng)作voidMainWindow::on_action_X_triggered(){ui->textEdit->cut();}//復(fù)制動(dòng)作voidMainWindow::on_action_C_2_triggered(){ui->textEdit->copy();}//粘貼動(dòng)作voidMainWindow::on_action_V_triggered(){ui->textEdit->paste();}//退出動(dòng)作voidMainWindow::on_action_X_2_triggered(){on_action_C_triggered();//先執(zhí)行關(guān)閉操作,再退出程序qApp->quit();//qApp是指向應(yīng)用程序的全局指針}編譯運(yùn)行,程序已能實(shí)現(xiàn)記事本的
文本編輯功能3.6狀態(tài)欄動(dòng)作狀態(tài)提示
(9)在Action編輯器中選中動(dòng)作,然后在右面的屬性編輯器中對(duì)其statusTip屬性進(jìn)行更改。臨時(shí)狀態(tài)信息使用showMessage()函數(shù)可以為狀態(tài)欄添加一個(gè)臨時(shí)信息,它會(huì)出現(xiàn)在狀態(tài)欄的最左邊(10)在構(gòu)造函數(shù)中添加代碼:MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){ui->setupUi(this);m_bSaved=false;//初始化文件為未保存狀態(tài)
m_sFilePathName=tr("未命名.txt");//初始化文件名
setWindowTitle(m_sFilePathName);//設(shè)置窗口標(biāo)題
ui->statusbar->showMessage(tr("歡迎使用TextPad寫字本!"));}持久狀態(tài)信息使用addPermanentWidget()函數(shù)可以為狀態(tài)欄添加一個(gè)持久信息,它會(huì)出現(xiàn)在狀態(tài)欄的最右邊(11)在MainWindow.cpp頂部及構(gòu)造函數(shù)中添加代碼:……#include<QTextStream>#include<QLabel>MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){ui->setupUi(this);m_bSaved=false;//初始化文件為未保存狀態(tài)
m_sFilePathName=tr("未命名.txt");//初始化文件名
setWindowTitle(m_sFilePathName);//設(shè)置窗口標(biāo)題
ui->statusbar->showMessage(tr("歡迎使用TextPad寫字本!"));QLabel*labPermanent=newQLabel;labPermanent->setText(tr("版本:1.0"));ui->statusbar->addPermanentWidget(labPermanent);}至此,一個(gè)簡(jiǎn)易的文本編輯寫字本已基本完成。還有搜索和版本信息菜單項(xiàng)的功能請(qǐng)同學(xué)們自行實(shí)現(xiàn)。OK!第4節(jié)鼠標(biāo)與鍵盤鼠標(biāo)事件處理鍵盤事件處理4.1鼠標(biāo)事件處理通過(guò)重寫Qt事件處理函數(shù)來(lái)實(shí)現(xiàn)鼠標(biāo)和鍵盤事件處理例7-6鼠標(biāo)鍵盤事件響應(yīng)(1)新建QtWidgets應(yīng)用,項(xiàng)目名稱為“MouseAndKey”(2)完成項(xiàng)目創(chuàng)建后,在設(shè)計(jì)模式向界面上拖入一個(gè)Label(3)在MainWindow.h文件添加鼠標(biāo)按下事件處理函數(shù)聲明:classMainWindow:publicQMainWindow{Q_OBJECTpublic:MainWindow(QWidget*parent=nullptr);~MainWindow();protected:voidmousePressEvent(QMouseEvent*);private:Ui::MainWindow*ui;};(4)在MainWindow.cpp中添加頭文件及鼠標(biāo)處理函數(shù)定義#include"mainwindow.h"#include"ui_mainwindow.h"#include<QMouseEvent>……MainWindow::~MainWindow(){deleteui;}voidMainWindow::mousePressEvent(QMouseEvent*e){ui->label->setText(tr("(%1,%2)").arg(e->x()).arg(e->y()));}同理,除了鼠標(biāo)按下事件,還有鼠標(biāo)釋放、雙擊、移動(dòng)、滾輪等事件,其處理方式與這個(gè)例子相似4.2鍵盤事件處理(5)在MainWindow.h文件添加鍵盤按下事件處理函數(shù)聲明:classMainWindow:publicQMainWindow{Q_OBJECTpublic:MainWindow(QWidget*parent=nullptr);~MainWindow();protected:voidmousePressEvent(QMouseEvent*);voidkeyPressEvent(QKeyEvent*);private:Ui::MainWindow*ui;};(6)在MainWindow.cpp中添加頭文件及鍵盤處理函數(shù)定義……#include<QMouseEvent>#include<QKeyEvent>……voidMainWindow::keyPressEvent(QKeyEvent*e){//打印出按鍵字符
QStringsMsg;sMsg=QString::asprintf("Keypressed:%c",e->key());ui->label->setText(sMsg);//移動(dòng)標(biāo)簽
intnX=ui->label->x();intnY=ui->label->y();switch(e->key()){caseQt::Key_W:ui->label->move(nX,nY-5);break;caseQt::Key_S:ui->label->move(nX,nY+5);break;caseQt::Key_A:ui->label->move(nX-5,nY);break;caseQt::Key_D:ui->label->move(nX+5,nY);break;}}
同理,還有鍵盤釋放事件,處理相似OK!第5節(jié)簡(jiǎn)單繪圖常用繪圖類簡(jiǎn)單繪圖示例5.1繪圖常用類QPainter類可以繪制一切想要的圖形,從最簡(jiǎn)單的一條直線到其他任何復(fù)雜的圖形,它還可以用來(lái)繪制文本和圖片。重繪事件QPainter一般在一個(gè)部件的重繪事件(PaintEvent)處理函數(shù)paintEvent()中進(jìn)行繪制。QPen類畫(huà)筆類。可以控制圖形的顏色、線寬和線型。QBrush類
畫(huà)刷類。為封閉圖形填充顏色和圖案。5.2例7-7簡(jiǎn)單繪圖示例(1)新建QtWidgets應(yīng)用,項(xiàng)目名稱為SimpleDraw(2)在mainwindow.h文件中添加重繪事件處理函數(shù)的聲明:classMainWindow:publicQMainWindow{Q_OBJECTpublic:MainWindow(QWidget*parent=nullptr);~MainWindow();protected:voidpaintEvent(QPaintEvent*);private:Ui::MainWindow*ui;};(3)在MainWindow.cpp中添加頭文件及重繪事件函數(shù)定義……#include<QPainter>……MainWindow::~MainWindow(){deleteui;}voidMainWindow::paintEvent(QPaintEvent*){QPainterpainter(this);painter.drawLine(QPointF(100,100),QPointF(200,200));//簡(jiǎn)單畫(huà)線QPenpen;//畫(huà)筆
pen.setColor(QColor(255,0,0));QBrushbrush(QColor(0,0,255,128));//畫(huà)刷。顏色第四個(gè)參數(shù)為透明度
painter.setPen(pen);//選擇畫(huà)筆
painter.setBrush(brush);//選擇畫(huà)刷
painter.drawRect(200,100,100,100);//繪制矩形pen.setColor(QColor(255,0,255));pen.setWidth(5);brush.setColor(QColor(255,255,0));brush.setStyle(Qt::CrossPattern);//CrossPattern為十字線填充,更多圖案參見(jiàn)幫助
painter.setPen(pen);painter.setBrush(brush);painter.drawEllipse(300,100,100,100);//繪制圓
pen.setColor(QColor(0,128,128));pen.setStyle(Qt::DashLine);//DashLine為虛線。更多線型參見(jiàn)幫助
painter.setPen(pen);painter.drawLine(QPointF(400,200),QPointF(500,100));//繪制虛線}OK!小結(jié)MFC與QT的比較開(kāi)發(fā)速度MFC√運(yùn)行效率MFC√代碼風(fēng)格
QT封裝哲學(xué)√適用平臺(tái)MFC:Windows√QT:Window、Android、iOS…--eg./naibozhuan3744/article/details/78909086/作業(yè)對(duì)照PPT,重做例7-5TextPad程序C++程序設(shè)計(jì)第8章視頻與音頻第1節(jié)音視頻開(kāi)發(fā)概述第2節(jié)DirectShow音視頻開(kāi)發(fā)第3節(jié)SDL多媒體開(kāi)發(fā)庫(kù)第4節(jié)FFMpeg音視頻開(kāi)發(fā)(一)第5節(jié)FFMpeg音視頻開(kāi)發(fā)(二)第1節(jié)音視頻開(kāi)發(fā)概述音視頻開(kāi)發(fā)應(yīng)用領(lǐng)域常用的音視頻開(kāi)發(fā)庫(kù)1.1音視頻開(kāi)發(fā)應(yīng)用領(lǐng)域音視頻播放軟件音視頻采集、錄制視頻監(jiān)控音視頻編輯、格式轉(zhuǎn)化軟件網(wǎng)絡(luò)直播數(shù)字電視1.2常用的音視頻開(kāi)發(fā)庫(kù)(1)微軟:VideoForWindows(VFW)→DirectShow
→MediaFoundation特征:Windows系統(tǒng)適用
難度:★★常用的音視頻開(kāi)發(fā)庫(kù)(2)FFMpeg全稱:FastForwardMovingpictureexpertgroup特征:
功能強(qiáng)大
格式覆蓋全
跨平臺(tái)
難度:★★★★官網(wǎng):/常用的音視頻開(kāi)發(fā)庫(kù)(3)VLC全稱:VideoLanClient特征:支持大多數(shù)音視頻格式
跨平臺(tái)官網(wǎng):/常用的音視頻開(kāi)發(fā)庫(kù)(4)Gstreamer全稱:VideoLanClient特征:支持大多數(shù)音視頻格式
跨平臺(tái)官網(wǎng):/第2節(jié)DirectShow音視頻開(kāi)發(fā)DirectShow簡(jiǎn)介DirectShow構(gòu)架最簡(jiǎn)單的DirectShow播放器MFC圖形界面DirectShow2.1DirectShow簡(jiǎn)介DirectShow(簡(jiǎn)稱DShow)是一個(gè)Windows平臺(tái)上的流媒體框架,提供了高質(zhì)量的多媒體流采集和回放功能。它支持多種多樣的媒體文件格式,包括ASF、MPEG、AVI、MP3和WAV等多種文件。VideoForWindows(VFW)→DirectShow
→MediaFoundation開(kāi)發(fā)語(yǔ)言:C++2.2DirectShow架構(gòu)DirectShow是一個(gè)開(kāi)放性的應(yīng)用框架,也是一套基于COM的編程接口。DirectShow使用一種交FilterGraph的模型來(lái)管理整個(gè)數(shù)據(jù)流的處理過(guò)程;參與數(shù)據(jù)處理的各個(gè)功能模塊叫做Filter;各個(gè)Filter在FilterGraph中按一定的順序連接成一條"流水線"協(xié)同工作。Filter,它是最基本的軟件構(gòu)件,過(guò)濾器通常在多媒體流中執(zhí)行一個(gè)操作。各個(gè)Filter在FilterGraph中按一定的順序連接成一條"流水線"協(xié)同工作。DirectShow的Filter與各種設(shè)備進(jìn)行通信并對(duì)它們進(jìn)行相應(yīng)的控制,這些設(shè)備包括本地文件系統(tǒng)、電視卡、視頻采集卡、VFW編解碼器、顯示器和聲卡。通過(guò)這種方式,DirectShow成功的隔離了應(yīng)用程序和各種復(fù)雜設(shè)備。2.3最簡(jiǎn)單的DirectShow播放器例8-1一個(gè)最簡(jiǎn)單的基于DirectShow的播放器2.3.1流程1.最簡(jiǎn)單的基于DirectShow的視頻播放器的流程圖如右圖CoInitialize()CoCreateInstance(…,pGraph)pGraph->QueryInterface(…,pControl)pGraph->QueryInterface(…,pEvent)pGraph->RenderFile(“xxxx.mp4”)pControl->Run()pEvent->WaitForCompletionCoUnInitialize()成員變量:IGraphBuilder*pGraph;IMediaControl*pControl;IMediaEvent*pEvent;2.3.1流程2.流程圖中涉及到幾個(gè)接口:IGraphBuilder:繼承自IFilterGraph,用于構(gòu)建FilterGraph。相比于IFilterGraph來(lái)說(shuō)IGraphBuilder提供了一些更加“智能”的方法,例如RenderFile()方法。IMediaControl:提供和播放控制有關(guān)的一些接口。IMediaEvent:用來(lái)處理FilterGraph發(fā)出的事件。流程3.流程圖中關(guān)鍵函數(shù)CoInitialize():初始化COM運(yùn)行環(huán)境。CoCreateInstance(…,pGraph):用指定的類標(biāo)識(shí)符創(chuàng)建一個(gè)Com對(duì)象。在該播放器中類標(biāo)識(shí)符為“CLSID_FilterGraph”,用于創(chuàng)建IGraphBuilder。pGraph->QueryInterface(…,pControl):通過(guò)QueryInterface()查詢某個(gè)組件是否支持某個(gè)特定的接口。在這里查詢IMediaControl接口。pGraph->QueryInterface(…,pEvent):同上。在這里查詢IMediaEvent接口。pGraph->RenderFile("xxxx.mp4"):為指定的文件智能的構(gòu)建一個(gè)FilterGraph。pControl->Run():開(kāi)始運(yùn)行FilterGraph中的所有Filter。pEvent->WaitForCompletion():等待FilterGraph處理完所有數(shù)據(jù)。CoUninitialize():釋放CoInitialize()初始化的COM運(yùn)行環(huán)境。2.3.2步驟啟動(dòng)VisualStudio(如VS2022),創(chuàng)建一個(gè)控制臺(tái)項(xiàng)目。項(xiàng)目名稱可取為SimpleDShowPlayer把cpp文件中的代碼替換成以下代碼:#include<DShow.h>#pragmacomment(lib,“strmiids.lib”)//使用DirectShow需要這個(gè)庫(kù)文件//請(qǐng)嘗試去掉這句,而用這種方法替代:菜單“項(xiàng)目--***屬性”,彈出對(duì)話框中找//到“配置屬性--鏈接器--輸入--附加依賴項(xiàng)”,添加“strmiids.lib”。具有同樣效果//用宏定義定義釋放的過(guò)程#defineSAFE_RELEASE(filter){if(NULL!=filter){filter->Release();filter=NULL;}}intmain(){IGraphBuilder*pGraphBuilder=NULL; //Filtergraph管理器
IMediaControl*pMediaControl=NULL; //控制視頻/音頻的播放、暫停與停止
IMediaEvent*pMediaEvent=NULL; //捕獲播放過(guò)程中的事件CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);//初始化COM運(yùn)行環(huán)境
//創(chuàng)建Filtergraph管理器對(duì)象HRESULThr=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&pGraphBuilder);if(FAILED(hr)){printf("CoCreateInstanceFailed!\n");goto__exit;}
//獲取IMediaControl接口hr=pGraphBuilder->QueryInterface(IID_IMediaControl,(void**)&pMediaControl);if(FAILED(hr)){printf("QueryMediaControlInterfaceFailed!\n");goto__exit;}
//獲取IMediaEvent接口hr=pGraphBuilder->QueryInterface(IID_IMediaEvent,(void**)&pMediaEvent);if(FAILED(hr)){printf("QueryMediaEventInterfaceFailed!\n");goto__exit;}
//打開(kāi)視頻文件
hr=pGraphBuilder->RenderFile(L“..\\..\\VideoForTest\\Megamind.avi”,NULL);//可改路徑文件
if(FAILED(hr)){printf("RenderFileFailed!\n");goto__exit;}
//視頻播放hr=pMediaControl->Run();if(FAILED(hr)){printf("RunFailed!\n");goto__exit;}{longcode=0;hr=pMediaEvent->WaitForCompletion(INFINITE,&code);//等待視頻播放完畢
if(FAILED(hr)){printf("WaitForCompletionFailed!\n");goto__exit;}}__exit:
//清理變量回收內(nèi)存SAFE_RELEASE(pMediaEvent);SAFE_RELEASE(pMediaControl);SAFE_RELEASE(pGraphBuilder);CoUninitialize();system("pause");return0;}編譯,運(yùn)行--OK!2.4圖形界面DirectShow播放器例8-2一個(gè)基于MFC圖形界面的DirectShow的播放器參看課件提供的代碼自行學(xué)習(xí),課堂上不詳細(xì)講述了。第3節(jié)SDL多媒體開(kāi)發(fā)庫(kù)SDL簡(jiǎn)介SDL開(kāi)發(fā)設(shè)置SDL顯示流程SDL顯示圖片SDL事件驅(qū)動(dòng)SDL鍵盤事件3.1SDL簡(jiǎn)介SDL是SimpleDirectMediaLayer(簡(jiǎn)易直控媒體層)的縮寫。它是一個(gè)跨平臺(tái)的多媒體庫(kù),以用于直接控制底層的多媒體硬件的接口。這些多媒體功能包括了音頻、鍵盤和鼠標(biāo)(事件)、游戲搖桿等。其最為重要的是提供了2D圖形幀緩沖(framebuffer)的接口,以及為OpenGL與各種操作系統(tǒng)之間提供了統(tǒng)-的標(biāo)準(zhǔn)接口以實(shí)現(xiàn)3D圖形。從這些屬性我們可以看出,SDL基本上可以認(rèn)為是為以電腦游戲?yàn)楹诵拈_(kāi)發(fā)的多媒體庫(kù)。C語(yǔ)言寫成,可在C++下工作官網(wǎng):/最新版本:SDL2.0第4節(jié)FFMpeg將會(huì)用到SDL顯示視頻圖像,因此有必要先學(xué)習(xí)一下SDL。3.2SDL開(kāi)發(fā)設(shè)置從官網(wǎng)下載最新的SDL2(/download-2.0.php),或者從課件資料中拷貝SDL2,解壓,放到某個(gè)方便記憶的目錄位置,例如“D:\SDL2\SDL2”SDL開(kāi)發(fā)設(shè)置以后在每一個(gè)需要SDL的VisualStudtio工程中,菜單“項(xiàng)目–xxx屬性”,在彈出的屬性頁(yè)對(duì)話框中,在配置屬性樹(shù)中點(diǎn)“VC++目錄”,然后在“包含目錄”中添加SDL中的include目錄,如“D:\SDL2\SDL2\include”;再在“庫(kù)目錄”中添加SDL中的lib目錄,如“D:\SDL2\SDL2\lib\x64”。請(qǐng)根據(jù)VS中編譯的版本是x64還是x86來(lái)正確選擇lib下的x64或x86目錄。SDL開(kāi)發(fā)設(shè)置再在“鏈接器-輸入-附加依賴項(xiàng)”中添加“SDL2.lib;SDL2main.lib;”。把lib目錄下(注意正確選擇x64或x86目錄)的SDL2.dll拷貝工程目錄下3.3SDL2.0顯示流程SDL_Init()SDL_CreateWindow()SDL_CreateRenderer()SDL_CreateTexture()SDL_UpdateTexture()SDL_RenderCopy()SDL_RenderPresent()Decode()YUV/RGB顯示主要函數(shù)簡(jiǎn)介SDL_Init():初始化SDL系統(tǒng)SDL_CreateWindow():創(chuàng)建窗口SDL_WindowSDL_CreateRenderer():創(chuàng)建渲染器SDL_RendererSDL_CreateTexture():創(chuàng)建紋理SDL_TextureSDL_UpdateTexture():設(shè)置紋理的數(shù)據(jù)SDL_RenderCopy():將紋理的數(shù)據(jù)拷貝給渲染器SDL_RenderPresent():顯示SDL_Delay():工具函數(shù),用于延時(shí)。SDL_Quit():退出SDL系統(tǒng)3.4SDL顯示圖片例8-3使用SDL顯示一張bmp圖片步驟:(1)打開(kāi)VS,創(chuàng)建一個(gè)控制臺(tái)工程。工程起名為“HelloSDL”(2)按照3.2節(jié)設(shè)置好SDL開(kāi)發(fā)環(huán)境(3)打開(kāi)HelloSDL.cpp,把原來(lái)的代碼替換成以下代碼:#defineSDL_MAIN_HANDLED#include<iostream>#include<SDL.h>usingnamespacestd;intmain(){//初始化SDLif(SDL_Init(SDL_INIT_VIDEO)){cout<<"SDL_InitError:"<<SDL_GetError()<<endl;return-1;}//創(chuàng)建窗口
SDL_Window*pWin=SDL_CreateWindow("HelloWorld!",100,100,640,480,SDL_WINDOW_SHOWN);if(pWin==nullptr){cout<<"SDL_CreateWindowError:"<<SDL_GetError()<<endl;return-1;}
//創(chuàng)建渲染器
SDL_Renderer*pRen=SDL_CreateRenderer(pWin,-1,SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);//第三個(gè)參數(shù)是:開(kāi)啟硬件//加速|(zhì)控制屏幕幀率不超過(guò)電腦默認(rèn)刷新率,如果改為0//的話CPU和GPU占用率會(huì)比較高
if(pRen==nullptr){SDL
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 案件辦理委托協(xié)議
- 貴州省六盤水市2025屆高三第二次診斷性監(jiān)測(cè)考試語(yǔ)文試題
- 感恩同行青春追夢(mèng)
- 2025年全球及中國(guó)升降式傳遞窗行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025-2030全球沖壓飛輪行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- 2025年全球及中國(guó)天窗玻璃更換和維修行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025年全球及中國(guó)量子信息系統(tǒng)服務(wù)行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025年度食品飲料代理銷售服務(wù)合同
- 二零二五年度石油化工設(shè)備采購(gòu)代理協(xié)議3篇
- 數(shù)字化工作空間與創(chuàng)新園區(qū)的未來(lái)展望
- 電氣工程及其自動(dòng)化專業(yè)《畢業(yè)設(shè)計(jì)(論文)及答辯》教學(xué)大綱
- 《客艙安全管理與應(yīng)急處置》課件-第14講 應(yīng)急撤離
- 中華人民共和國(guó)文物保護(hù)法
- 2025屆高考作文押題預(yù)測(cè)5篇
- 節(jié)前物業(yè)安全培訓(xùn)
- 一年級(jí)數(shù)學(xué)(上)計(jì)算題專項(xiàng)練習(xí)集錦
- 阿里巴巴國(guó)際站:2024年珠寶眼鏡手表及配飾行業(yè)報(bào)告
- 高甘油三酯血癥相關(guān)的器官損傷
- 手術(shù)室護(hù)士考試題及答案
- 牙膏項(xiàng)目創(chuàng)業(yè)計(jì)劃書(shū)
- 單位食堂供餐方案
評(píng)論
0/150
提交評(píng)論