首页 > 技术文章 > Qt_Demo_1:实现一个简易的记事本

mrlayfolk 2020-06-20 00:41 原文

1  环境:

系统:windows 10

代码编写运行环境:Qt Creator 4.4.1 (community)

GitHub:https://github.com/zhengcixi/Qt_Demo/tree/master/notepad

2  参考代码

 Karllenqt5.5实现 记事本程序 https://www.cnblogs.com/Forever-Kenlen-Ja/p/4985133.html

3  实现效果

主界面如下:

 

下面依次演示操作各个菜单:

(1)文件菜单

包括:新建、新窗口、打开、保存、另存为、打印、退出等功能。

(2)编辑菜单

包括:撤销、剪切、复制、粘贴、删除、查找、替换、全选等功能。

全部替换的功能还存在bug。

(3)格式菜单

包括:更换字体,自动换行功能。

自动换行功能还没有实现。

(4)查看菜单

实现功能:放大、缩小以及状态栏的查看。

放大和缩小功能使用的是QTextEdit自带的槽函数处理,但是没有效果,不知道为什么。

状态栏功能没有实现,现在状态栏默认是打开的,显示的是文本中的鼠标所在的字符是第几个字符。

(5)帮助菜单栏

实现功能:帮助菜单和关于记事本。

点击帮助菜单,会弹出一个网页并跳转到本博客。

点击关于记事本,会弹出一个消息框。

至此,记事本实现的功能就大致如此了,上述的功能大部分也可以通过快捷键的方式进行访问。

下面简单说说工程的组织结构,及部分代码。

4  工程结构及代码说明

工程包含的文件有:

 其中,mainwindow.h和mainwindow.cpp是主窗口的相关文件,finddialog.h和finddialog.cpp是查找对话框的相关文件,replacedialog.h和replacedialog.cpp是替换对话框的相关文件。

先给出各个文件的源代码:

finddialog.h

 1 #ifndef FINDDIALOG_H
 2 #define FINDDIALOG_H
 3 
 4 #include <QWidget>
 5 #include <QLabel>
 6 #include <QLineEdit>
 7 #include <QPushButton>
 8 #include <QRadioButton>
 9 #include <QCheckBox>
10 #include <QGridLayout>
11 #include <QHBoxLayout>
12 #include <QGroupBox>
13 #include <QCheckBox>
14 #include <QDialog>
15 
16 class FindDialog : public QDialog
17 {
18     Q_OBJECT
19 public:
20     explicit FindDialog(QWidget *parent = nullptr);
21 
22 signals:
23     //参数:查找关键字、是否区分大小写、向前或向后查找
24     void findTextDataButtonClickedSignal(QString, bool, bool);
25 
26 public slots:
27     void findButtonState();
28     void findDataButtonClickedState();
29 
30 private:
31     QLineEdit *find_edit;
32     QLabel *find_label, *ignore_label, *next_label, *back_label;
33     QPushButton  *find_button;
34     QRadioButton *next_radio;
35     QRadioButton *back_radio;
36     QCheckBox *ignore_flag;
37 };
38 
39 #endif // FINDDIALOG_H
View Code

