范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Qt开发NotePad实例开发

  一、界面开发
  NotePad使用主窗口作为顶层窗口组件,使用QMainWindow作为基类,QMainWindow内部封装了菜单栏、工具栏、中央组件、停靠组件、状态栏等。QMainWindow内置了布局管理器,基本的组件布局如下:
  使用二阶构造模式构建NotePad界面。MainWindow::MainWindow() { resize(800, 600); }  MainWindow::~MainWindow() {  }  MainWindow* MainWindow::newInstance() { MainWindow* ret = new MainWindow(); if((ret == NULL) || (!ret->construct())) { delete ret; ret = NULL; } return ret; }  bool MainWindow::construct() { bool ret = true; ret = ret && initMenuBar();//菜单栏构建 ret = ret && initToolBar();//工具栏构建 ret = ret && initStatusBar();//状态栏构建 ret = ret && initMainEditor();//中央组件构建  return ret; }
  1、菜单栏
  QT中提供了预定义的与菜单相关的类组件,菜单栏QMenuBar,下拉菜单QMenu,菜单项QAction。    QMenuBar* mb = menuBar();     QMenu* menu = new QMenu("File(&F)");     QAction *action = new QAction(text, NULL);     menu->addAction(action);     mb->addMenu(menu);
  快捷键设置
  action->setShortcut(QKeySequence(KEY));
  QKeySequence是QT中与快捷键相关的类,KEY是QT中代表键值的常量。
  NotePad菜单栏共有文件、编辑、格式、查看、帮助五组下拉菜单,每组下拉菜单使用一个函数构建。bool MainWindow::initMenuBar() { bool ret = true; QMenuBar *mb = menuBar(); ret = ret && initFileMenu(mb); ret = ret && initEditMenu(mb); ret = ret && initFormatMenu(mb); ret = ret && initViewMenu(mb); ret = ret && initHelpMenu(mb); return ret; }  bool MainWindow::initFileMenu(QMenuBar *mb) { QMenu *menu = new QMenu("File(&F)"); bool ret = (menu != NULL); if(ret) { QAction *action = NULL; ret = ret && makeAction(action, "New(&N)", Qt::CTRL + Qt::Key_N); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Open(&O)", Qt::CTRL + Qt::Key_O); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Save(&S)", Qt::CTRL + Qt::Key_S); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Save As(&A)", 0); if(ret) { menu->addAction(action); } menu->addSeparator();  ret = ret && makeAction(action, "Page Setting(&U)", 0); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Print(&P)", Qt::CTRL + Qt::Key_P); if(ret) { menu->addAction(action); } menu->addSeparator();  ret = ret && makeAction(action, "Exit(&X)", 0); if(ret) { menu->addAction(action); } }  if(ret) { mb->addMenu(menu); } else { delete menu; } return ret; }  bool MainWindow::makeAction(QAction *&action, QString text, int key) { bool ret = true; action = new QAction(text, NULL); if(action != NULL) { action->setShortcut(QKeySequence(key)); } else { ret = false; } return ret; }  bool MainWindow::initEditMenu(QMenuBar *mb) { QMenu *menu = new QMenu("Edit(&E)", NULL); bool ret = (menu != NULL); if(ret) { QAction *action = NULL; ret = ret && makeAction(action, "Undo(&U)", Qt::CTRL + Qt::Key_Z); if(ret) { menu->addAction(action); } menu->addSeparator();  ret = ret && makeAction(action, "Cut(&T)", Qt::CTRL + Qt::Key_X); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Copy(&C)", Qt::CTRL + Qt::Key_C); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Paste(&P)", Qt::CTRL + Qt::Key_V); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Delete(&L)", Qt::Key_Delete); if(ret) { menu->addAction(action); } menu->addSeparator();  ret = ret && makeAction(action, "Find(&F)", Qt::CTRL + Qt::Key_F); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Find Next(&N)", Qt::Key_F3); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Replace(&R)", Qt::CTRL + Qt::Key_H); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Goto(&G)", Qt::CTRL + Qt::Key_G); if(ret) { menu->addAction(action); } menu->addSeparator();  ret = ret && makeAction(action, "All(&A)", Qt::CTRL + Qt::Key_A); if(ret) { menu->addAction(action); }  ret = ret && makeAction(action, "Time/Date(&D)", Qt::Key_F5); if(ret) { menu->addAction(action); } } if(ret) { mb->addMenu(menu); } else { delete menu; } return ret; }  bool MainWindow::initFormatMenu(QMenuBar *mb) { QMenu *menu = new QMenu("Format(&O)", NULL); bool ret = (menu != NULL); if(ret) { QAction *action = NULL; ret = ret && makeAction(action, "Auto Wrap(&W)", 0); if(ret) { menu->addAction(action); } menu->addSeparator();  ret = ret && makeAction(action, "Font(&F)", 0); if(ret) { menu->addAction(action); } } if(ret) { mb->addMenu(menu); } else { delete menu; } return ret; }  bool MainWindow::initViewMenu(QMenuBar *mb) { QMenu *menu = new QMenu("View(&V)", NULL); bool ret = (menu != NULL); if(ret) { QAction *action = NULL; ret = ret && makeAction(action, "Status(&S)", 0); if(ret) { menu->addAction(action); } } if(ret) { mb->addMenu(menu); } else { delete menu; } return ret; }  bool MainWindow::initHelpMenu(QMenuBar *mb) { QMenu *menu = new QMenu("Help(&H)", NULL); bool ret = (menu != NULL); if(ret) { QAction *action = NULL; ret = ret && makeAction(action, "Help(&H)", 0); if(ret) { menu->addAction(action); } menu->addSeparator();  ret = ret && makeAction(action, "About NotePad(&A)", 0); if(ret) { menu->addAction(action); } } if(ret) { mb->addMenu(menu); } else { delete menu; } return ret; }
  2、工具栏
  工具栏是应用程序中集成各种功能使用快捷方式的区域,不是应用程序必须存在的组件,工具栏的元素可以是各种窗口组件,但通常以图标按钮的方式存在。
  QT中提供了预定义的工具栏相关组件,工具栏QToolBar和快捷项QAction。    //创建工具栏     QToolBar *tb = addToolBar("ToolBar");         //创建工具栏选项         QAction *action = new QAction("", NULL);     action->setToolTip("Open");     action->setIcon(QIcon("/res/pic/open.png"));         //将工具栏选项加入工具栏     tb->addAction(action);     void setFloatable(bool floatable)设置工具栏为浮动     void setMovable(bool movable)设置工具栏为可移动     void setIconSize(const QSize & iconSize)设置工具栏的图标大小     QTollBar组件中可以加入QT中的任意QWidget组件。     将菜单栏中的主要常用功能添加到工具栏中,按照功能所属的菜单栏进行分组创建。 bool MainWindow::initToolBar() { bool ret = true; QToolBar *tb = addToolBar("ToolBar"); tb->setMovable(false); tb->setIconSize(QSize(16, 16)); ret = ret && initFileToolItem(tb);//创建文件菜单栏的功能到工具栏 ret = ret && initEditToolItem(tb);//创建编辑菜单栏到工具栏 ret = ret && initFormatToolItem(tb);//创建格式菜单栏到工具栏 ret = ret && initViewToolItem(tb);//创建查看菜单栏到工具栏  return ret;  } bool MainWindow::initFileToolItem(QToolBar *tb) { bool ret = true; QAction *action = NULL; ret = ret && makeAction(action, "New", ":/res/pic/new.png");  if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Open", ":/res/pic/open.png"); if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Save", ":/res/pic/save.png"); if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "SaveAs", ":/res/pic/saveas.png"); if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Print", ":/res/pic/print.png"); if( ret ) { tb->addAction(action); } tb->addSeparator(); return ret; }  bool MainWindow::initEditToolItem(QToolBar* tb) { bool ret = true; QAction *action = NULL; ret = ret && makeAction(action, "Undo", ":/res/pic/undo.png");  if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Redo", ":/res/pic/redo.png");  if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Cut", ":/res/pic/cut.png"); if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Copy", ":/res/pic/copy.png"); if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Paste", ":/res/pic/paste.png"); if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Find", ":/res/pic/find.png"); if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Replace", ":/res/pic/replace.png"); if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Goto", ":/res/pic/goto.png"); if( ret ) { tb->addAction(action); } tb->addSeparator(); return ret; }  bool MainWindow::initFormatToolItem(QToolBar* tb) { bool ret = true; QAction *action = NULL; ret = ret && makeAction(action, "Auto Wrap", ":/res/pic/wrap.png"); if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Font", ":/res/pic/font.png"); if( ret ) { tb->addAction(action); } tb->addSeparator(); return ret; }  bool MainWindow::initViewToolItem(QToolBar* tb) { bool ret = true; QAction *action = NULL; ret = ret && makeAction(action, "ToolBar", ":/res/pic/tool.png");  if( ret ) { tb->addAction(action); }  ret = ret && makeAction(action, "Status", ":/res/pic/status.png");  if( ret ) { tb->addAction(action); } return ret; }  bool MainWindow::makeAction(QAction*& action, QString tip, QString icon) { bool ret = true;  action = new QAction("", NULL);  if( action != NULL ) { action->setToolTip(tip); action->setIcon(QIcon(icon)); } else { ret = false; }  return ret; }
  3、状态栏
  状态栏是应用程序中输出简要信息的区域,一般位于窗口的底部。状态栏显示的消息类型如下:
  A、实时消息,如当前程序状态
  B、永久消息,如程序版本,开发机构
  C、进度消息,进度显示
  QT中提供了预定义的状态栏相关组件状态栏QStatusBar,QStatusBar是容器型组件,可以是任意组件QWidget的父组件。
  QT状态栏的一般设计原则:
  A、状态栏左边区域用于输出实时消息
  B、状态栏右边区域用于输出永久消息
  因此,addWidget函数用于在状态栏左边区域添加组件,addPermanentWidget函数用于在状态栏右边区域添加组件。bool MainWindow::initStatusBar() { bool ret = true; QStatusBar *sb = statusBar(); QLabel *label = new QLabel("CopyRight @Scorpio Studio"); if(label != NULL) { label->setMinimumWidth(150); label->setAlignment(Qt::AlignCenter); sb->addPermanentWidget(label); } else { ret = false; } return ret; }
  4、中央组件
  中央组件是多行文本编组件,使用QPlainTextEdit组件。bool MainWindow::initMainEditor() { bool ret = true; //设置mainEditor的父组件 mainEditor.setParent(this); //设置中央组件为mainEditor setCentralWidget(&mainEditor); //设置mainEditor的背景色为豆沙绿 QPalette p = mainEditor.palette(); p.setColor(QPalette::Base, QColor(204, 232, 207)); mainEditor.setPalette(p); return ret; }
  二、核心功能开发
  1、信号与槽函数
  考虑到用户界面与业务逻辑代码的分离,槽函数实现需要与界面实现向分离,槽函数在新建MainwWindowSlots.cpp文件中实现,界面文件名称改为MainWindowUI.cpp。
  菜单栏与工具栏中的QAction对象在鼠标点击后会发送triggered()信号,通过信号与槽机制可以实现对QAction对象的操作的处理。
  connect(action, SIGNAL(triggered()), this, SLOT(slotfunction));
  在QAction对象创建的时候连接信号与槽函数。
  2、文件的存取操作
  创建文件对话框:QString MainWindow::createFileDialog(QFileDialog::AcceptMode mode, QString title) { QString ret = ""; QFileDialog filedialog(this); QStringList filter; filter.append("Text Files (*.txt)"); filter.append("All Files (*.*)"); filedialog.setWindowTitle(title); filedialog.setAcceptMode(mode); filedialog.setNameFilters(filter); if(mode == QFileDialog::AcceptOpen) { filedialog.setFileMode(QFileDialog::ExistingFile); } if(filedialog.exec() == QFileDialog::Accepted) { ret = filedialog.selectedFiles()[0]; } return ret; }
  错误消息提示框:void MainWindow::showErrorMessage(const QString& title, const QString & text, QMessageBox::StandardButtons buttons) { QMessageBox::critical(this, title, text, buttons); }
  打开文件:void MainWindow::onFileOpen() { QString path = createFileDialog(QFileDialog::AcceptOpen, "Open"); if(path != "") { QFile file(path); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { mainEditor.setPlainText(QString(file.readAll())); file.close(); m_filepath = path; setWindowTitle("NotePad - [" + m_filepath + "]"); } else { showErrorMessage(QString("Error"), QString("Open file error: " + m_filepath), QMessageBox::Ok); } } }
  保存文件:void MainWindow::onFileSave() { if(m_filepath == "") { m_filepath = createFileDialog(QFileDialog::AcceptSave, "Save"); } if(m_filepath != "") { QFile file(m_filepath); if(file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out << mainEditor.toPlainText(); file.close(); setWindowTitle("NotePad - [ " + m_filepath + " ]"); } else { showErrorMessage(QString("Error"), QString("Save file error: " + m_filepath), QMessageBox::Ok); m_filepath = ""; } } }
  另存文件:void MainWindow::onFileSaveAs() { QString path = createFileDialog(QFileDialog::AcceptSave, "Save As"); if(path != "") { QFile file(path); if(file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out << mainEditor.toPlainText(); file.close(); m_filepath = path; setWindowTitle("NotePad - [ " + m_filepath + " ]"); } else { showErrorMessage(QString("Error"), QString("Save as error: " + m_filepath), QMessageBox::Ok); } } }
  创建新文件:void MainWindow::onFileNew() { preTextChanged(); if(!m_isTextChanged) { mainEditor.clear(); setWindowTitle("NotePad - [New ]"); m_filepath = ""; m_isTextChanged = false; } }
  3、编辑区的数据交互    QPlainTextEdit编辑器组件提供了编辑交互功能接口。     QPlainTextEdit内置的信号如下:     void textChanged()     void copyAvailable(bool yes)     void redoAvailable(bool available)     void undoAvailable(bool available)     void cursorPositionChanged()         void modificationChanged(bool changed)     QPlainTextEdit内置的槽函数如下:     void copy()     void cut()     void paste()     void redo()     void selectAll()     void undo()
  将菜单栏、工具栏中的copy、cut、paste、redo、undo等编辑操作QAction对象的triggered()信号连接到QPlainTextEdit对象的相应操作的槽函数,即可实现编辑操作。    connect(action, SIGNAL(triggered(bool)), &mainEditor, SLOT(undo());     connect(action, SIGNAL(triggered()), &mainEditor, SLOT(cut()));     connect(action, SIGNAL(triggered()), &mainEditor, SLOT(copy()));     connect(action, SIGNAL(triggered()), &mainEditor, SLOT(paste());
  工具栏QAction对象的界面状态的设置
  在创建Copy、Undo、Redo的QAction对象时设置为不可用状态。
  将QPlainTextEdit对象的copyAvailable、undoAvailable、redoAvailable信号连接到自定义槽函数。   connect(&mainEditor, SIGNAL(copyAvailable(bool)), this, SLOT(onCopyAvailable(bool)));    connect(&mainEditor, SIGNAL(undoAvailable(bool)), this, SLOT(onUndoAvailable(bool)));    connect(&mainEditor, SIGNAL(redoAvailable(bool)), this, SLOT(onRedoAvailable(bool)));
  在自定义槽函数中根据信号的参数available设置QAction对象的状态void MainWindow::onCopyAvailable(bool available) { findMenuBarItem("Copy")->setEnabled(available); findMenuBarItem("Cut")->setEnabled(available); findToolBarItem("Copy")->setEnabled(available); findToolBarItem("Cut")->setEnabled(available); }  void MainWindow::onUndoAvailable(bool available) { findMenuBarItem("Undo")->setEnabled(available); findToolBarItem("Undo")->setEnabled(available); }  void MainWindow::onRedoAvailable(bool available) { findToolBarItem("Redo")->setEnabled(available); }
  4、拖放支持
  拖放一个文件进入窗口时将触发拖放事件,QWidget对象都能处理拖放事件。
  设置窗口支持拖放事件:
  在构造函数调用setAcceptDrops(true);
  重写拖放事件的处理函数:
  void dragEnterEvent(QDragEnterEvent *event);
  void dropEvent(QDropEvent *event);
  默认情况下,QPlainTextEdit接受来自其他应用程序拖拽来的文本,把文件名显示出来。由于DropEvent是由子组件向父组件传播的,通过禁止QPlainTextEdit的DropEvent,主窗口可以获取DropEvent,MainWindow中就可以处理DropEvent。
  在MainWwindow构造函数中需要禁止QPlainTextEdit接受DropEvent,允许MainWindow接受DropEvent。
  mainEditor.setAcceptDrops(false);
  setAcceptDrops(true);
  重写事件处理函数:void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if(event->mimeData()->hasFormat("text/uri-list")) { event->acceptProposedAction(); } else { event->ignore(); } }  void MainWindow::dropEvent(QDropEvent *event) { if(event->mimeData()->hasUrls()) { QList list = event->mimeData()->urls(); QString path = list[0].toLocalFile(); QFileInfo fi(path);  if( fi.isFile() ) { preTextChanged();  if(!m_isTextChanged) { loadFile(path); } } else { showMessage(this, QMessageBox::Critical, "Error", "Open file error", QMessageBox::Ok); } } else { event->ignore(); } }
  5、打印支持
  QTextDocument是表示文本及文本属性的数据类。可以设置文本属性如:排版、字体、标题;获取文本参数如:行数、文本宽度、文本信息;实现标准操作如:撤销、重做、查找、打印。
  打印功能实现如下:
  A、连接打印功能的QAction对象到打印功能槽函数
  B、在打印槽函数中定义打印对话框
  C、根据用户选择获取QPrinter对象
  D、使用QTextDocument对象进行打印void MainWindow::onPrint() { QPrintDialog printdialog(this); printdialog.setWindowTitle("Print"); if(printdialog.exec() == QPrintDialog::Accepted) { QPrinter *printer = printdialog.printer(); mainEditor.document()->print(printer); } }
  6、光标定位
  QPlainTextEdit编辑框内部包含QTextCursor对象。    [signal] void QPlainTextEdit::cursorPositionChanged()     QTextCursor QPlainTextEdit::textCursor() const     int QTextCursor::position() const   void MainWindow::onCursorChanged() { int pos = mainEditor.textCursor().position(); QString text = mainEditor.toPlainText(); int colum = 0; int row = 0; int flag = -1; for(int i = 0; i < pos; i++) { if( text[i] == " " ) { row++; flag = i; } } flag++; colum = pos - flag; m_status.setText("Line: " + QString::number(row + 1) + " Colum: " + QString::number(colum + 1)); }
  7、查找功能
  1)查找对话框的功能:
  A、可复用的组件
  B、查找文本框中的指定字符串
  C、能够指定查找方向
  D、支持大小写敏感查找
  (2)查找对话框架构设计如下:
  (3)查找对话框的界面布局:
  4)查找功能的实现:
  A、获取当前光标的位置作为起始点
  B、查找目标第一次出现的位置
  C、通过目标位置和目标长度在文本框内进行标记
  QString类提供了字符串中查找子串的函数:
  int QString::indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
  从指定位置向后查找子串的下标位置
  int QString::lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
  从指定位置向前查找子串的下标位置
  QPlainTextEdit文本框中选中子串的标记
  QTextCursor cursor = m_textedit->textCursor();//获取当前光标
  cursor.setPosition(index);//设置光标到下标index
  cursor.setPosition(index + target.length(), QTextCursor::KeepAnchor);//设置文本选择范围
  m_textedit->setTextCursor(cursor);//设置光标信息到文本
  (5)FindDailog类与MainWindow类的弱耦合关系
  通过setPlainTextEdit(pText)设置FindDailog查找对话框指向的文本框,确立了FindDailog类与MainWindow类的弱耦合关系。
  8、调色板设置 //设置mainEditor的背景色为豆沙绿     QPalette p = mainEditor.palette();     p.setColor(QPalette::Base, QColor(204, 232, 207));     p.setColor(QPalette::Inactive, QPalette::Highlight, p.color(QPalette::Active, QPalette::Highlight));     p.setColor(QPalette::Inactive, QPalette::HighlightedText, p.color(QPalette::Active, QPalette::HighlightedText));     mainEditor.setPalette(p);
  9、替换功能
  替换对话框的功能:
  A、可复用的组件
  B、查找文本框中的字符串
  C、替换当前查找到的字符串
  D、替换所有的字符串
  E、点击关闭按钮后隐藏
  替换对话框的架构设计:
  考虑到FindDialog类代码复用,RepalceDialog类继承自FindDialog。
  替换对话框界面设计:
  m_replacelabel.setText("Replace To:"); m_replacebutton.setText("Replace"); m_replaceallbutton.setText("Replace All");  m_layout.removeWidget(&m_check); m_layout.removeWidget(&m_radiogroup); m_layout.removeWidget(&m_cancelbutton);  m_layout.addWidget(&m_replacelabel, 1, 0); m_layout.addWidget(&m_replaceedit, 1, 1); m_layout.addWidget(&m_replacebutton, 1, 2);  m_layout.addWidget(&m_check, 2, 0); m_layout.addWidget(&m_radiogroup, 2, 1); m_layout.addWidget(&m_replaceallbutton, 2, 2);  m_layout.addWidget(&m_cancelbutton, 3, 2);
  替换功能的实现:
  要实现替换操作,首先需要查找文本框中是否存在的字符串。如果存在字符串,则将鼠标标记的字符串替换。void ReplaceDialog::onReplace() { QString target = m_edit.text(); QString to = m_replaceedit.text(); if((m_textedit != NULL) && (target != NULL) && (to != NULL)) { QString select = m_textedit->textCursor().selectedText(); if(select == target) { m_textedit->insertPlainText(to); } onFind(); } }  void ReplaceDialog::onRepalceAll() { QString target = m_edit.text(); QString to = m_replaceedit.text(); if((m_textedit != NULL) && (target != NULL) && (to != NULL)) { QString text = m_textedit->toPlainText(); text.replace(target, to, m_check.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive); m_textedit->clear(); m_textedit->insertPlainText(text); } }
  10、工具栏、状态栏的显示隐藏
  在构建菜单栏、工具栏中ToolBar、StatusBar的QAction对象时,设置QAction对象的属性。        action->setCheckable(true);         action->setChecked(true);         connect(action, SIGNAL(triggered()), this, SLOT(onViewToolBar()));
  槽函数如下:void MainWindow::onViewStatusBar() { QStatusBar *sb = statusBar(); bool visible = sb->isVisible(); sb->setVisible(!visible); findToolBarItem("Status Bar")->setChecked(!visible); findMenuBarItem("Status Bar")->setChecked(!visible); }  void MainWindow::onViewToolBar() { const QObjectList& list = children(); for(int i = 0; i < list.count(); i++) { QToolBar *tb = dynamic_cast(list[i]); if(tb != NULL) { bool visible = tb->isVisible(); tb->setVisible(!visible); findMenuBarItem("Tool Bar")->setChecked(!visible); findToolBarItem("Tool Bar")->setChecked(!visible); break; } } }
  11、关于对话框
  关于对话框用于标识软件的信息,如:Logo、版本号、开发者信息、版权、联系方式、项目信息等。
  经典的关于对话框界面设计:AboutDialog::AboutDialog(QWidget* parent) :QDialog(parent, Qt::WindowCloseButtonHint), m_logo(this), m_info(this), m_close(this) { QPixmap pm(":/res/pic/dt.png"); pm = pm.scaled(120,120, Qt::KeepAspectRatio); m_logo.setPixmap(pm); m_logo.move(20, 20); m_logo.resize(120, 120);  QPalette p = m_info.palette(); p.setColor(QPalette::Active, QPalette::Base, palette().color(QPalette::Active, QPalette::Background)); p.setColor(QPalette::Inactive, QPalette::Base, palette().color(QPalette::Inactive, QPalette::Background)); m_info.setPalette(p); m_info.move(200, 30); m_info.resize(180, 130); m_info.setFrameStyle(QPlainTextEdit::NoFrame); m_info.setReadOnly(true); m_info.insertPlainText("NotePad Project  Platform: Qt 5.6.2  Version: 1.0.0  Author: Scorpio");  m_close.setText("Close"); m_close.move(273, 175); m_close.resize(100, 30);  setWindowTitle("About NotePad"); setFixedSize(395, 230); connect(&m_close, SIGNAL(clicked()), this, SLOT(onClose())); }
  12、字体设置
  设置文本框中的字体的属性。
  字体设置通过QFontDialog对话框实现
  槽函数如下:void MainWindow::onFormatFont() { bool ok = false; QFont font = QFontDialog::getFont(&ok, mainEditor.font(), this); if(ok) { mainEditor.setFont(font); } }
  13、换行
  QPlainTextEdit支持换行操作。在菜单栏、工具栏创建QAction对象时设置属性。       action->setCheckable(true);         action->setChecked(true);         connect(action, SIGNAL(triggered()), this, SLOT(onFormatWrap())); 槽函数如下: void MainWindow::onFormatWrap() { QPlainTextEdit::LineWrapMode mode = mainEditor.lineWrapMode(); if(mode == QPlainTextEdit::NoWrap) { mainEditor.setLineWrapMode(QPlainTextEdit::WidgetWidth); findMenuBarItem("Auto Wrap")->setChecked(true); findToolBarItem("Auto Wrap")->setChecked(true); } else { mainEditor.setLineWrapMode(QPlainTextEdit::NoWrap); findMenuBarItem("Auto Wrap")->setChecked(false); findToolBarItem("Auto Wrap")->setChecked(false); } }
  14、帮助文档
  QDesktopServices提供了一系列桌面开发的服务接口。
  通过QDesktopServices的成员函数打开帮助文档。
  [static] bool QDesktopServices::openUrl(const QUrl &url)
  打开网页:
  QDesktopServices::openUrl(QUrl("http://9291927.blog.51cto.com/"));
  打开文档:
  QDesktopServices::openUrl(QUrl("file:///C:/Documents and Settings/All Users/Desktop/help.pdf"));
  15、程序配置文件
  程序状态的保存可以通过在程序退出前保存程序状态参数到文件(数据库),程序启动时从配置文件读出状态参数并恢复。
  程序状态参数的存储方式:
  A、文本文件格式(XML、Json等)
  B、轻量级数据库(Access、SQLite等)
  C、二进制文件格式
  通过二进制数据流将状态参数直接存储带文件中。
  Appconfig.h文件:#ifndef APPCONFIG_H #define APPCONFIG_H  #include  #include  #include  #include  #include   class AppConfig : public QObject { Q_OBJECT public: explicit AppConfig(QObject *parent = 0); explicit AppConfig(QFont editorfont, bool isautowrap, bool istoolbarvisible, bool isstatusbarvisible, QObject *parent = 0); bool store(); QFont editorFont(); bool isAutoWrap(); bool isToolBarVisible(); bool isStatusBarVisible(); bool isValid(); private: bool restore(); private: QFont m_editorFont; bool m_isAutoWrap; bool m_isToolBarVisible; bool m_isStatusBarVisible;  bool m_isValid; }; #endif // APPCONFIG_H
  Appconfig.cpp文件:#include "AppConfig.h"  AppConfig::AppConfig(QObject *parent) : QObject(parent) { m_isValid = restore(); }  AppConfig::AppConfig(QFont editorfont, bool isautowrap, bool istoolbarvisible, bool isstatusbarvisible, QObject *parent) { m_editorFont = editorfont; m_isAutoWrap = isautowrap; m_isToolBarVisible = istoolbarvisible; m_isStatusBarVisible = isstatusbarvisible; m_isValid = true; }  QFont AppConfig::editorFont() { return m_editorFont; }  bool AppConfig::isAutoWrap() { return m_isAutoWrap; }  bool AppConfig::isStatusBarVisible() { return m_isStatusBarVisible; }  bool AppConfig::isToolBarVisible() { return m_isToolBarVisible; }  bool AppConfig::isValid() { return m_isValid; }  bool AppConfig::store() { bool ret = true; QFile file(QApplication::applicationDirPath() + "/config.dat"); if(file.open(QIODevice::WriteOnly)) { QDataStream out(&file); out.setVersion(QDataStream::Qt_5_6); out << m_editorFont; out << m_isAutoWrap; out << m_isToolBarVisible; out << m_isStatusBarVisible; file.close(); } else { ret = false; } return ret; }  bool AppConfig::restore() { bool ret = true; QFile file(QApplication::applicationDirPath() + "/config.dat"); if(file.open(QIODevice::ReadOnly)) { QDataStream in(&file); in.setVersion(QDataStream::Qt_5_6);  in >> m_editorFont; in >> m_isAutoWrap; in >> m_isToolBarVisible; in >> m_isStatusBarVisible; file.close(); } else { ret = false; } return ret; }
  从配置文件的读取状态参数恢复程序状态在构造函数中:bool MainWindow::construct() { bool ret = true;  AppConfig config;  ret = ret && initMenuBar(); ret = ret && initToolBar(); ret = ret && initStatusBar(); ret = ret && initMainEditor();  if(config.isValid()) { mainEditor.setFont(config.editorFont()); if(!config.isAutoWrap()) { mainEditor.setLineWrapMode(QPlainTextEdit::NoWrap); findToolBarItem("Auto Wrap")->setCheckable(false); findMenuBarItem("Auto Wrap")->setChecked(false); } if(!config.isToolBarVisible()) { toolBar()->setVisible(false); findMenuBarItem("Tool Bar")->setChecked(false); findToolBarItem("Tool Bar")->setChecked(false); } if(!config.isStatusBarVisible()) { statusBar()->setVisible(false); findMenuBarItem("Status Bar")->setChecked(false); findToolBarItem("Status Bar")->setChecked(false); } } return ret; }
  状态参数保存到配置文件在析构函数中:MainWindow::~MainWindow() { QFont font = mainEditor.font(); bool isautowrap = (mainEditor.lineWrapMode() == QPlainTextEdit::WidgetWidth); bool istoolbarvisible = (findMenuBarItem("Tool Bar")->isChecked() && findToolBarItem("Tool Bar")->isChecked()); bool isstatusbarvisible = (findMenuBarItem("Status Bar")->isChecked() && findToolBarItem("Status Bar")->isChecked());  AppConfig config(font, isautowrap, istoolbarvisible, isstatusbarvisible); config.store(); }
  【领QT开发教程 学习资料,点击下方链接莬费领取  ,先码住不迷路~】
  「链接」

