界面编程之实例学习,系统记事本是个极好的参考,初学Delphi及后之c#,皆以记事本为参考,今以Qt学习,亦是如此。

期间搭建开发环境,复习c++知识,寻找模块对应功能,不一而足;现刻录其模块代码,以做助记,功能接近系统记事本之95%。

学习了Qt事件驱动之信号槽机投、窗体间数据传递方法、文件编码、本地化等功能,然而初接触,仍不能得心应手。

IDE: VS2015+Qt5.8.0

界面如下:

直贴源代码吧!完成源码包,附于文后。

1、入口程序(main.cpp):

#pragma execution_character_set("utf-8")

#include <QtWidgets/QApplication>
#include "qtranslator.h"
#include "notepad.h" int main(int argc, char *argv[])
{
QApplication a(argc, argv); //对话框类应用中文
QTranslator user;
bool ok = user.load("qt_zh_CN.qm", ".");
a.installTranslator(&user); NotePad np;
if (argc >= )
{
QString s = QString::fromLocal8Bit(argv[]);
np.loadFromFile(s);
} np.show();
return a.exec();
}

2、主模块(notepad.cpp):

#include <Windows.h>
#include <qfileinfo.h>
#include <qfile.h>
#include <qmimedata.h>
#include <qtextstream.h>
#include <qprinter.h>
#include <qprintdialog.h>
#include <qpagesetupdialog.h>
#include <qfiledialog.h>
#include <qfontdialog.h>
#include <qmessagebox.h>
#include <qtextobject.h>
#include <qdatetime.h>
#include <qsettings.h> #include "notepad.h" NotePad::NotePad(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this); //searchDialog = new SearchDialog(Q_NULLPTR, ui.textEdit);
lblStatus = new QLabel();
lblStatus->setAlignment(Qt::AlignRight);
statusBar()->addPermanentWidget(lblStatus); setActionState();
initTextEdifUI();
loadSettings();
} void NotePad::loadSettings()
{
//大小&位置
QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Notepad", QSettings::NativeFormat);
int x = settings.value("iWindowPosX", ).toInt();
int y = settings.value("iWindowPosY", ).toInt();
int w = settings.value("iWindowPosDX", ).toInt();
int h = settings.value("iWindowPosDY", ).toInt();
this->setGeometry(x, y, w, h);
ui.actWordWrap->setChecked(settings.value("fWrap", true).toBool());
ui.actStatus->setChecked(settings.value("StatusBar", true).toBool());
ui.statusBar->setVisible(ui.actStatus->isChecked());
} void NotePad::saveSettings()
{
//大小&位置
QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Notepad", QSettings::NativeFormat);
settings.setValue("iWindowPosX", this->x());
settings.setValue("iWindowPosY", this->y());
settings.setValue("iWindowPosDX", this->width());
settings.setValue("iWindowPosDY", this->height());
settings.setValue("fWrap", ui.actWordWrap->isChecked());
settings.setValue("StatusBar", ui.actStatus->isChecked());
} void NotePad::setFileName(QString fileName)
{
this->fileName = fileName;
ui.textEdit->document()->setModified(false); QString shownName;
if (fileName.isEmpty())
shownName = tr("未命名");
else
shownName = QFileInfo(fileName).fileName();
setWindowTitle(tr("%1[*] - %2").arg(shownName, tr("记事本")));
setWindowModified(false); lastDir = QFileInfo(fileName).absoluteDir().absolutePath();
} void NotePad::loadFromFile(QString fileName)
{
QFileInfo fileInfo(fileName);
if (!fileInfo.isFile())
return; QFile file(fileName);
if (!file.open(QIODevice::ReadOnly))
{
QMessageBox::warning(this, tr("提示"), tr("不能打开此文件!"), tr("确定"));
return;
} setFileName(fileName);
QTextStream in(&file);
ui.textEdit->setText(in.readAll());
} void NotePad::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("text/uri-list"))
event->acceptProposedAction();
} void NotePad::dropEvent(QDropEvent *event)
{
QList<QUrl> urls = event->mimeData()->urls();
if (urls.isEmpty())
return; QString fileName = urls.first().toLocalFile();
if (!fileName.isEmpty())
loadFromFile(fileName);
} void NotePad::closeEvent(QCloseEvent * event)
{
if (confirmSave())
{
saveSettings();
event->accept();
}
else
event->ignore();
} bool NotePad::confirmSave()
{
if (!ui.textEdit->document()->isModified())
return true; QMessageBox::StandardButtons sb = QMessageBox::question(this, tr("提示"), tr("是否将更改保存到 %1?").arg(this->windowTitle().replace(tr(" - 记事本"), "")),
tr("保存(&S)"), tr("不保存(&N)"), tr("取消")); switch (sb)
{
case :
return saveFile();
case :
return true;
case :
return false;
default:
return true;
}
} bool NotePad::saveFile()
{
if (this->fileName.isEmpty())
return saveFileAs(); return saveFile(this->fileName);
} bool NotePad::saveFile(QString fileName)
{
if (!ui.textEdit->document()->isModified())
return false; QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text))
{
QMessageBox::critical(this, tr("提示"), tr("不能写入文件!"), tr("确定"));
return false;
} QTextStream out(&file);
out << ui.textEdit->toPlainText();
setFileName(fileName);
return true;
} bool NotePad::saveFileAs()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("另存为"),
lastDir + tr("./未命名.txt"), tr("文本文档(*.txt);;所有文件(*.*)"));
if (fileName.isEmpty())
return false; return saveFile(fileName);
} void NotePad::setActionState()
{
ui.actUndo->setEnabled(false);
ui.actCopy->setEnabled(false);
ui.actCut->setEnabled(false);
ui.actDelete->setEnabled(false); ui.actFind->setEnabled(false);
ui.actFindNext->setEnabled(false);
ui.actGoto->setEnabled(false);
} void NotePad::initTextEdifUI()
{
QPalette palette = ui.textEdit->palette();
palette.setColor(QPalette::Highlight, Qt::darkGreen);
palette.setColor(QPalette::HighlightedText, Qt::white);
ui.textEdit->setPalette(palette); ui.textEdit->setAcceptDrops(false);
setAcceptDrops(true);
} //槽函数
void NotePad::slotNew()
{
if (!confirmSave())
return; ui.textEdit->clear();
setFileName("");
} void NotePad::slotOpen()
{
if (!confirmSave())
return; QString fileName = QFileDialog::getOpenFileName(this, tr("另存为"),
lastDir, tr("文本文档(*.txt);;所有文件(*.*)"));
if (!fileName.isEmpty())
loadFromFile(fileName);
} void NotePad::slotSave()
{
saveFile();
} void NotePad::slotSaveAs()
{
saveFileAs();
} void NotePad::slotPageSetup()
{
QPrinter printer;
QPageSetupDialog pageSetUpdlg(&printer, this);
if (pageSetUpdlg.exec() == QDialog::Accepted)
printer.setOrientation(QPrinter::Landscape);
else
printer.setOrientation(QPrinter::Portrait);
} void NotePad::slotPrint()
{
QPrinter printer;
QString printerName = printer.printerName();
if (printerName.size() == )
return; QPrintDialog dlg(&printer, this);
if (ui.textEdit->textCursor().hasSelection())
dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection);
// 如果在对话框中按下了打印按钮,则执行打印操作
if (dlg.exec() == QDialog::Accepted)
ui.textEdit->print(&printer);
} void NotePad::slotExit()
{
this->close();
} void NotePad::slotUndo()
{
ui.textEdit->undo();
} void NotePad::slotCut()
{
ui.textEdit->cut();
} void NotePad::slotCopy()
{
ui.textEdit->copy();
} void NotePad::slotPaste()
{
ui.textEdit->paste();
} void NotePad::slotDelete()
{
ui.textEdit->textCursor().removeSelectedText();
} void NotePad::slotFind()
{
if (replaceDialog != Q_NULLPTR && replaceDialog->isVisible())
{
replaceDialog->activateWindow();
return;
} if (searchDialog == Q_NULLPTR)
searchDialog = new SearchDialog(this, ui.textEdit);
searchDialog->show();
searchDialog->activateWindow();
} void NotePad::slotFindNext()
{
if (searchDialog == Q_NULLPTR)
searchDialog = new SearchDialog(this, ui.textEdit);
searchDialog->search();
} void NotePad::slotReplace()
{
if (searchDialog != Q_NULLPTR && searchDialog->isVisible())
{
searchDialog->activateWindow();
return;
} if (replaceDialog == Q_NULLPTR)
replaceDialog = new ReplaceDialog(this, ui.textEdit);
replaceDialog->show();
replaceDialog->activateWindow();
} void NotePad::slotGoto()
{
//跳转...传this以此做为其窗主,Modal状态标题栏闪烁
GotoDialog gotoDialog(this);
gotoDialog.setLineNumber(ui.textEdit->textCursor().blockNumber() + , ui.textEdit->document()->lineCount());
if (gotoDialog.exec() == QDialog::Accepted)
{
int line = gotoDialog.gotoLine;
QTextCursor cursor = ui.textEdit->textCursor();
int position = ui.textEdit->document()->findBlockByNumber(line - ).position();
cursor.setPosition(position, QTextCursor::MoveAnchor);
ui.textEdit->setTextCursor(cursor);
}
} void NotePad::slotSelectAll()
{
ui.textEdit->selectAll();
} void NotePad::slotDatetime()
{
QString dateTime = QDateTime::currentDateTime().toString(Qt::SystemLocaleDate);
ui.textEdit->textCursor().insertText(dateTime);
} void NotePad::slotWordWrap()
{
if (ui.actWordWrap->isChecked())
ui.textEdit->setWordWrapMode(QTextOption::WordWrap);
else
ui.textEdit->setWordWrapMode(QTextOption::NoWrap); ui.actGoto->setEnabled(!ui.actWordWrap->isChecked());
ui.actStatus->setEnabled(ui.actWordWrap->isChecked());
if (!ui.actWordWrap->isChecked())
{
if (ui.actStatus->isChecked())
{
ui.actStatus->setChecked(false);
ui.statusBar->setVisible(ui.actStatus->isChecked());
}
}
else if (this->statusChecked)
ui.actStatus->trigger();
} void NotePad::slotFont()
{
bool ok;
QFont font = QFontDialog::getFont(&ok, ui.textEdit->font());
if (ok)
ui.textEdit->setFont(font);
} void NotePad::slotStatus()
{
this->statusChecked = ui.actStatus->isChecked();
ui.statusBar->setVisible(ui.actStatus->isChecked());
} void NotePad::slotHelp()
{
QMessageBox::warning(this, tr("提示"), tr("黔驴技穷,搞不定[IHxHelpPane->(\"mshelp://windows/?id=e725b43f-94e4-4410-98e7-cc87ab2739aa\")]"), tr("确定")); //HxHelpPane *helpPane = new HxHelpPane();
//CoInitialize(NULL);
//IHxHelpPane *helpPane = NULL;
//HRESULT hr = ::CoCreateInstance(CLSID_HxHelpPane, NULL, CLSCTX_ALL, IID_IHxHelpPane, reinterpret_cast<void**>(&helpPane));
//if (SUCCEEDED(hr))
// helpPane->DisplayTask(BSTR("mshelp://windows/?id=e725b43f-94e4-4410-98e7-cc87ab2739aa"));
} void NotePad::slotAbout()
{
QString appPath = QApplication::applicationFilePath();
HICON icon = ExtractIcon(NULL, appPath.toStdWString().c_str(), );
ShellAbout((HWND)this->winId(), tr("Qt记事本").toStdWString().c_str(), tr("作者:刘景威").toStdWString().c_str(), icon);
} void NotePad::slotCopyAvailable(bool enabled)
{
ui.actCopy->setEnabled(enabled);
} void NotePad::slotCursorPositionChanged()
{
QTextCursor tc = ui.textEdit->textCursor();
QString info = tr("第%1行,第%2列 ").arg(tc.blockNumber() + ).arg(tc.columnNumber());
lblStatus->setText(info);
} void NotePad::slotRedoAvailable(bool enabled)
{
} void NotePad::slotSelectionChanged()
{
QString selecdedText = ui.textEdit->textCursor().selectedText();
//ui.actUndo
ui.actCopy->setEnabled(!selecdedText.isEmpty());
ui.actCut->setEnabled(!selecdedText.isEmpty());
ui.actDelete->setEnabled(!selecdedText.isEmpty());
} void NotePad::slotTextChanged()
{
slotSelectionChanged(); QString text = ui.textEdit->toPlainText();
ui.actFind->setEnabled(text != "");
ui.actFindNext->setEnabled(text != "");
ui.actGoto->setEnabled(text != "" && !ui.actWordWrap->isChecked());
} void NotePad::slotUndoAvailable(bool enabled)
{
ui.actUndo->setEnabled(enabled);
}