mainwindow.h

  1 #ifndef MAINWINDOW_H
  2 #define MAINWINDOW_H
  3 
  4 #include <QMainWindow>
  5 #include <QMenuBar>
  6 #include <QAction>
  7 #include <QMenu>
  8 #include <QTextEdit>
  9 #include <QStatusBar>
 10 #include <QLabel>
 11 #include <QDebug>
 12 #include <QString>
 13 #include <QFileDialog>
 14 #include <QFile>
 15 #include <QMessageBox>
 16 #include "finddialog.h"
 17 #include "replacedialog.h"
 18 
 19 class MainWindow : public QMainWindow
 20 {
 21     Q_OBJECT
 22 
 23 public:
 24     MainWindow(QWidget *parent = 0);
 25     ~MainWindow();
 26     //常用函数
 27     void CreateMenu();  //创建主菜单
 28     void Creatslots();  //创建各组件的槽函数
 29     void save_file();   //保存文件
 30 
 31     /* 槽函数 */
 32     //菜单项--文件相关功能:新建、新建新窗口、打卡、保存、另存、打印、退出
 33     void slot_menu_file_new(void);
 34     void slot_menu_file_new_win(void);
 35     void slot_menu_file_open(void);
 36     void slot_menu_file_save(void);
 37     void slot_menu_file_save_as(void);
 38     void slot_menu_file_print(void);
 39     void slot_menu_file_quit(void);
 40 
 41     //菜单项--编辑相关功能:撤销、剪切、复制、粘贴、删除、查找、替换、全选
 42     void slot_menu_edit_undo(void);
 43     void slot_menu_edit_cut(void);
 44     void slot_menu_edit_copy(void);
 45     void slot_menu_edit_paste(void);
 46     void slot_menu_edit_delete(void);
 47     void slot_menu_edit_find();
 48     void slot_menu_edit_replace(void);
 49     void slot_menu_edit_all(void);
 50 
 51     //菜单项--格式相关功能:自动换行、格式
 52     void slot_menu_format_warp(void);
 53     void slot_menu_format_font(void);
 54 
 55     //菜单项--查看相关功能:放大、缩小、状态栏
 56     void slot_menu_view_zoon_in(void);
 57     void slot_menu_view_zoon_out(void);
 58     void slot_menu_view_status(void);
 59 
 60     //菜单项--帮助相关功能:查看帮助、关于
 61     void slot_menu_help_view(void);
 62     void slot_menu_help_about(void);
 63 
 64     //查找、替换
 65     void findAct(QString, bool, bool);
 66     void findReplace(QString, bool);
 67     void replaceCur(QString, QString);
 68     void replaceAll(QString, QString, bool);
 69 
 70     //文本状态发生变化时调用
 71     void slot_judge_text_state();
 72     //文本中的鼠标发生状态时调用
 73     void slot_cursor_change_state();
 74 
 75 private:
 76     QTextEdit *textEdit;
 77     QString cur_file_name;
 78     QString sbar_str;  //状态栏
 79 
 80     /* 添加菜单栏 */
 81     QMenuBar *qBar;
 82     //菜单--文件
 83     QMenu *menu_file;
 84     QAction *menu_file_new;
 85     QAction *menu_file_new_win;
 86     QAction *menu_file_open;
 87     QAction *menu_file_save;
 88     QAction *menu_file_save_as;
 89     QAction *menu_file_print;
 90     QAction *menu_file_quit;
 91 
 92     //菜单--编辑
 93     QMenu *menu_edit;
 94     QAction *menu_edit_undo;
 95     QAction *menu_edit_cut;
 96     QAction *menu_edit_copy;
 97     QAction *menu_edit_paste;
 98     QAction *menu_edit_delete;
 99     QAction *menu_edit_find;
100     QAction *menu_edit_replace;
101     QAction *menu_edit_all;
102 
103     //菜单--格式
104     QMenu *menu_format;
105     QAction *menu_format_warp;
106     QAction *menu_format_font;
107 
108     //菜单--查看
109     QMenu *menu_view;
110     QAction *menu_view_zoom_in;
111     QAction *menu_view_zoom_out;
112     QAction *menu_view_status;
113 
114     //菜单--帮助
115     QMenu *menu_help;
116     QAction *menu_help_view;
117     QAction *menu_help_about;
118 
119     /* 添加状态栏 */
120     QStatusBar *sbar;
121     QLabel *label;
122 
123     /* 查找替换 */
124     bool find;
125     FindDialog *find_dialog;
126     replacedialog *replace_dialog;
127 
128     /* 剪贴板 */
129     QClipboard *clipboard;
130 };
131 
132 #endif // MAINWINDOW_H
View Code

replacedialog.h

 1 #ifndef REPLACEDIALOG_H
 2 #define REPLACEDIALOG_H
 3 
 4 #include <QWidget>
 5 #include <QDialog>
 6 #include <QPushButton>
 7 #include <QLabel>
 8 #include <QCheckBox>
 9 #include <QLineEdit>
10 #include <QGridLayout>
11 #include <QVBoxLayout>
12 #include <QString>
13 
14 class replacedialog : public QDialog
15 {
16     Q_OBJECT
17 public:
18     explicit replacedialog(QWidget *parent = nullptr);
19 
20 signals:
21     void signal_replaceAllStr(QString, QString, bool);
22     void signal_replaceCurOneStr(QString, QString);
23     void signal_findReplaceStr(QString, bool);
24 
25 public slots:
26     void slot_choose_str();
27     void slot_find_button_state();
28     void slot_replace_one_button_state();
29     void slot_repalce_all_button_state();
30 
31 private:
32     QLineEdit *find_str;
33     QLineEdit *replace_str;
34     QPushButton *find_next_button;
35     QPushButton *replace_one_button;
36     QPushButton *replace_all_button;
37     QPushButton *cancel_button;
38     QCheckBox *ignore_flag;
39     QLabel *find_label;
40     QLabel *replace_label;
41 
42 };
43 
44 #endif // REPLACEDIALOG_H
View Code

