今天開始呢,我們就開始用Qt做兩個比較實用的東西,這一篇我們主要探究下文本編輯器的實現。
首先我們來看下我們的大致框架:
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); protected: void closeEvent(QCloseEvent *event);
對於所有定義的信號和槽的類,在類定義開始處的O_OBJECT宏都是必需的。
private slots: void newFile(); void open(); bool save(); bool saveAs(); void about(); void documentWasModified();
私有槽中包含了創建新文件、打開文件、保存文件以及about。當然了我們還有一個在程序中最重要的函數documentWasModified(),實現的共ing功能是判斷是否文件被修改。
private: void createActions(); void createMenus(); void createToolBars(); void createStatusBar(); void readSettings(); void writeSettings(); bool maybeSave(); void loadFile(const QString &fileName); bool saveFile(const QString &fileName); void setCurrentFile(const QString &fileName); QString strippedName(const QString &fullFileName); QTextEdit *textEdit; QString curFile; QMenu *fileMenu; QMenu *editMenu; QMenu *formMenu; QMenu *helpMenu; QToolBar *fileToolBar; QToolBar *editToolBar; QAction *newAct; QAction *openAct; QAction *saveAct; QAction *saveAsAct; QAction *exitAct; QAction *automaticAct; QAction *typefaceAct; QAction *cutAct; QAction *copyAct; QAction *pasteAct; QAction *aboutAct; QAction *aboutQtAct; };
在這裡面定義了在程序中用到的所有類的實例,createActions();createMenus(); createToolBars();createStatusBar();用於創建用戶接口。readSetting()用於恢復用戶以前的設置。下面我們就來一一看看具體實現:
MainWindow::MainWindow() { textEdit = new QTextEdit; setCentralWidget(textEdit); createActions(); createMenus(); createToolBars(); createStatusBar(); readSettings(); connect(textEdit->document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified)); setCurrentFile(""); }
我們的構造函數首先創建一個文本框實例,而後設置中心窗體,再者調用用戶接口即可完成。
void MainWindow::closeEvent(QCloseEvent *event) { if(maybeSave()) { writeSettings(); event->accept(); } else { event->ignore(); } }
closeEvent()函數實現功能:在用戶嘗試退出時警告用戶關於未保存的修改信息。
void MainWindow::newFile() { if(maybeSave()) { textEdit->clear(); setCurrentFile(""); } }
newFile函數實現功能:首先判斷當前文件是否已保存,如果未保存先保存而後創建新文件。
void MainWindow::open() { if(maybeSave()) { QString fileName = QFileDialog::getOpenFileName(this); if(!fileName.isEmpty()) loadFile(fileName); } }
open()函數實現功能:首先判斷當前文件是否已保存,如果未保存則先保存,而後通過QFileDialog的靜態函數getOpenFileName()獲取文件目錄,打開。
bool MainWindow::save() { if(curFile.isEmpty()) { return saveAs(); } else { return saveFile(curFile); } } bool MainWindow::saveAs() { QString fileName = QFileDialog::getSaveFileName(this); if(fileName.isEmpty()) return false; return saveFile(fileName); }
save() slot在用戶點擊File|Save菜單項時被調用。如果用戶還沒為文件提供一個名字,則調用saveAs(),否則調用saveFile()來保存文件。
void MainWindow::about() { QMessageBox::about(this, tr("About Application"), tr("The <b>Application</b> example created by <b>Yzs</b> ")); }
about()函數對話框通過QMessageBox::about()靜態函數實現
void MainWindow::documentWasModified() { setWindowModified(textEdit->document()->isModified()); }
documentWasModified() slot在QTextEdit中的文本被改變時被調用。我們調用QWidget::setWindowModified()來是標題欄顯示文件已被修改(顯示個*號)。
void MainWindow::createActions() { newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this); newAct->setShortcut(tr("Ctrl+N")); newAct->setStatusTip(tr("Create a new file")); connect(newAct, SIGNAL(triggered()), this, SLOT(newFile())); openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this); openAct->setShortcut(tr("Ctrl+O")); openAct->setStatusTip(tr("Open an existing file")); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); saveAct = new QAction(QIcon(":/images/save.png"), tr("&Save"), this); saveAct->setShortcut(tr("Ctrl+S")); saveAct->setStatusTip(tr("Save a file")); connect(saveAct, SIGNAL(triggered()), this, SLOT(save())); saveAsAct = new QAction(tr("Save &As..."), this); saveAsAct->setStatusTip(tr("Save the file under a new name")); connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcut(tr("Ctrl+Q")); exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); automaticAct = new QAction(tr("&Automatic"), this); automaticAct->setChecked(false); automaticAct->setStatusTip(tr("Automatic the file")); connect(automaticAct, SIGNAL(triggered()), this, SLOT(automatic())); typefaceAct = new QAction(tr("&Typeface"), this); typefaceAct->setStatusTip(tr("typefaceAct")); connect(typefaceAct, SIGNAL(triggered()), this, SLOT(typeface())); cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this); cutAct->setShortcut(tr("Ctrl+X")); cutAct->setStatusTip(tr("Cut the current selection's contents to the clipboard")); connect(cutAct, SIGNAL(triggered()), this, SLOT(cut())); copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Copy"), this); copyAct->setShortcut(tr("Ctrl+C")); copyAct->setStatusTip(tr("Copy the current selection's contents to clipboard")); connect(copyAct, SIGNAL(triggered()), this, SLOT(copy())); pasteAct = new QAction(QIcon(":/images/paste.png"), tr("&Paste"), this); pasteAct->setShortcut(tr("Ctrl+V")); pasteAct->setStatusTip(tr("Paste the current selection's contents to clipboard")); connect(pasteAct, SIGNAL(triggered()), this, SLOT(paste())); aboutAct = new QAction(tr("&About"), this); aboutAct->setStatusTip(tr("Show the application's About box")); connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); aboutQtAct = new QAction(tr("About &Qt"), this); aboutQtAct->setStatusTip(tr("Show the Qt library's About box")); connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); cutAct->setEnabled(false); copyAct->setEnabled(false); connect(textEdit, SIGNAL(copyAvailable(bool)), cutAct, SLOT(setEnabled(bool))); connect(textEdit, SIGNAL(copyAvailable(bool)), copyAct, SLOT(setEnabled(bool))); }
QAction是一個代表用戶行為的對象,例如,保存文件或彈出對話框。一個action可以被放入QMenu或QToolBar中,也可以被放入其它重載了QWidget::actionEvent()的widget中。一個action有一個用於描述它作用的文本,當用戶觸發這個action時,它發出triggered()信號。我們將這個信號連接到一個slot上以實現真正的功能。Edit|Cut和Edit|Copy action必須在QTextEdit包含已選擇的文本時才有效。在默認情況下我們將它們禁用並將QTextEdit::copyAvailable()信號連接到QAction::setEnabled() slot上,以確保在文本編輯器中沒有選擇文本時著兩個行為無效。
本文出自 “驿落黃昏” 博客,請務必保留此出處http://yiluohuanghun.blog.51cto.com/3407300/959827