zoukankan      html  css  js  c++  java
  • Qt: 记事本源代码

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

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

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

    IDE: VS2015+Qt5.8.0

    界面如下:

    Qt记事本

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

    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 >= 2)
        {
            QString s = QString::fromLocal8Bit(argv[1]);
            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", 0).toInt();
        int y = settings.value("iWindowPosY", 0).toInt();
        int w = settings.value("iWindowPosDX", 800).toInt();
        int h = settings.value("iWindowPosDY", 600).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 0:
            return saveFile();
        case 1:
            return true;
        case 2:
            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() == 0)
            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() + 1, 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 - 1).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(), 0);
        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() + 1).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

  • 相关阅读:
    学习MongoDB(Troubleshoot Replica Sets) 集群排除故障
    MyBatis 相同事物查询缓存问题
    Spring事物源码
    Spring Session Redis
    Tomcat配置多个域名绑定到不同项目
    Shiro相关文章资料
    一网打尽:Java 程序员必须了解的计算机底层知识!
    Chrome 80 调教篇
    谭浩强《C++程序设计》
    HTTP/HTTPS协议
  • 原文地址:https://www.cnblogs.com/crwy/p/9213830.html
Copyright © 2011-2022 走看看