finddialog.cpp

 1 #include "finddialog.h"
 2 #include <QDebug>
 3 
 4 FindDialog::FindDialog(QWidget *parent) : QDialog(parent)
 5 {
 6     setWindowTitle("查找");
 7     find_label  = new QLabel("查找");
 8     ignore_label= new QLabel("区分大小写");
 9     next_label  = new QLabel("向后");
10     back_label  = new QLabel("向前");
11     find_edit   = new QLineEdit;
12     find_button = new QPushButton("查找下一个");
13     next_radio  = new QRadioButton;
14     back_radio  = new QRadioButton;
15     ignore_flag = new QCheckBox;
16 
17     find_edit->setText("");
18 
19     QGridLayout *grid_layout = new QGridLayout(this);
20     grid_layout->addWidget(find_label, 0, 0);
21     grid_layout->addWidget(find_edit, 0, 1);
22     grid_layout->addWidget(find_button, 0, 3);
23 
24     QHBoxLayout *ignore_layout = new QHBoxLayout;
25     ignore_layout->setSpacing(10);
26     ignore_layout->addWidget(ignore_label);
27     ignore_layout->addWidget(ignore_flag);
28 
29     QHBoxLayout *radio_layout = new QHBoxLayout;
30     radio_layout->addWidget(next_label);
31     radio_layout->addWidget(next_radio);
32     radio_layout->addWidget(back_label);
33     radio_layout->addWidget(back_radio);
34 
35     QGroupBox *group_radio = new QGroupBox("方向", this);
36     group_radio->setLayout(radio_layout);
37 
38     QHBoxLayout *do_radio = new QHBoxLayout;
39     do_radio->addWidget(group_radio);
40 
41     grid_layout->addLayout(ignore_layout, 1, 0);
42     grid_layout->addLayout(do_radio, 1, 1);
43 
44     this->setMaximumSize(400, 200);
45     this->setMinimumSize(350, 150);
46     next_radio->setCheckable(true);
47     find_button->setEnabled(false);
48     connect(find_edit,   &QLineEdit::textChanged, this, &FindDialog::findButtonState);
49     connect(find_button, &QPushButton::clicked,   this, &FindDialog::findDataButtonClickedState);
50 }
51 
52 void FindDialog::findButtonState()
53 {
54     if (find_edit->text().isEmpty()) {
55         find_button->setEnabled(false);
56     } else {
57         find_button->setEnabled(true);
58     }
59 }
60 void FindDialog::findDataButtonClickedState()
61 {
62     if (find_edit->text().isEmpty()) {
63         return;
64     }
65     QString str = find_edit->text();
66     if (next_radio->isChecked()) {
67         if (ignore_flag->isChecked()) {
68             emit findTextDataButtonClickedSignal(str, true, true);
69         } else {
70             emit findTextDataButtonClickedSignal(str, false, true);
71         }
72     }
73     if (back_radio->isChecked()) {
74         if (ignore_flag->isChecked()) {
75             emit findTextDataButtonClickedSignal(str, true, false);
76         } else {
77             emit findTextDataButtonClickedSignal(str, false, false);
78         }
79     }
80 }
View Code

main.cpp

 1 #include "mainwindow.h"
 2 #include <QApplication>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     QApplication a(argc, argv);
 7     MainWindow w;
 8     w.show();
 9 
10     return a.exec();
11 }
View Code

