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