3、跳转模块(goto.cpp)

#include "qmessagebox.h"
#include "goto.h" GotoDialog::GotoDialog(QWidget *parent) :
QDialog(parent)
{
ui.setupUi(this);
setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint | Qt::MSWindowsFixedSizeDialogHint); ui.label->setBuddy(ui.lineEdit);
QRegExp regx("[0-9]+$");
QValidator *validator = new QRegExpValidator(regx, this);
ui.lineEdit->setValidator(validator);
} GotoDialog::~GotoDialog()
{
} void GotoDialog::setLineNumber(int currLine, int maxLineCount)
{
ui.lineEdit->setText(QString::number(currLine));
ui.lineEdit->selectAll();
this->maxLineCount = maxLineCount;
} void GotoDialog::accept()
{
QString value = ui.lineEdit->text().trimmed();
if (value.isEmpty())
{
this->showMessage(tr("请输入要跳到的行数。"));
return;
}
if (value.toInt() > this->maxLineCount)
{
this->showMessage(tr("行数超过了总行数。"));
return;
} this->gotoLine = value.toInt();
return QDialog::accept();
} void GotoDialog::showMessage(QString title)
{
QMessageBox::warning(this, tr("记事本 - 跳行"), title, tr("确定"));
}

4、查找功能(search.cpp):