mainwindow.cpp

  1 #include "mainwindow.h"
  2 #include <QDialog>
  3 #include <QDebug>
  4 #include <QtPrintSupport/QPrinter>
  5 #include <QtPrintSupport/QPrintDialog>
  6 #include <QtPrintSupport/QAbstractPrintDialog>
  7 #include <QPixmap>
  8 #include <QTextCursor>
  9 #include <QKeySequence>
 10 #include <QFontDialog>
 11 #include <QFont>
 12 #include <QDesktopServices>
 13 #include <QLatin1String>
 14 #include <QTextCodec>
 15 #include <QClipboard>
 16 #include <QApplication>
 17 #include <QTextCursor>
 18 #include <QPoint>
 19 #include <QTextEdit>
 20 
 21 MainWindow::MainWindow(QWidget *parent)
 22     : QMainWindow(parent)
 23 {
 24     //查找文本框
 25     find_dialog = new FindDialog(this);
 26     //替换文本框
 27     replace_dialog = new replacedialog(this);
 28     //剪贴板
 29     clipboard = QApplication::clipboard();
 30 
 31     this->resize(900, 700);
 32     CreateMenu();
 33     Creatslots();
 34 }
 35 
 36 void MainWindow::CreateMenu()
 37 {
 38     /* 添加核心控件 */
 39     textEdit = new QTextEdit(this);
 40     this->setCentralWidget(textEdit);
 41     cur_file_name = "";
 42     sbar = statusBar();
 43     label = new QLabel(this);
 44 
 45     /* 添加菜单栏 */
 46     qBar = menuBar();
 47     //添加菜单--文件
 48     menu_file = qBar->addMenu("文件(F)");
 49     menu_file_new = menu_file->addAction("新建(N)");
 50     menu_file_new->setShortcut(QKeySequence::New);
 51     menu_file_new_win = menu_file->addAction("新窗口(W)");
 52     menu_file_open    = menu_file->addAction("打开(O)");
 53     menu_file_open->setShortcut(QKeySequence::Open);
 54     menu_file_save    = menu_file->addAction("保存(S)");
 55     menu_file_save->setShortcut(QKeySequence::Save);
 56     menu_file_save_as = menu_file->addAction("另存为(S)");
 57     menu_file_save_as->setShortcut(QKeySequence::SaveAs);
 58     menu_file->addSeparator();
 59     menu_file_print = menu_file->addAction("打印(P)");
 60     menu_file_print->setShortcut(QKeySequence::Print);
 61     menu_file->addSeparator();
 62     menu_file_quit  = menu_file->addAction("退出(X)");
 63     menu_file_quit->setShortcut(QKeySequence::Quit);
 64 
 65     //添加菜单项--编辑
 66     menu_edit = qBar->addMenu("编辑(E)");
 67     menu_edit_undo = menu_edit->addAction("撤销(U)");
 68     menu_edit_undo->setShortcut(QKeySequence::Undo);
 69     menu_edit_undo->setEnabled(false);
 70     menu_edit->addSeparator();
 71     menu_edit_cut    = menu_edit->addAction("剪切(T)");
 72     menu_edit_cut->setShortcut(QKeySequence::Cut);
 73     menu_edit_cut->setEnabled(false);
 74     menu_edit_copy   = menu_edit->addAction("复制(C)");
 75     menu_edit_copy->setShortcut(QKeySequence::Copy);
 76     menu_edit_copy->setEnabled(false);
 77     menu_edit_paste  = menu_edit->addAction("粘贴(P)");
 78     menu_edit_paste->setShortcut(QKeySequence::Paste);
 79     menu_edit_delete = menu_edit->addAction("删除(D)");
 80     menu_edit_delete->setShortcut(QKeySequence::Delete);
 81     menu_edit_delete->setEnabled(false);
 82     menu_edit_delete->setShortcut(QKeySequence::Delete);
 83     menu_edit->addSeparator();
 84     menu_edit_find    = menu_edit->addAction("查找(F)");
 85     menu_edit_find->setShortcut(QKeySequence::Find);
 86     menu_edit_replace = menu_edit->addAction("替换(R)");
 87     menu_edit_replace->setShortcut(QKeySequence::Replace);
 88     menu_edit->addSeparator();
 89     menu_edit_all = menu_edit->addAction("全选(A)");
 90     menu_edit_all->setShortcut(QKeySequence::SelectAll);
 91 
 92     //添加菜单项--格式
 93     menu_format = qBar->addMenu("格式(O)");
 94     menu_format_warp = menu_format->addAction("自动换行(W)");
 95     menu_format_font = menu_format->addAction("字体(F)");
 96 
 97     //添加菜单项--查看
 98     menu_view = qBar->addMenu("查看(V)");
 99     menu_view_zoom_in = menu_view->addAction("放大(Z)");
100     menu_view_zoom_in->setShortcut(QKeySequence::ZoomIn);
101     menu_view_zoom_out = menu_view->addAction("缩小(Z)");
102     menu_view_zoom_out->setShortcut(QKeySequence::ZoomOut);
103     menu_view_status = menu_view->addAction("状态栏(S)");
104 
105     //添加菜单项--帮助
106     menu_help = qBar->addMenu("帮助(H)");
107     menu_help_view = menu_help->addAction("查看帮助(H)");
108     menu_help_about = menu_help->addAction("关于记事本(A)");
109 }
110 
111 void MainWindow::Creatslots()
112 {
113     //菜单 -- 文件
114     connect(menu_file_new,     &QAction::triggered, this, &MainWindow::slot_menu_file_new);
115     connect(menu_file_new_win, &QAction::triggered, this, &MainWindow::slot_menu_file_new_win);
116     connect(menu_file_open,    &QAction::triggered, this, &MainWindow::slot_menu_file_open);
117     connect(menu_file_save,    &QAction::triggered, this, &MainWindow::slot_menu_file_save);
118     connect(menu_file_save_as, &QAction::triggered, this, &MainWindow::slot_menu_file_save_as);
119     connect(menu_file_print,   &QAction::triggered, this, &MainWindow::slot_menu_file_print);
120     connect(menu_file_quit,    &QAction::triggered, this, &MainWindow::slot_menu_file_quit);
121 
122     //菜单 -- 编辑
123     connect(menu_edit_delete,  &QAction::triggered, this, &MainWindow::slot_menu_edit_delete);
124     connect(menu_edit_undo,    &QAction::triggered, textEdit, &textEdit->undo);  //使用QTextEdit自带的槽函数
125     connect(menu_edit_cut,     &QAction::triggered, textEdit, &textEdit->cut);
126     connect(menu_edit_copy,    &QAction::triggered, textEdit, &textEdit->copy);
127     connect(menu_edit_paste,   &QAction::triggered, textEdit, &textEdit->paste);
128     connect(menu_edit_find,    &QAction::triggered, this, &MainWindow::slot_menu_edit_find);
129     connect(menu_edit_replace, &QAction::triggered, this, &MainWindow::slot_menu_edit_replace);
130     connect(menu_edit_all,     &QAction::triggered, textEdit, &textEdit->selectAll);
131 
132     //菜单 -- 格式
133     connect(menu_format_warp, &QAction::triggered, this, &MainWindow::slot_menu_format_warp);
134     connect(menu_format_font, &QAction::triggered, this, &MainWindow::slot_menu_format_font);
135 
136     //菜单 -- 查看
137     connect(menu_view_zoom_in, &QAction::triggered, textEdit, &textEdit->zoomIn);
138     connect(menu_view_zoom_out,&QAction::triggered, textEdit, &textEdit->zoomOut);
139     connect(menu_view_status,  &QAction::triggered, this, &MainWindow::slot_menu_view_status);
140 
141     //菜单 -- 帮助
142     connect(menu_help_view,  &QAction::triggered, this, &MainWindow::slot_menu_help_view);
143     connect(menu_help_about, &QAction::triggered, this, &MainWindow::slot_menu_help_about);
144 
145     //查找、替换
146     connect(find_dialog, &FindDialog::findTextDataButtonClickedSignal, this, &MainWindow::findAct);
147     connect(replace_dialog, &replacedialog::signal_findReplaceStr, this, &MainWindow::findReplace);
148     connect(replace_dialog, &replacedialog::signal_replaceCurOneStr, this, &MainWindow::replaceCur);
149     connect(replace_dialog, &replacedialog::signal_replaceAllStr, this, &MainWindow::replaceAll);
150 
151     //判断文本框是否已经改变
152     connect(textEdit, &QTextEdit::textChanged, this, &MainWindow::slot_judge_text_state);
153     connect(textEdit, &QTextEdit::cursorPositionChanged, this, &MainWindow::slot_cursor_change_state);
154 }
155 
156 //菜单项--文件
157 void MainWindow::slot_menu_file_new(void)
158 {
159     /*
160     * 1、如果文本框是空白的,就直接新建;
161     * 2、如果文本框有内容,但内容未修改,则直接新建;
162     * 3、如果文本框有内容,且内容被修改过,则询问是否保存。
163     */
164     if (textEdit->document()->isModified()) {
165         QMessageBox::StandardButton button = QMessageBox::information(this,
166         "未保存", "是否保存?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
167         switch (button) {
168             case QMessageBox::Save:
169                 save_file();
170                 if (textEdit->document()->isModified()) {
171                     return;
172                 }
173                 break;
174             case QMessageBox::Cancel:
175                 return;
176             case QMessageBox::Discard:
177                 break;
178             default:
179                 break;
180         }
181     }
182     textEdit->clear();
183 }
184 void MainWindow::slot_menu_file_new_win(void)
185 {
186     MainWindow *new_win = new MainWindow();
187     new_win->show();
188 }
189 void MainWindow::slot_menu_file_open(void)
190 {
191     /*
192     * 1、如果文本框是空的,则直接打开文件;
193     * 2、如果文本框有内容,且内容被修改过,则询问是否保存,再打开文件。
194     */
195     if (textEdit->document()->isModified())
196     {
197         QMessageBox::StandardButton button = QMessageBox::information(this,
198         "未保存", "是否保存?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
199         switch (button) {
200             case QMessageBox::Save:
201                 save_file();
202                 if (textEdit->document()->isModified()) {
203                     return;
204                 }
205                 break;
206             case QMessageBox::Cancel:
207                 return;
208             case QMessageBox::Discard:
209                 break;
210             default:
211                 break;
212         }
213     }
214 
215     QString file_name = QFileDialog::getOpenFileName(this, "open file", "../", "文本文档(*.txt);;所有文件(*.*)");
216     cur_file_name = file_name;
217     if (!file_name.isEmpty()) {
218         QFile file(file_name);
219         if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
220             QMessageBox::critical(this, "错误", "不能打开文件");
221             return;
222         }
223         QTextStream ins(&file);
224         textEdit->setText(ins.readAll());
225         file.close();
226     }
227 }
228 void MainWindow::slot_menu_file_save(void)
229 {
230     /*
231     * 1、如果文本框是空的,则直接返回;
232     * 2、如果文本框中存在内容,且没有在一个文件中,则询问是否新建个文件保存;
233     * 3、如果文本框中存在内容,且已经在一个文件中,则将内容保存进文件。
234     */
235     if (textEdit->toPlainText().isEmpty()) {
236         return;
237     }
238 
239     if (cur_file_name.isEmpty()) {
240         QString file_name =QFileDialog::getSaveFileName(this, "保存文件", "../", "文本文档(*.txt);;所有文件(*.*)");
241         if (!file_name.isEmpty()) {
242             QFile file(file_name);
243             if (!file.open(QIODevice::WriteOnly)) {
244                 QMessageBox::critical(this, "错误", "不能打开文件");
245                 return;
246             }
247             QTextStream outs(&file);
248             outs<<textEdit->toPlainText();
249             outs.flush();
250             file.close();
251         }
252     } else {
253         QFile file(cur_file_name);
254         if (!file.open(QIODevice::WriteOnly)) {
255             QMessageBox::critical(this, "错误", "不能打开文件");
256             return;
257         }
258         QTextStream outs(&file);
259         outs<<textEdit->toPlainText();
260         outs.flush();
261         file.close();
262     }
263 }
264 void MainWindow::slot_menu_file_save_as(void)
265 {
266     /*
267     * 1、如果文本框是空的,则直接返回;
268     * 2、如果文本框中存在内容,则询问是否保存。
269     */
270     if (textEdit->toPlainText().isEmpty()) {
271         return;
272     }
273     QString file_name =QFileDialog::getSaveFileName(this, "保存文件", "../", "文本文档(*.txt);;所有文件(*.*)");
274     if (!file_name.isEmpty()) {
275         QFile file(file_name);
276         if (!file.open(QIODevice::WriteOnly)) {
277             QMessageBox::critical(this, "错误", "不能打开文件");
278             return;
279         }
280         QTextStream outs(&file);
281         outs << textEdit->toPlainText();
282         outs.flush();
283         file.close();
284     }
285 }
286 void MainWindow::slot_menu_file_print(void)
287 {
288     if (textEdit->toPlainText().isEmpty()) {
289         return;
290     }
291     QPrinter printer;
292     QString printer_name = printer.printerName();
293     QPrintDialog print_dlg(&printer, this);
294     if (printer_name.size() == 0) {
295         return;
296     }
297     if (textEdit->textCursor().hasSelection()) {
298         print_dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection);
299     }
300     if (print_dlg.exec() == QDialog::Accepted) {
301         textEdit->print(&printer);
302     }
303 }
304 void MainWindow::slot_menu_file_quit(void)
305 {
306     this->close();
307 }
308 
309 //菜单项--编辑
310 void MainWindow::slot_menu_edit_delete(void)
311 {
312     textEdit->cut();
313     clipboard->setText("");
314 }
315 void MainWindow::slot_menu_edit_replace(void)
316 {
317     replace_dialog->show();
318 }
319 void MainWindow::slot_menu_edit_find(void)
320 {
321     find_dialog->show();
322 }
323 
324 //菜单项--格式
325 void MainWindow::slot_menu_format_warp(void)
326 {
327 
328 }
329 void MainWindow::slot_menu_format_font(void)
330 {
331     QFontDialog font_dialog;
332     font_dialog.show();
333     QFont inifont = textEdit->font();
334     bool ok = false;
335     QFont font = font_dialog.getFont(&ok, inifont);
336     if (ok) {
337         textEdit->setFont(font);
338     }
339     font_dialog.close();
340 }
341 
342 //菜单项--查看
343 void MainWindow::slot_menu_view_status(void)
344 {
345 
346 }
347 
348 //菜单项--帮助
349 void MainWindow::slot_menu_help_view(void)
350 {
351     QDesktopServices::openUrl(QUrl(QLatin1String("https://www.cnblogs.com/mrlayfolk/p/13167219.html")));
352 }
353 void MainWindow::slot_menu_help_about(void)
354 {
355     QMessageBox message(QMessageBox::NoIcon, "关于", ("version: v1.0\nauthor: zzq\nqq: 544705365"));
356     message.exec();
357 }
358 
359 
360 //保存文件
361 void MainWindow::save_file()
362 {
363     if (cur_file_name.isEmpty()) {
364         QString file_name =QFileDialog::getSaveFileName(this, "保存文件", "../", "文本文档(*.txt);;所有文件(*.*)");
365         if (!file_name.isEmpty()) {
366             QFile file(file_name);
367             if (!file.open(QIODevice::WriteOnly)) {
368                 QMessageBox::critical(this, "错误", "不能打开文件");
369                 return;
370             }
371             QTextStream outs(&file);
372             outs.setCodec("utf-8");
373             outs<<textEdit->toPlainText();
374             outs.flush();
375             file.close();
376             textEdit->document()->setModified(false);
377         }
378     } else {
379         QFile file(cur_file_name);
380         if (!file.open(QIODevice::WriteOnly)) {
381             QMessageBox::critical(this, "错误", "不能打开文件");
382             return;
383         }
384         QTextStream outs(&file);
385         outs.setCodec("utf-8");
386         outs<<textEdit->toPlainText();
387         outs.flush();
388         file.close();
389         textEdit->document()->setModified(false);
390     }
391 }
392 
393 //查找
394 void MainWindow::findAct(QString str_key, bool ignore_case, bool choose_direction)
395 {
396     /*
397     * 参数str_key:查找的关键字,支持中文
398     * 参数ignore_case:是否区分大小写
399     * 参数choose_direction:向前或向后查找,true:向前;false:先后;
400     */
401     bool find_flag;
402     if (!str_key.isEmpty()) {
403         if (choose_direction) {
404             if (ignore_case) {
405                 find_flag = textEdit->find(str_key, QTextDocument::FindCaseSensitively);
406             } else {
407                 find_flag = textEdit->find(str_key);
408             }
409         } else {
410             if (ignore_case) {
411                 find_flag = textEdit->find(str_key, QTextDocument::FindBackward|QTextDocument::FindCaseSensitively);
412             } else {
413                 find_flag = textEdit->find(str_key, QTextDocument::FindBackward);
414             }
415         }
416         if (!find_flag) {
417             QMessageBox::information(this, "结果", "没有找到查找内容", QMessageBox::Yes);
418         }
419     }
420 }
421 //替换
422 void MainWindow::findReplace(QString find_str, bool ignore_flg)
423 {
424     /*
425     * 参数find_str:查找关键字
426     * 参数ignore_flg:区分大小写
427     */
428     bool find_flag;
429     if (ignore_flg) {
430         find_flag = textEdit->find(find_str, QTextDocument::FindCaseSensitively);
431     } else {
432         find_flag = textEdit->find(find_str);
433     }
434     if (!find_flag) {
435         QMessageBox::information(this, "结果", "没有找到查找内容", QMessageBox::Yes);
436     } else {
437         find = true;
438     }
439 }
440 void MainWindow::replaceCur(QString find_str, QString replace_str)
441 {
442     /*
443     * 参数find_str:查找的关键字;
444     * 参数replace_str:替换的关键字
445     */
446     QTextCursor text_cursor;
447     if (find) {
448         text_cursor = textEdit->textCursor();
449         text_cursor.insertText(replace_str);
450     } else {
451         QMessageBox::information(this, "结果", "没有内容,不能替换"+find_str, QMessageBox::Yes);
452     }
453     find = false;
454 }
455 void MainWindow::replaceAll(QString find_str, QString replace_str, bool ignore_flg)
456 {
457     /*
458     * 参数find_str:查找关键字
459     * 参数replace_str:替换关键字
460     * 参数ignore_flg:是否忽略大小写
461     */
462     QTextCursor text_cursor;
463     if (!ignore_flg) {
464         bool haf = textEdit->find(find_str);
465         if (haf) {
466             text_cursor = textEdit->textCursor();
467             text_cursor.insertText(replace_str);
468             while (textEdit->find(find_str)) {
469                 text_cursor = textEdit->textCursor();
470                 text_cursor.insertText(replace_str);
471             }
472             while (textEdit->find(find_str, QTextDocument::FindBackward)) {
473                 text_cursor = textEdit->textCursor();
474                 text_cursor.insertText(replace_str);
475             }
476         } else {
477             QMessageBox::information(this, "结果", "没有内容,不能替换"+find_str, QMessageBox::Yes);
478         }
479     } else {
480         bool haf = textEdit->find(find_str, QTextDocument::FindCaseSensitively);
481         if (haf) {
482             text_cursor = textEdit->textCursor();
483             text_cursor.insertText(replace_str);
484             while (textEdit->find(find_str, QTextDocument::FindCaseSensitively)) {
485                 text_cursor = textEdit->textCursor();
486                 text_cursor.insertText(replace_str);
487             }
488             while (textEdit->find(find_str, QTextDocument::FindCaseSensitively|QTextDocument::FindBackward)) {
489                 text_cursor = textEdit->textCursor();
490                 text_cursor.insertText(replace_str);
491             }
492         } else {
493             QMessageBox::information(this, "结果", "没有内容,不能替换"+find_str, QMessageBox::Yes);
494         }
495     }
496 }
497 
498 void MainWindow::slot_judge_text_state()
499 {
500     if (textEdit->toPlainText().isEmpty()) {
501         menu_edit_undo->setEnabled(false);
502         menu_edit_cut->setEnabled(false);
503         menu_edit_copy->setEnabled(false);
504         menu_edit_delete->setEnabled(false);
505     } else {
506         menu_edit_undo->setEnabled(true);
507         menu_edit_cut->setEnabled(true);
508         menu_edit_copy->setEnabled(true);
509         menu_edit_delete->setEnabled(true);
510     }
511 }
512 
513 void MainWindow::slot_cursor_change_state()
514 {
515     /* 添加状态栏 */
516     int pos;
517     pos = textEdit->textCursor().position();
518     sbar_str = QString("第%1个字符").arg(pos);
519     sbar->showMessage(sbar_str);
520 }
521 
522 MainWindow::~MainWindow()
523 {
524 
525 }
View Code

