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

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

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

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 }

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 }

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 }

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 }

代码说明:

(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,如果网友发现了,还请指出来。

Qt_Demo_1:实现一个简易的记事本的更多相关文章

  1. .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”

    FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...

  2. 自己来实现一个简易的OCR

    来做个简易的字符识别 ,既然是简易的 那么我们就不能用任何的第三方库 .啥谷歌的 tesseract-ocr, opencv 之类的 那些玩意是叼 至少图像处理 机器视觉这类课题对我这种高中没毕业的人 ...

  3. 基于 getter 和 setter 撸一个简易的MVVM

    Angular 和 Vue 在对Angular的学习中,了解到AngularJS 的两个主要缺点: 对于每一次界面时间,Ajax 或者 timeout,都会进行一个脏检查,而每一次脏检查又会在内部循环 ...

  4. C++-Qt【2】-实现一个简单的记事本

    用Qt实现一个简单的记事本: #include "helloqt.h" #include <qfiledialog.h> #include <qfile.h> ...

  5. 探秘Tomcat——一个简易的Servlet容器

    即便再简陋的服务器也是服务器,今天就来循着书本的第二章来看看如何实现一个servlet容器. 背景知识 既然说到servlet容器这个名词,我们首先要了解它到底是什么. servlet 相比你或多或少 ...

  6. 使用Windows Form 制作一个简易资源管理器

    自制一个简易资源管理器----TreeView控件 第一步.新建project,进行基本设置:(Set as StartUp Project:View/Toolbox/TreeView) 第二步.开始 ...

  7. [后端人员耍前端系列]AngularJs篇:使用AngularJs打造一个简易权限系统

    一.引言 上一篇博文已经向大家介绍了AngularJS核心的一些知识点,在这篇博文将介绍如何把AngularJs应用到实际项目中.本篇博文将使用AngularJS来打造一个简易的权限管理系统.下面不多 ...

  8. ENode 2.0 - 第一个真实案例剖析-一个简易论坛(Forum)

    前言 经过不断的坚持和努力,ENode 2.0的第一个真实案例终于出来了.这个案例是一个简易的论坛,开发这个论坛的初衷是为了验证用ENode框架来开发一个真实项目的可行性.目前这个论坛在UI上是使用了 ...

  9. 使用MVVM框架avalon.js实现一个简易日历

    最近在做公司内部的运营管理系统,因为与日历密切相关,同时无需触发条件直接显示在页面上,所以针对这样的功能场景,我就用avalon快速实现了一个简易日历,毕竟也是第一次造日历这种轮子,所以这里记录下我当 ...

  10. 做了一个简易的git 代码自动部署脚本

    做了一个简易的git 代码自动部署脚本 http://my.oschina.net/caomenglong/blog/472665 发表于2个月前(2015-06-30 21:08)   阅读(200 ...

随机推荐

  1. burp suite历程-安装burp suite

    安装时,捯饬了快一上午,不是jdk高了就是装上后不好使了,后来看了下以下文章,安装成功,特此记录以备不时之需: 内容拷贝至链接:https://juejin.cn/post/6844904111867 ...

  2. 设备像素、css像素、设备独立像素、dpr、ppi 之间的区别

    一.背景 在css中我们通常使用px作为单位,在PC浏览器中css的1个像素都是对应着电脑屏幕的1个物理像素 这会造成一种错觉,我们会认为css中的像素就是设备的物理像素 但实际情况却并非如此,css ...

  3. 如何将 ASP.NET Core MVC 项目的视图分离到另一个项目

    如何将 ASP.NET Core MVC 项目的视图分离到另一个项目 在当下这个年代 SPA 已是主流,人们早已忘记了 MVC 以及 Razor 的故事.但是在某些场景下 SSR 还是有意想不到效果. ...

  4. 国内chatGPT中文版网站有哪些?国内人工智能百花齐放!该如何选择?

    人工智能技术在中国的快速发展和普及,使得国内的人工智能产业日益壮大.在这些领域中,自然语言处理技术和聊天机器人已经取得了显著的进展.ChatGPT作为一种基于深度学习的聊天机器人模型,在国内得到了广泛 ...

  5. 自建Kubernetes集群如何使用弹性容器实例ECI

    简介: 虚拟节点(Virtual Node)实现了Kubernetes与弹性容器实例ECI的无缝连接,让Kubernetes集群轻松获得极大的弹性能力,而不必受限于集群的节点计算容量.您可以灵活动态的 ...

  6. Java编程技巧之样板代码

    简介: 在日常编码的过程中,可以总结出很多"样板代码",就像"活字印刷术中的"活字"一样.当我们编写新的代码时,需要用到这些"活字" ...

  7. Effective Java 在工作中的应用总结

    简介: <Effective Java>是一本经典的 Java 学习宝典,值得每位 Java 开发者阅读.笔者将书中和平日工作较密切的知识点做了部分总结. ​ 作者 | 宜秋 来源 | 阿 ...

  8. [Linux] 日志管理: rsyslog 日志格式 / 配置文件详解

    1. 日志文件格式包含以下四列: 事件时间 | 发生事件的服务器的主机名 | 产生事件的服务名或程序名 | 事件的具体信息 2. /etc/rsyslog.conf 配置文件 # 服务名称 [连接符号 ...

  9. WPF 项目文件不加 -windows 的引用 WPF 框架方式

    默认情况下的 WPF 项目都是带 -windows 的 TargetFramework 方式,但有一些项目是不期望加上 -windows 做平台限制的,本文将介绍如何实现不添加 -windows 而引 ...

  10. 经验之谈:我为什么选择了这样一个激进的缓存大Key治理方案

    一.引言 本文将结合我的一次Redis大Key的治理经验,来浅谈一下缓存大Key的治理方案选择.文中主要包括缓存大Key基础知识.大Key治理方案选择.大Key治理案例等,适合有一定开发经验的开发者阅 ...