#include "qmessagebox.h"
#include "qtextedit.h"
#include "qtextdocument.h"
#include "search.h" SearchDialog::SearchDialog(QWidget *parent, QTextEdit *textEdit) :
QDialog(parent),
textEdit(textEdit)
{
ui.setupUi(this);
setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint | Qt::MSWindowsFixedSizeDialogHint); ui.label->setBuddy(ui.lineEdit);
ui.searchButton->setEnabled(false);
QObject::connect(ui.searchButton, SIGNAL(clicked()), this, SLOT(search()));
QObject::connect(ui.lineEdit, &QLineEdit::textChanged, [=]()
{
ui.searchButton->setEnabled(ui.lineEdit->text() != "");
});
} SearchDialog::~SearchDialog()
{
} void SearchDialog::activateWindow()
{
QDialog::activateWindow(); ui.lineEdit->setText(textEdit->textCursor().selectedText());
ui.lineEdit->selectAll();
} //此重载方法实现选择数据填充,置入上面函数中
//void SearchDialog::show(QString text)
//{
// QDialog::show();
// if (text != "")
// ui.lineEdit->setText(text);
//} void SearchDialog::search()
{
QString text = ui.lineEdit->text();
if (text.isEmpty())
return; QTextDocument::FindFlags findFlags;
if (ui.cbCaseSensitive->isChecked())
findFlags = QTextDocument::FindCaseSensitively;
if (ui.rbUp->isChecked())
findFlags |= QTextDocument::FindBackward;
bool found = textEdit->find(text, findFlags); if (!found)
QMessageBox::information(this, tr("记事本"), tr("找不到\"%1\"").arg(text), QMessageBox::Ok);
}