replacedialog.cpp

 1 #include "replacedialog.h"
 2 #include <QString>
 3 #include <QDialog>
 4 
 5 replacedialog::replacedialog(QWidget *parent) : QDialog(parent)
 6 {
 7     find_label         = new QLabel("替换内容");
 8     replace_label      = new QLabel("替换为");
 9     find_str           = new QLineEdit();
10     replace_str        = new QLineEdit();
11     find_next_button   = new QPushButton("查找下一个");
12     replace_one_button = new QPushButton("替换");
13     replace_all_button = new QPushButton("全部替换");
14     cancel_button      = new QPushButton("取消");
15     ignore_flag        = new QCheckBox("区分大小写");
16 
17     QGridLayout *gridly = new QGridLayout(this);
18     QVBoxLayout *vboxly = new QVBoxLayout();
19 
20     vboxly->addWidget(replace_all_button);
21     vboxly->addWidget(cancel_button);
22     gridly->addWidget(find_label, 0, 0);
23     gridly->addWidget(find_str, 0, 1);
24     gridly->addWidget(find_next_button, 0, 2);
25     gridly->addWidget(replace_label, 1, 0);
26     gridly->addWidget(replace_str, 1, 1);
27     gridly->addWidget(replace_one_button, 1, 2);
28     gridly->addWidget(ignore_flag, 2, 1);
29     gridly->addLayout(vboxly, 2, 2);
30 
31     find_str->setText("");
32     replace_str->setText("");
33     find_next_button->setEnabled(false);
34     replace_one_button->setEnabled(false);
35     replace_all_button->setEnabled(false);
36 
37     this->setMaximumSize(350, 150);
38     this->setMinimumSize(300, 100);
39 
40     connect(find_str,         &QLineEdit::textChanged, this, &replacedialog::slot_choose_str);
41     connect(cancel_button,      &QPushButton::clicked, this, &replacedialog::close);
42     connect(find_next_button,   &QPushButton::clicked, this, &replacedialog::slot_find_button_state);
43     connect(replace_one_button, &QPushButton::clicked, this, &replacedialog::slot_replace_one_button_state);
44     connect(replace_all_button, &QPushButton::clicked, this, &replacedialog::slot_repalce_all_button_state);
45 
46 }
47 
48 void replacedialog::slot_choose_str()
49 {
50     if (!find_str->text().isEmpty()) {
51         find_next_button->setEnabled(true);
52         replace_one_button->setEnabled(true);
53         replace_all_button->setEnabled(true);
54     } else {
55         find_next_button->setEnabled(false);
56         replace_one_button->setEnabled(false);
57         replace_all_button->setEnabled(false);
58     }
59 }
60 void replacedialog::slot_find_button_state()
61 {
62     if (ignore_flag->isChecked()) {
63         emit signal_findReplaceStr(find_str->text(), true);
64     } else {
65         emit signal_findReplaceStr(find_str->text(), false);
66     }
67 }
68 void replacedialog::slot_replace_one_button_state()
69 {
70     emit signal_replaceCurOneStr(find_str->text(), replace_str->text());
71 }
72 void replacedialog::slot_repalce_all_button_state()
73 {
74     if (ignore_flag->isChecked()) {
75         emit signal_replaceAllStr(find_str->text(), replace_str->text(), true);
76     } else {
77         emit signal_replaceAllStr(find_str->text(), replace_str->text(), false);
78     }
79 }
View Code