晚安温柔清美的文案句子手持清风待明月,眉挑烟火过一生岁月不声不响,你且不慌不忙。在凡俗的烟火里,愿以素心,阅来日方长,愿晨昏相依,四季欢喜,愿你全力以赴地过,云淡风轻地活,手持清风待明月,眉挑烟火过一生。晚安灵魂的一半是学识,另一半人生,赢在和气,输在脾气古人说性躁心粗者一事无成,心和气平者百福自集。脾气,是每个人一生的修行。脾气越坏,福气越少脾气越好,福报越多。曾看过一个新闻。一个老人在公园看别人下棋,忍不住出手指点,但下棋人不听刚刚,2022年第一发成功来源学习军团解放军新闻传播中心融媒体作者解放军报记者安普忠王凌硕图频丨许春雷吕志刚王晓虎我国成功发射试验十三号卫星解放军报太原1月17日电(记者安普忠王凌硕)1月17日10时35分天地劫手游星之晶小技巧作者NGA涛涛涛涛涛弹越来越多的小伙伴武器升到70了我是升满70之后,过了小半个月才发现的武器强化,侠客实锤。分享点小技巧,如何在不氪金的情况下,去赌更高的强化。首先,了解下星之晶灵魂碎片怎么刷?暗黑325赛季暗黑3速刷碎片路线推荐作者秋仲琉璃子不语25赛季的主题为灵魂碎片,而暴雪在25赛季的蓝贴中提到了BOSS处更容易掉落灵魂碎片,本文将为你带来七大灵魂碎片在BOSS处的掉落情况,方便你轻松的获取它们就算你刀剑封魔录埋藏二十年的秘密,这才是影响宝石属性的关键刀剑封魔录真的是一款非常值得深入研究的游戏,其中的很多要素我们在研究透彻之后都会收获不少快乐。无论是宝石合成系统连段系统,还是宝石属性搭配和生日都值得深入挖掘。虽然已经发行了二十多S26赛季段位继承更新,赛季皮肤锁定黄忠机甲皮肤王者荣耀S26赛季马上就要来了,大家近期可以快速上分了,因为新赛季开启的时候会有年度限定皮肤,之前玄策的限定皮肤就非常不错,拥有两种炫酷的技能特效,那么下一款皮肤的人选备受期待,主井喷式官宣!LPL转会汇总刘青松离队,iG引进RNG中单大家好,这里是锦城,给大家带来英雄联盟电竞圈的最新资讯。在2021英雄联盟冬季转会期正式结束之后的第二天,憋气许久的LPL赛区终于是迎来了井喷式官宣,短短一个上午5支战队官宣了14王者荣耀12。14更新就在今天王者荣耀于830到9点30对全服进行了不停机更新。本次更新大小安卓约16MB,iOS约20MB。下面就是本商城更新的内容1夺宝更新积分夺宝奖池更新宫本武藏钟馗替换为诸葛亮关在你的记忆中是否有那么一条小径让你难以忘怀?在你的记忆中是否有那么一条小径让你难以忘怀?喧嚣的城市里,幽深且富有意境的丛林小径总是难得一见的绿色资源。这张照片一定会让你心动,这并不是油画,是真实存在的,是米利亚里诺自然庄园(08年中国实现奥运梦,他是申奥成功背后的英雄,患癌症仍四处奔走文通政司编辑通政司知事爸爸,我们赢了,北京赢了,中国赢了!七十八岁的霍英东听到电话那端的长子霍震霆激动地大喊着。霍英东起身冲向了人民广场,和所有人一起庆祝这一伟大的时刻。回到住处的
定了!今晚8点,天猫双11正式开启预售天猫双11真的要来了,根据消息显示,今晚8点天猫双11正式开启预售,今年又不用再熬夜了!除了预售时间的确定以外,随之而来的还有大家比较关注的双11的一些变化和优惠,今年的天猫双11iOS16。1正式版发布,史诗级更新来了经过多个测试版本,Apple今日凌晨正式向所有果粉们推送了iOSiPadOS16。1正式版,版本号20B82与RC版有所升级。iOS16。1正式版官方更新称iCloud共享照片图库WTT世界杯决赛赛程公布!孙颖莎压力增加,王楚钦成为焦点WTT世界杯决赛赛程公布!孙颖莎压力增加,王楚钦成为焦点!今天我们继续来关注国乒的最新消息,随着孙颖莎和王楚钦分别获得两个单打的冠军,澳门冠军赛已经正式的落下帷幕,但是对于国乒团队WTT世界杯总决赛将开打!地点河南新乡,25日抽签,27日打揭幕战北京时间10月25日,WTT澳门冠军赛刚刚刚刚过去不久,紧接着备受关注的WTT世界杯总决赛也要开打了,赛事有点密集,今天会进行抽签,决定具体的分组,一场乒乓球的顶级盛宴将再次火热来归化球员德尔加多,蒋光泰的个人能力不如冯潇霆,黄博文昨天与山东泰山球迷杠上了,他说,德尔加多的个人能力相当于中超外援的中等水平。如果我没有记错的话,山东泰山以前有位外援叫乌索,他的身价只有200万欧元,应该是中超外援当中的中游水平,为何五台山尼姑人数不断上涨,且多数年轻貌美,她们有何目的无论大家对佛有没有兴趣,也许都听过一首脍炙人口的诗句曾虑多情损梵行,入山又恐别倾城。世间安得两全法,不负如来不负卿。也有的就是因为这一首诗对佛产生的兴趣。对佛门生活有了向往,便想去人到中年,主动靠近你的异性,往往有这三个目的年轻时的爱情,无关家庭,无关利益,只因那份心动就义无反顾。而随着我们的成长,我们要面对现实,要承担起家庭的责任。慢慢地,爱情已不再是一场心动后的冲动,而是认定后的矢志不渝。人到中年新一波秋景上线!实测成都6大免费户外露营区野餐地,你想去哪个秋游目的地?向日葵属性的成都人有多爱户外?从上半年的新铁人三项绿道骑行龙泉山看日出露营到下半年的飞盘划艇一到周末,就忍不住要出门体验10月的成都,新一波秋景上线公园城市的美,正在各大公园绽放中哈国人问我中国怎么可能比他们更发达,是不知道哈国的资源储备吧全球之旅我在哈萨克斯坦大家好,我是申典启,一个实地走访世界各地,关注全球华人的旅行者。下图是哈萨克斯坦的第三大城市奇姆肯特,看基建水平,仿佛是一个大农村。1,女主人自己挖坑前面提到江汽集团十年砥砺奋进,探索车企高质量发展之路十年磨一剑,党的十八大以来的这十年,正是江汽集团涅槃重生的关键十年。十年来,江汽集团持续发力数字化转型国际化战略布局与开放合作等领域,在高质量发展路上不断续写着新的辉煌。发力新能源她芳华绝代,但遭好莱坞排挤,去世60年后却登美国货币10月24日,美国会上市一款全新的25美分硬币,这款硬币上出现了一位东方女性的形象,她就是第一位闯荡好莱坞的华裔演员黄柳霜。出现在新版25美分硬币上的黄柳霜,用的是她头托下巴的经典玩泥巴长大的孩子,有什么不一样?英文外刊童年的你,有没有过这样的经历每次换上干净的衣服,妈妈都会再三叮嘱不许踩水坑?每次玩得脏兮兮地回到家,就不得不面对妈妈的怒火?其实,喜欢玩泥巴是孩子的天性,而且研究发现,事实崂山区六大攻坚行动绘出旅游品质提升路线图10月24日,崂山区举行文化和旅游发展大会,打响了助力2023全省旅游发展大会,推动崂山文化和旅游高质量发展的发令枪。大会发布崂山区发布旅游品质提升三年攻坚行动实施方案,将实施旅游一年秋意浓十里桂花香如果季节有香气,那么桂花一定是秋天的专属香味。宝山区顾村公园内的桂花正开得热烈,那万点金黄藏在绿幕中,幽香而不露,秀丽而不骄,清雅高洁,恬淡超然。最佳观赏区一号门悦林大道桂花岛二号石家庄的正太饭店,入住过哪些历史人物?原创悟空杂文微信公众号石家庄的百年老建筑正太饭店,如今修缮工作即将完成,10月底即将正式对公众开放。去年,为了研究石家庄的历史文化,悟空也曾到过正太饭店去实地查看,当时正处于施工状布展进入尾声第32届菊花展要亮相了今年是菊花被定为南通市市花的第四十年,和往年有所不同,今年的菊花展将在南通植物园举办。传统菊花与植物园的自然景色交相辉映,将为大家带来别具风味的赏菊盛宴。目前,菊展的布展工作已进入大西北小城哈密,因同名水果而闻名全国,旷世风光却鲜有人知每座城市都有自己的历史文化,而城市名称不仅是一个城市的特殊标志,也承载着许多的历史渊源和文化底蕴。我国城市的命名方式多种多样,有以山川河流命名的,比如白山汉川济源等,有以方位命名的窗边随想午饭后步入窗前,暖洋洋的光线穿透玻璃,直达每个屋角,耳及之处,听到风吹树叶舞动的哗哗作响,呼吸之余,桂花香味缕缕扑鼻,目及之后,眼见的树木竟然十种之多,惭愧的是我知之甚少,正值霜降乡村微度假要聚焦微五大主题与四大模式微度假微旅游已经被正式写进十四五旅游业发展规划,文件明确提出不管是城市群规划建设,还是在城镇规划布局中,都要立足同城化一体化旅游休闲消费需求,合理推进特色旅游村镇的建设和乡村旅游的秋收有信,自驾秦岭,抵达离北方最近的南方宁陕渔湾村远近浅深,四时朝暮,风雨明晦不同。十月,大地之书迎来了秋的告白,其中一个篇章,独给了秦岭。3600米的高差配合北亚热带的季风气候,让秦岭的植物景观带呈现丰富的多样性,草甸关隘瀑布溪华为新款小折叠PoketS即将震撼发布,11月2日发布会揭晓更多惊喜对于华为P50Pocket的更新换代机型,之前在网络上就有过热议。就在10月24日官方微博就正式官宣了华为PocketS折叠屏手机,将在11月2日的华为新品全场景发布会上与大家相见表面是演员,实际是大学老师的10位明星,他们的学生占半个娱乐圈文娱情故纵编辑娱情故纵前言老师这个职业在不少人的心里,可以说都是一种非常神圣的职业,正所谓一日为师终生为父,而娱乐圈中其实也有不少的明星曾是老师。但这么多年来他们有些人却是早已忘记