5、替换功能(replace.cpp):

#include "qmessagebox.h"
#include "qtextedit.h"
#include "qtextdocument.h"
#include "replace.h" ReplaceDialog::ReplaceDialog(QWidget *parent, QTextEdit *textEdit) :
QDialog(parent),
textEdit(textEdit)
{
ui.setupUi(this);
setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint | Qt::MSWindowsFixedSizeDialogHint); initDialog();
} ReplaceDialog::~ReplaceDialog()
{
} void ReplaceDialog::initDialog()
{
ui.label->setBuddy(ui.lineEdit);
ui.lblReplace->setBuddy(ui.replaceEdit);
ui.searchButton->setEnabled(false);
ui.replaceButton->setEnabled(false);
ui.replaceAllButton->setEnabled(false);
QObject::connect(ui.searchButton, SIGNAL(clicked()), this, SLOT(search()));
QObject::connect(ui.replaceButton, SIGNAL(clicked()), this, SLOT(replace()));
QObject::connect(ui.replaceAllButton, SIGNAL(clicked()), this, SLOT(replaceAll()));
QObject::connect(ui.lineEdit, &QLineEdit::textChanged, [=]()
{
ui.searchButton->setEnabled(ui.lineEdit->text() != "");
ui.replaceButton->setEnabled(ui.lineEdit->text() != "");
ui.replaceAllButton->setEnabled(ui.lineEdit->text() != "");
});
} void ReplaceDialog::activateWindow()
{
QDialog::activateWindow(); ui.lineEdit->setText(textEdit->textCursor().selectedText());
ui.lineEdit->selectAll();
} bool ReplaceDialog::search(bool showWarn)
{
QString text = ui.lineEdit->text();
if (text.isEmpty())
return false; QTextDocument::FindFlags findFlags;
if (ui.cbCaseSensitive->isChecked())
findFlags = QTextDocument::FindCaseSensitively;
bool found = textEdit->find(text, findFlags); if (!found && showWarn)
QMessageBox::information(this, tr("记事本"), tr("找不到\"%1\"").arg(text), QMessageBox::Ok);
return found;
} void ReplaceDialog::replace()
{
bool found = search();
if (!found)
return; QTextCursor textCursor = textEdit->textCursor();
QString replaceText = ui.replaceEdit->text();
textCursor.insertText(replaceText); //寻找下一个
search();
} void ReplaceDialog::replaceAll()
{
QString text = ui.lineEdit->text();
if (text.isEmpty())
return; QTextDocument::FindFlags findFlags;
if (ui.cbCaseSensitive->isChecked())
findFlags = QTextDocument::FindCaseSensitively;
QString replaceText = ui.replaceEdit->text();
while (textEdit->find(text, findFlags))
{
QTextCursor textCursor = textEdit->textCursor();
textCursor.insertText(replaceText);
}
//往回找
findFlags |= QTextDocument::FindBackward;
while (textEdit->find(text, findFlags))
{
QTextCursor textCursor = textEdit->textCursor();
textCursor.insertText(replaceText);
}
}