代码说明:

(1)撤销、剪切、复制、粘贴、全选最好使用QTextEdit自带的槽函数,自己去实现比较麻烦。

1     connect(menu_edit_undo,    &QAction::triggered, textEdit, &textEdit->undo);  //使用QTextEdit自带的槽函数
2     connect(menu_edit_cut,     &QAction::triggered, textEdit, &textEdit->cut);
3     connect(menu_edit_copy,    &QAction::triggered, textEdit, &textEdit->copy);
4     connect(menu_edit_paste,   &QAction::triggered, textEdit, &textEdit->paste);
5     connect(menu_edit_all,     &QAction::triggered, textEdit, &textEdit->selectAll);

(2)切换字体直接使用QFontDialog类就可以实现。

(3)打印直接使用QPrinter类就可以实现。

(4)删除功能没有QTextEdit自带的槽函数,其实可以使用剪切的功能,它们的区别在于删除之后的内容不会出现在剪贴板上。

1     textEdit->cut();
2     clipboard->setText("");

5  存在的bug

(1)替换全部功能还存在bug,会导致程序崩溃。

(2)打开和保存的的中文编码格式使用的是默认的编码,Windows下是ANSI编码,如果打开其它编码格式的文件,例如"UTF-8"编码,则会出现乱码。

其实最好的解决方式,是在读取文本的时候,判断一下编码格式,但是怎么实现还不知道,查了一些资料,也没搞定。电脑自带的记事本就有这个功能:

(3)部分功能还没有实现:自动换行、放大、缩小、状态栏显示等。

(4)另外,肯定还有一些我不知道的bug,如果网友发现了,还请指出来。

推荐阅读