Qt 文档编辑设置
該文章原創(chuàng)于Qter開(kāi)源社區(qū)(www.qter.org),作者yafeilinux,轉(zhuǎn)載請(qǐng)注明出處!
? ?? ??前面已經(jīng)在主窗口中添加了菜單和工具欄,這一篇中我們將實(shí)現(xiàn)基本的文本編輯功能。在開(kāi)始正式寫(xiě)程序之前,我們先要考慮一下整個(gè)流程。因?yàn)檫@里要寫(xiě)一個(gè)記事本一樣的程序,所以最好先打開(kāi)Windows中的記事本,進(jìn)行一些簡(jiǎn)單的操作,然后考慮怎樣去實(shí)現(xiàn)這些功能。再者,再?gòu)?qiáng)大的軟件,它的功能也是一個(gè)一個(gè)加上去的,不要設(shè)想一下子寫(xiě)出所有的功能。我們這里先實(shí)現(xiàn)新建文件,保存文件,和文件另存為三個(gè)功能,是因?yàn)樗鼈兟?lián)系很緊,而且這三個(gè)功能總的代碼量也不是很大。
一、實(shí)現(xiàn)新建文件、文件保存和另存為功能 二、實(shí)現(xiàn)打開(kāi)、關(guān)閉、退出、撤銷、復(fù)制、剪切、粘貼等功能
一、實(shí)現(xiàn)新建文件、文件保存和另存為功能
? ?? ?這一篇中實(shí)現(xiàn)了最基本的編輯功能,現(xiàn)在還剩下查找和幫助菜單沒(méi)有實(shí)現(xiàn),這個(gè)會(huì)在下一篇進(jìn)行介紹。如果大家想學(xué)習(xí)一個(gè)更完整的文本編輯器的實(shí)現(xiàn),可以參考《Qt及QtQuick開(kāi)發(fā)實(shí)戰(zhàn)精解》一書(shū)的第一章
? ?? ??前面已經(jīng)在主窗口中添加了菜單和工具欄,這一篇中我們將實(shí)現(xiàn)基本的文本編輯功能。在開(kāi)始正式寫(xiě)程序之前,我們先要考慮一下整個(gè)流程。因?yàn)檫@里要寫(xiě)一個(gè)記事本一樣的程序,所以最好先打開(kāi)Windows中的記事本,進(jìn)行一些簡(jiǎn)單的操作,然后考慮怎樣去實(shí)現(xiàn)這些功能。再者,再?gòu)?qiáng)大的軟件,它的功能也是一個(gè)一個(gè)加上去的,不要設(shè)想一下子寫(xiě)出所有的功能。我們這里先實(shí)現(xiàn)新建文件,保存文件,和文件另存為三個(gè)功能,是因?yàn)樗鼈兟?lián)系很緊,而且這三個(gè)功能總的代碼量也不是很大。
一、實(shí)現(xiàn)新建文件、文件保存和另存為功能 二、實(shí)現(xiàn)打開(kāi)、關(guān)閉、退出、撤銷、復(fù)制、剪切、粘貼等功能
一、實(shí)現(xiàn)新建文件、文件保存和另存為功能
?
1.首先來(lái)分析下整個(gè)流程,當(dāng)新建文件時(shí),要考慮是否保存正在編輯的文件,如果需要保存,還要根據(jù)該文件以前是否保存過(guò)來(lái)進(jìn)行保存或者另存為操作。下面我們根據(jù)這里的分析來(lái)添加需要的函數(shù)和對(duì)象。?
2.打開(kāi)上一篇完成的項(xiàng)目,然后先在main.cpp文件中添加代碼來(lái)保證代碼中可以使用中文字符。 首先添加#include?<QTextCodec>頭文件包含,然后在主函數(shù)中添加如下代碼: QTextCodec::setCodecForTr(QTextCodec::codecForLocale());?
3.在mainwindow.h文件中添加public函數(shù)聲明: void?newFile();? ?//?新建操作 bool?maybeSave(); //?判斷是否需要保存 bool?save();? ?? ?//?保存操作 bool?saveAs();? ? //?另存為操作 bool?saveFile(const QString &fileName); //?保存文件?
這里的幾個(gè)函數(shù)就是用來(lái)完成功能邏輯的,下面我們會(huì)添加它們的定義來(lái)實(shí)現(xiàn)相應(yīng)的功能。因?yàn)檫@幾個(gè)功能聯(lián)系緊密,所以這幾個(gè)函數(shù)會(huì)相互調(diào)用。?
4.然后添加private變量定義: //?為真表示文件沒(méi)有保存過(guò),為假表示文件已經(jīng)被保存過(guò)了 bool?isUntitled; //?保存當(dāng)前文件的路徑 QString?curFile;?
這里的isUntitled是一個(gè)標(biāo)志,用來(lái)判斷文檔是否被保存過(guò)。而curFile用來(lái)保存當(dāng)前打開(kāi)的文件的路徑。?
5.下面到mainwindow.cpp文件,先添加頭文件: #include?<QMessageBox> #include?<QPushButton> #include?<QFileDialog> #include?<QTextStream> 然后在構(gòu)造函數(shù)中添加如下代碼來(lái)進(jìn)行一些初始化操作: //?初始化文件為未保存狀態(tài) isUntitled = true; //?初始化文件名為"未命名.txt" curFile = tr("未命名.txt"); //?初始化窗口標(biāo)題為文件名 setWindowTitle(curFile); ? ??這里設(shè)置了在啟動(dòng)程序時(shí)窗口標(biāo)題顯示文件的名字,效果如下圖所示。 <ignore_js_op>?
6.下面添加那幾個(gè)函數(shù)的定義。 首先是新建文件操作的函數(shù): void?MainWindow::newFile() { ? ?if?(maybeSave()) { ? ?? ??isUntitled?=?true; ? ?? ??curFile?=?tr("未命名.txt"); ? ?? ??setWindowTitle(curFile); ? ?? ??ui->textEdit->clear(); ? ?? ??ui->textEdit->setVisible(true); ? ?} } 這里先使用maybeSave()來(lái)判斷文檔是否需要保存,如果已經(jīng)保存完了,則新建文檔,并進(jìn)行初始化。下面是maybeSave()函數(shù)的定義: bool?MainWindow::maybeSave() { ? ?//?如果文檔被更改了 if (ui->textEdit->document()->isModified()) { // 自定義一個(gè)警告對(duì)話框 ? ?? ??QMessageBox?box; ? ?? ??box.setWindowTitle(tr("警告")); ? ?? ??box.setIcon(QMessageBox::Warning); ? ?? ??box.setText(curFile + tr("?尚未保存,是否保存?")); ? ?? ??QPushButton?*yesBtn?=?box.addButton(tr("是(&Y)"), ? ?? ?? ?? ?? ?? ?? ?? ?QMessageBox::YesRole); ? ?? ??box.addButton(tr("否(&N)"),?QMessageBox::NoRole); ? ?? ??QPushButton?*cancelBut?=?box.addButton(tr("取消"), ? ?? ?? ?? ?? ?? ?? ?? ?QMessageBox::RejectRole); ? ?? ??box.exec(); ? ?? ??if?(box.clickedButton() == yesBtn) ? ?? ?? ?? ?return?save(); ? ?? ??else?if?(box.clickedButton() == cancelBut) ? ?? ?? ?? ?return?false; ? ?} ? ?//?如果文檔沒(méi)有被更改,則直接返回true ? ?return?true; } ? ??這里先使用了isModified()來(lái)判斷文檔是否被更改了,如果被更改了,則彈出對(duì)話框讓用戶選擇是否進(jìn)行保存,或者取消操作。如果取消操作,那么就返回false,什么都不執(zhí)行。下面是save()函數(shù)的定義: bool?MainWindow::save() { ? ?if?(isUntitled)?{ ? ?? ??return?saveAs(); ? ?}?else?{ ? ?? ??return?saveFile(curFile); ? ?} } ? ??這里如果文檔以前沒(méi)有保存過(guò),那么執(zhí)行另存為操作saveAs(),如果已經(jīng)保存過(guò),那么調(diào)用saveFile()執(zhí)行文件保存操作。下面是saveAs()函數(shù)的定義: bool?MainWindow::saveAs() { ? ?QString?fileName?=?QFileDialog::getSaveFileName(this, ? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???tr("另存為"),curFile); ? ?if?(fileName.isEmpty()) return false; ? ?return?saveFile(fileName); } 這里使用QFileDialog來(lái)實(shí)現(xiàn)了一個(gè)另存為對(duì)話框,并且獲取了文件的路徑,然后使用文件路徑來(lái)保存文件。下面是saveFile()函數(shù)的定義: bool?MainWindow::saveFile(const QString &fileName) { ? ?QFile?file(fileName); ? ? ? ?if?(!file.open(QFile::WriteOnly?|?QFile::Text))?{ ? ?? ?? ? ?? ??//?%1和%2分別對(duì)應(yīng)后面arg兩個(gè)參數(shù),/n起換行的作用 ? ?? ??QMessageBox::warning(this, tr("多文檔編輯器"), ? ?? ?? ?? ?? ?? ??tr("無(wú)法寫(xiě)入文件?%1:/n?%2") ? ?? ?? ?? ?? ?? ?.arg(fileName).arg(file.errorString())); ? ?? ??return?false; ? ?} ? ?QTextStream?out(&file); ? ?//?鼠標(biāo)指針變?yōu)榈却隣顟B(tài) ? ?QApplication::setOverrideCursor(Qt::WaitCursor); ? ?out?<<?ui->textEdit->toPlainText(); ? ?//?鼠標(biāo)指針恢復(fù)原來(lái)的狀態(tài) ? ?QApplication::restoreOverrideCursor(); ? ?isUntitled?=?false; ? ?//?獲得文件的標(biāo)準(zhǔn)路徑 ? ?curFile?=?QFileInfo(fileName).canonicalFilePath(); ? ?setWindowTitle(curFile); ? ?return?true; } 該函數(shù)執(zhí)行真正的文件保存操作。先是使用一個(gè)QFile類對(duì)象來(lái)指向要保存的文件,然后將其使用寫(xiě)入方式打開(kāi)。打開(kāi)后再使用QTextStream文本流將編輯器中的內(nèi)容寫(xiě)入到文件中。 這里使用了很多新的類,以后我們對(duì)自己不明白的類都可以去幫助里進(jìn)行查找,這也許是我們以后要做的最多的一件事了。對(duì)于其中的英文解釋,我們最好想辦法弄明白它的大意,其實(shí)網(wǎng)上也有一些中文的翻譯,但最好還是從一開(kāi)始就嘗試著看英文原版的幫助,這樣以后才不會(huì)對(duì)中文翻譯產(chǎn)生依賴。
?
現(xiàn)在運(yùn)行程序,已經(jīng)能夠?qū)崿F(xiàn)新建文件,保存文件,文件另存為的功能了。
?
先到mainwindow.h文件中添加public函數(shù)聲明: bool?loadFile(const QString &fileName); //?加載文件?
然后到mainwindow.cpp文件中添加該函數(shù)的定義: bool?MainWindow::loadFile(const QString &fileName) { ? ?QFile?file(fileName);?//?新建QFile對(duì)象 ? ?if?(!file.open(QFile::ReadOnly?|?QFile::Text))?{ ? ?? ??QMessageBox::warning(this, tr("多文檔編輯器"), ? ?? ?? ?? ?? ?? ?? ?? ?? ???tr("無(wú)法讀取文件?%1:\n%2.") ? ?? ?? ?? ?? ?? ?? ?? ?? ???.arg(fileName).arg(file.errorString())); ? ?? ??return?false;?//?只讀方式打開(kāi)文件,出錯(cuò)則提示,并返回false ? ?} ? ?QTextStream?in(&file);?//?新建文本流對(duì)象 QApplication::setOverrideCursor(Qt::WaitCursor);? // 讀取文件的全部文本內(nèi)容,并添加到編輯器中 ui->textEdit->setPlainText(in.readAll());? ?? ?QApplication::restoreOverrideCursor();?
? ?//?設(shè)置當(dāng)前文件 ? ?curFile?=?QFileInfo(fileName).canonicalFilePath(); ? ?setWindowTitle(curFile); ? ?return?true; }? ??? 這里的操作和saveFile()函數(shù)是相似的。下面到設(shè)計(jì)模式,分別進(jìn)入其他幾個(gè)動(dòng)作的觸發(fā)信號(hào)的槽,更改如下: //?打開(kāi)動(dòng)作 void?MainWindow::on_action_Open_triggered() { ? ?if?(maybeSave()) { ? ?? ?? ? ?? ??QString?fileName?=?QFileDialog::getOpenFileName(this); ? ?? ?? ? ?? ??//?如果文件名不為空,則加載文件 ? ?? ??if?(!fileName.isEmpty()) { ? ?? ?? ?? ?loadFile(fileName); ? ?? ?? ?? ?ui->textEdit->setVisible(true); ? ?? ??} ? ?} } //?關(guān)閉動(dòng)作 void?MainWindow::on_action_Close_triggered() { ? ?if?(maybeSave()) { ? ?? ??ui->textEdit->setVisible(false); ? ?} } //?退出動(dòng)作 void?MainWindow::on_action_Exit_triggered() { ? ?//?先執(zhí)行關(guān)閉操作,再退出程序 ? ?//?qApp是指向應(yīng)用程序的全局指針 ? ?on_action_Close_triggered(); ? ?qApp->quit(); } //?撤銷動(dòng)作 void?MainWindow::on_action_Undo_triggered() { ? ?ui->textEdit->undo(); } //?剪切動(dòng)作 void?MainWindow::on_action_Cut_triggered() { ? ?ui->textEdit->cut(); } //?復(fù)制動(dòng)作 void?MainWindow::on_action_Copy_triggered() { ? ?ui->textEdit->copy(); } //?粘貼動(dòng)作 void?MainWindow::on_action_Paste_triggered() { ? ?ui->textEdit->paste(); } 這里可以看到,復(fù)制、粘貼等常用功能是QTextEdit已經(jīng)實(shí)現(xiàn)的,我們只需要調(diào)用相應(yīng)的函數(shù)。雖然實(shí)現(xiàn)了退出功能,但是,有時(shí)候會(huì)使用窗口標(biāo)題欄的關(guān)閉按鈕來(lái)關(guān)閉程序,這里我們需要使用關(guān)閉事件處理函數(shù)來(lái)實(shí)現(xiàn)相應(yīng)的功能。 下面到mainwindow.h文件中,先添加頭文件包含#include?<QCloseEvent>,然后添加函數(shù)聲明: protected: ? ??void?closeEvent(QCloseEvent?*event); //?關(guān)閉事件?
然后到mainwindow.cpp文件中添加該函數(shù)的定義: void?MainWindow::closeEvent(QCloseEvent?*event) { ? ?//?如果maybeSave()函數(shù)返回true,則關(guān)閉程序 ? ?if?(maybeSave()) {? ? ?? ??event->accept(); ? ?}?else?{? ?//?否則忽略該事件 ? ?? ??event->ignore(); ? ?} } 關(guān)于事件的概念,會(huì)在后面的教程中講解。
? ?? ?這一篇中實(shí)現(xiàn)了最基本的編輯功能,現(xiàn)在還剩下查找和幫助菜單沒(méi)有實(shí)現(xiàn),這個(gè)會(huì)在下一篇進(jìn)行介紹。如果大家想學(xué)習(xí)一個(gè)更完整的文本編輯器的實(shí)現(xiàn),可以參考《Qt及QtQuick開(kāi)發(fā)實(shí)戰(zhàn)精解》一書(shū)的第一章
轉(zhuǎn)載于:https://www.cnblogs.com/xuaidongstdudyrecording/p/6211641.html
總結(jié)
- 上一篇: 手把手教你用.NET Core写爬虫
- 下一篇: 6.控制器