源码下载:

https://files.cnblogs.com/files/crwy/qt_notepad.rar

Qt: 记事本源代码的更多相关文章

  1. 23.QT记事本

    描述 主要功能有: 新建,打开,保存,另存为,打印, 编辑,撤销,,拖放,xml配置文件读写,字体更改,查找替换 菜单栏,工具栏,状态栏的实现 如下图所示: 效果如下所示:   源码下载地址: htt ...

  2. 在QtCreater中配置Artistic Style格式化Qt程序源代码!!

    Qt很吸引人,可能是我对Qt开发工具QtCreater不熟悉,只发现里面提供了一个快捷键:"ctrl+i",很多人说这就是格式化代码快捷键,我发现这仅仅是代码缩进,并不是真正意义上 ...

  3. QT 记事本小程序

    //mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <Q ...

  4. Qt记事本,美化版

    主体代码实现 #include "mainwindow.h" #include "ui_mainwindow.h" #include<QMenu> ...

  5. qt creator 源代码中含有中文编译报错

    Tools-Options-Text Editor-Behavior-File Encoding-Default encoding:UTF-8 Tools-Options-Text Editor-Be ...

  6. 记事本源代码 python3

    已实现基本功能,显示行号功能暂时实现不了(后面学会了再加,右下角可以实现定位光标所在行.列) 可能会有些bug 1 from tkinter import * from tkinter.message ...

  7. Qt核心剖析: 寻找 QObject 的源代码

    本来打算把<Qt学习之路>作为一个类似教程的东西,所以就不打算把一些关系到源代码的内容放在那个系列之中啦.因此今天就先来看一个新的开始吧!这个系列估计不会进展很快,因为最近公司里面要做 f ...

  8. QT的三种协议说明

    关于Qt的三种协议以及是否收费,有以下引文: 引文一: 最近一直在学习 Qt.Qt 有两个许可证:LGPL 和商业协议.这两个协议在现在的 Qt 版本中的代码是完全一致的(潜在含义是,Qt 的早期版本 ...

  9. Qt中,当QDockWidget的父窗口是一个不可以拖动的QTabWidget的时候实现拖动的方法

    之前在做有关QDockWidget的内容时候遇到了瓶颈,那就是窗口弹出来之后拖动不了,也不可以放大和缩小,若是弹出来之后设置成了window的flags,也不可以拖动,而且也不是需要的效果. 1.弹出 ...

随机推荐

  1. Java快速开发平台——JEECG 3.7.8 版本发布!我们的目标是有鱼丸也有粗面

    JEECG 3.7.8 版本发布,多样化主题UI满足你不同的需求 导读                    ⊙平台性能优化,速度闪电般提升           ⊙提供5套新的主流UI代码生成器模板( ...

  2. sizeof 空类

    C++标准规定类的大小不为0,空类的大小为1,当类不包含虚函数和非静态数据成员时,其对象大小也为1. 如果在类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针 ...

  3. jquery接触初级-----ajax 之:load()方法

    jquery _ajax 请求主要有几种方式:load(),$.get(),$.post(),$.ajax(),$.getScript(),$.getJson() 1.load()方法 格式:load ...

  4. Servlet基本_初期化パラメータ、外部ファイル

    1.サーブレットの初期化パラメータサーブレットの初期化パラメータを利用するには.必ずweb.xmlにおいてサーブレットマッピングを指定する必要がある.(Tomactのinvokerサーブレットは利用で ...

  5. sublime text3 激活码——许可证

    亲测: 现在是公元2018年6月4日.晴 ``` ----- BEGIN LICENSE ----- sgbteam Single User License EA7E-1153259 8891CBB9 ...

  6. 对于低版本IE,ajax的设置处理

    !(function() {     var timeout = 16000;     //设置ajax请求的setting配置----start     jQuery.support.cors = ...

  7. shell脚本中比较两个小数的办法

    具体情况#man bc 然而对小数进行比较的相关方法有几个: 1. 自己的解决方法,判断小数点后最多有几位数(N),然后对将要比较的两个数值进行 乘与10的N次方 也就是将小数点去掉来进行比较(小数点 ...

  8. video 播放本地视屏

    var file = document.getElementById('file_video').files[0]; var url = URL.createObjectURL(file); docu ...

  9. pandas 常用清洗数据(三)排序,去重

    1.排序 DataFrame 按照Index排序 Series.order()进行排序,而DataFrame则用sort或者sort_index或者sort_values 2.去重, dt = dt. ...

  10. 04_web基础(一)之tomcat介绍

    01.web引入 在这之前我们已经能够在数据库进行CRUD,在dao处进行CRUD,在service处进行CRUD,对用户来说必须在浏览器上进行CRUD,要完成这个就必须具备web知识. 而web运行 ...