引言
QMainWindow 是一個為使用者提供主視窗程式的類,包含一個選單欄(menu bar)、多個工具欄(tool bars)、多個錨接部件(dock widgets)、一個狀態列(status bar)及一箇中心部件(central widget),是許多應用程式的基礎,如文字編輯器,圖片編輯器等。(本篇主要介紹選單欄和工具欄)
一,選單欄
一個主視窗最多隻有一個選單欄。位於主視窗頂部、主視窗標題欄下面。
- 建立選單欄。
QMenuBar* menuBar = new QMenuBar(this);
-
建立選單,呼叫 QMenu 的成員函式 addMenu 來新增選單
QAction* addMenu(QMenu * menu)
QMenu* addMenu(const QString & title)
QMenu* addMenu(const QIcon & icon, const QString & title)
- 建立選單項,呼叫 QMenu 的成員函式 addAction 來新增選單項
QAction* activeAction()
QAction* addAction(const QString & text)
QAction* addAction(const QIcon & icon, const QString & text)
QAction* addAction(const QString & text, const QObject * receiver, const char * member, const QKeySequence & shortcut = 0)
QAction* addAction(const QIcon & icon, const QString & text, const QObject * receiver, const char * member,const QKeySequence & shortcut = 0)
例項演示:(vs2019+qt5)
//建立選單欄 QMenuBar* menuBar = new QMenuBar(this); //建立選單(用addMenu方法新增入選單欄) QMenu* filename = menuBar->addMenu(QStringLiteral("檔案(&F)")); //建立選單項 QAction* openfile = new QAction(QStringLiteral("開啟檔案(&O)")); QAction* opendlg = new QAction(QStringLiteral("開啟對話方塊(&D)")); //給選單項添入圖示 openfile->setIcon(QIcon(":/D:/image/Luffy.png")); opendlg->setIcon(QIcon(":/D:/image/LuffyQ.png")); //用addAction加入選單項 filename->addAction(opendlg); filename->addAction(openfile);
注意:使用 QStringLiteral 巨集可以在編譯期把程式碼裡的常量字串 str 直接構造為 QString 物件,於是執行時就不再需要額外的構造開銷了。
資原始檔的新增
openfile->setIcon(QIcon(":/D:/image/Luffy.png"));
對於該句程式碼":/D:/image/Luffy.png"是以相對路徑新增的(即以:/開頭的是資原始檔),那麼如何新增資原始檔呢?
- 新增->新建項->Qt->Qt Resource File。
- 在Resource1.qrc中新增說需要的資源(比如圖片)
最後以冒號+字首+名稱(相對路徑)寫入資源。
二,工具欄
主視窗的工具欄上可以有多個工具條,通常採用一個選單對應一個工具條的的方式,也可根據需要進行工具條的劃分。
新增標頭檔案
-
直接呼叫 QMainWindow 類的 addToolBar()函式獲取主視窗的工具條物件,每增加一個工具條都需要呼叫一次該函式
-
插入屬於工具條的動作,即在工具條上新增操作。通過 QToolBar 類的 addAction 函式新增
-
工具條是一個可移動的視窗,它的停靠區域由 QToolBar 的 allowAreas 決定,包括:
- Qt::LeftToolBarArea 停靠在左側
- Qt::RightToolBarArea停靠在右側
- Qt::TopToolBarArea 停靠在頂部
- Qt::BottomToolBarArea停靠在底部
- Qt::AllToolBarAreas以上四個位置都可停靠
使用 setAllowedAreas()函式指定停靠區域:
setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea)
使用 setMoveable()函式設定工具欄的可移動性:
setMoveable(false)//工具條不可移動, 只能停靠在初始化的位置上
三,對話方塊 QDialog
對話方塊是 GUI 程式中不可或缺的組成部分。很多不能或者不適合放入主視窗的功能元件都必須放在對話方塊中設定。對話方塊通常會是一個頂層視窗,出現在程式最上層,用於實現短期任務或者簡潔的使用者互動。
Qt 中使用 QDialog 類實現對話方塊。就像主視窗一樣,我們通常會設計一個類繼承 QDialog。QDialog(及其子類,以及所有 Qt::Dialog 型別的類)的對於其parent 指標都有額外的解釋:如果 parent 為 NULL,則該對話方塊會作為一個頂
層視窗,否則則作為其父元件的子對話方塊(此時,其預設出現的位置是 parent的中心)。頂層視窗與非頂層視窗的區別在於,頂層視窗在工作列會有自己的位置,而非頂層視窗則會共享其父元件的位置。
1️⃣對話方塊分為模態對話方塊和非模態對話方塊。
- 模態對話方塊,就是會阻塞同一應用程式中其它視窗的輸入。模態對話方塊很常見,比如“開啟檔案”功能。你可以嘗試一下記事本的開啟檔案,當開啟檔案對話方塊出現時,我們是不能對除此對話方塊之外的視窗部分進行操作的。
- 與此相反的是非模態對話方塊,例如查詢對話方塊,我們可以在顯示著查詢對話方塊的同時,繼續對記事本的內容進行編輯。
模態與非模態的實現:
- 使用 QDialog::exec()實現應用程式級別的模態對話方塊
- 使用 QDialog::open()實現視窗級別的模態對話方塊
- 使用 QDialog::show()實現非模態對話方塊。
模態對話方塊例項:
我們呼叫了 exec()將對話方塊顯示出來,因此這就是一個模態對話方塊。當對話方塊出現時,我們不能與主視窗進行任何互動,直到我們關閉了該對話方塊。
QDialog dlg1(this); dlg1.resize(300,200); dlg1.setWindowTitle(QStringLiteral("模態對話方塊")); dlg1.exec();
非模態對話方塊例項:
下面我們試著將 exec()修改為 show(),看看非模態對話方塊:
QDialog dlg1(this); dlg1.resize(300,200); dlg1.setWindowTitle(QStringLiteral("模態對話方塊")); dlg1.show();
是不是事與願違?對話方塊竟然一閃而過!這是因為,show()函式不會阻塞當前執行緒,對話方塊會顯示出來,然後函式立即返回,程式碼繼續執行。注意,dialog 是建立在棧上的,show()函式返回,函式結束,dialog超出作用域被析構,因此對話方塊消失了。知道了原因就好改了,我們將 dialog改成堆上建立(即new一個物件),當然就沒有這個問題了。
QDialog *dlg2 = new QDialog(); dlg2->resize(200, 200); dlg2->setAttribute(Qt::WA_DeleteOnClose);//關閉時清理記憶體 dlg2->show();
注意:在堆上就不能用點(.)了,要用->。而且由於使用 new 在堆上分配空間,卻一直沒有 delete。因此我們用setAttribute()函式設定對話方塊關閉時,自動銷燬對話方塊。
2️⃣標準檔案對話方塊
QFileDialog,也就是檔案對話方塊。
我們使用 QFileDialog::getOpenFileName()來獲取需要開啟的檔案的路徑。這個函式原型如下:
QString getOpenFileName(QWidget * parent = 0, //父視窗 const QString & caption = QString(), //對話方塊標題 const QString & dir = QString(), //對話方塊開啟的預設路徑 const QString & filter = QString(), //過濾器(例如我們使用“imagefile(*.jpg*.png)”則只顯示jpg和png檔案。多個過濾器用“;;”分割。 QString * selectedFilter = 0, //預設選擇的過濾器 Options options = 0 //對話方塊的引數設定 )
下面是最主要的 openFile()和 saveFile()這兩個函式的程式碼:
//開啟檔案 void MainWindow::openFile() { QString path = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Text Files(*.txt)")); if(!path.isEmpty()) { QFile file(path); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::warning(this, tr("Read File"), tr("Cannot open file:\n%1").arg(path)); return; } QTextStream in(&file); textEdit->setText(in.readAll()); file.close(); } else { QMessageBox::warning(this, tr("Path"), tr("You did not select any file.")); } }
//儲存檔案 void MainWindow::saveFile() { QString path = QFileDialog::getSaveFileName(this, tr("Open File"), ".", tr("Text Files(*.txt)")); if(!path.isEmpty()) { QFile file(path); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::warning(this, tr("Write File"), tr("Cannot open file:\n%1").arg(path)); return; } QTextStream out(&file); out << textEdit->toPlainText(); file.close(); } else { QMessageBox::warning(this, tr("Path"), tr("You did not select any file.")); } }
例項演示:建立選單欄,選單項為開啟資料夾和對話方塊。點選開啟對應功能。
//選單檔案 // 使用 QStringLiteral 巨集可以在編譯期把程式碼裡的常量字串 str 直接構造為 QString 物件,於是執行時就不再需要額外的構造開銷了。 QMenuBar* menuBar = new QMenuBar(this); QMenu* filename = menuBar->addMenu(QStringLiteral("檔案(&F)")); QAction* openfile = new QAction(QStringLiteral("開啟檔案(&O)")); QAction* opendlg = new QAction(QStringLiteral("開啟對話方塊(&D)")); openfile->setIcon(QIcon(":/D:/image/Luffy.png")); opendlg->setIcon(QIcon(":/D:/image/LuffyQ.png")); filename->addAction(opendlg); filename->addAction(openfile); //開啟對話方塊 connect(opendlg, &QAction::triggered, [=]() { //模態對話方塊(不可對其他對話方塊操作) QDialog dlg1(this); dlg1.resize(300,200); dlg1.setWindowTitle(QStringLiteral("模態對話方塊")); dlg1.exec(); //非模態對話方塊(可以對其他對話方塊操作) // QDialog *dlg2 = new QDialog(); //dlg2->resize(200, 200); //dlg2->setAttribute(Qt::WA_DeleteOnClose);//關閉時清理記憶體 //dlg2->show(); });
//開啟資料夾 connect(openfile, &QAction::triggered, [=]() { QFileDialog fdlg(this); fdlg.getOpenFileName(this, QStringLiteral("選擇檔案"), "D:\\", tr("Image(*.jpg*.png)")); });