如何利用Qt创建一个IDE

Wzhrdx 发布于

新建一个Qt项目

新建一个Qt Widgets Applications项目
Details不勾选Generate form
图1

一直点下一步
Kits里勾选MinGw 32-bitMinGW 64-bit
mainwindows.h里修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

#ifndef MAINWINDOW_H
#define MAINWINDOW_H


#include <QMainWindow>

#include <QTextEdit> //文本

QT_BEGIN_NAMESPACE
class QTextEdit;
QT_END_NAMESPACE


class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);

private:

QTextEdit *editor; //中央XextEdit控件

private slots:
void setupEditor();
};


#endif // MAINWINDOW_H


mainwindows.cpp里修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29


#include <QtWidgets>

#include "mainwindow.h"


MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{

setupEditor();
setCentralWidget(editor);
setWindowTitle(tr("IDE"));

}

void MainWindow::setupEditor()
{
QFont font;
font.setFamily("Courier");
font.setFixedPitch(true);
font.setPointSize(10);

editor = new QTextEdit;
editor->setFont(font);

}

main.cpp里修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.resize(640, 512);
window.show();
return app.exec();
}


添加状态栏

mainwindows.h里修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

#ifndef MAINWINDOW_H
#define MAINWINDOW_H


#include <QMainWindow>

#include <QTextEdit> //文本
#include <QMenu> //加入菜单
#include <QMenuBar> //加入菜单栏
#include <QAction> //加入菜单栏
#include <QFileDialog>

QT_BEGIN_NAMESPACE
class QTextEdit;
QT_END_NAMESPACE


class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);

private:

bool is_changed;
QTextEdit *editor; //中央XextEdit控件

QString fileName; //当前文件的名字


//文件菜单
QMenu *file_menu; //文件菜单
QAction *new_file; //新建文件菜单项
QAction *open_file; //打开文件菜单项
QAction *save_file; //保存文件菜单项
QAction *exit_file; //退出文件菜单项

//编辑菜单
QMenu *edit_menu; //编辑菜单
QAction *copy_edit; //编辑菜单的复制按钮
QAction *paste_edit;
QAction *cut_edit;
QAction *allselect_edit;

QMenu *help_menu; //帮助菜单

//编译菜单
QMenu *comp_menu; //编译菜单
QAction *comp_comp; //编译按钮
QAction *run_comp; //运行按钮


void precomp();

private slots:
void on_exit();//在QT编辑环境,安装ALT+ENTER,出现提示再按一次回车
void on_open(const QString &path = QString());
void on_save();
void on_new();
void on_copy();
void on_paste();
void on_cut();
void on_allselect();
void on_changed();
void on_comp();
void on_run();
void setupEditor();
void setupFileMenu();
void setupHelpMenu();
void about();
};


#endif // MAINWINDOW_H


mainwindows.cpp里修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258


#include <QtWidgets>

#include "mainwindow.h"


MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setupFileMenu();
setupHelpMenu();
setupEditor();

setCentralWidget(editor);
setWindowTitle(tr("IDE"));


//文本内容在保存前是否发生变动
is_changed = false;

//添加菜单项,并为其设定快捷键
//【文件菜单栏】
file_menu = this->menuBar()->addMenu("文件");
new_file = new QAction("新建文件",this); //第一个参数是菜单项的文字,第二个参数是指向主体的指针
new_file ->setShortcut(tr("ctrl+n")); //设定快捷键
file_menu ->addAction(new_file); //关联 菜单栏 与 菜单项
file_menu ->addSeparator(); //在文件下拉菜单上面显示一个分隔符

open_file = new QAction("打开文件",this);
file_menu ->addAction(open_file);
open_file ->setShortcut(tr("ctrl+o"));

save_file = new QAction("保存文件",this);
file_menu ->addAction(save_file);
save_file ->setShortcut(tr("ctrl+s"));

exit_file = new QAction("退出",this);
file_menu ->addAction(exit_file);



//【编译菜单栏】
comp_menu = this->menuBar()->addMenu("编译");
comp_comp = new QAction("编译",this); comp_menu->addAction(comp_comp);
run_comp = new QAction("运行",this); comp_menu->addAction(run_comp);

//【帮助菜单栏】
help_menu = this->menuBar()->addMenu("帮助");



//【鼠标事件与函数关联】当鼠标点击exit_file 菜单的时候,执行on_exit()函数
connect(exit_file,SIGNAL(triggered()),this,SLOT(on_exit()));
connect(open_file,SIGNAL(triggered()),this,SLOT(on_open()));
connect(save_file,SIGNAL(triggered()),this,SLOT(on_save()));
connect(new_file,SIGNAL(triggered()),this,SLOT(on_new()));
connect(copy_edit,SIGNAL(triggered()),this,SLOT(on_copy()));
connect(paste_edit,SIGNAL(triggered()),this,SLOT(on_paste()));
connect(cut_edit,SIGNAL(triggered()),this,SLOT(on_cut()));
connect(allselect_edit,SIGNAL(triggered()),this,SLOT(on_allselect()));
connect(editor,SIGNAL(textChanged()),this,SLOT(on_changed()));//当文本内容发生变化时,触发on_changed函数
connect(comp_comp,SIGNAL(triggered()),this,SLOT(on_comp()));//当文本内容发生变化时,触发on_changed函数
connect(run_comp,SIGNAL(triggered()),this,SLOT(on_run()));//当文本内容发生变化时,触发on_changed函数

}



void MainWindow::on_open(const QString &path)
{
QString fileName = path;

if (fileName.isNull())
fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", "C++ Files (*.cpp *.h)");

if (!fileName.isEmpty()) {
QFile file(fileName);
if (file.open(QFile::ReadOnly | QFile::Text))
editor->setPlainText(file.readAll());
}
}

void MainWindow::setupFileMenu()
{
QMenu *fileMenu = new QMenu(tr("&File"),this);
menuBar()->addMenu(fileMenu);
//【编辑菜单栏】
edit_menu = this->menuBar()->addMenu("编辑");
copy_edit = new QAction("复制",this);
copy_edit ->setShortcut(tr("ctrl+c"));
edit_menu ->addAction(copy_edit);

paste_edit = new QAction("粘贴",this);
paste_edit ->setShortcut(tr("ctrl+v"));
edit_menu ->addAction(paste_edit);

cut_edit = new QAction("剪切",this);
cut_edit ->setShortcut(tr("ctrl+x"));
edit_menu ->addAction(cut_edit);

allselect_edit = new QAction("全选",this);
allselect_edit ->setShortcut(tr("ctrl+a"));
edit_menu ->addAction(allselect_edit);

}

void MainWindow::setupEditor()
{
QFont font;
font.setFamily("Courier");
font.setFixedPitch(true);
font.setPointSize(10);

editor = new QTextEdit;
editor->setFont(font);



QFile file("mainwindow.h");
if (file.open(QFile::ReadOnly | QFile::Text))
editor->setPlainText(file.readAll());
}
void MainWindow::about()
{
QMessageBox::about(this, tr("About IDE"),
tr("version0.0.1"));
}



void MainWindow::setupHelpMenu()
{
QMenu *helpMenu = new QMenu(tr("&Help"), this);
menuBar()->addMenu(helpMenu);

helpMenu->addAction(tr("&About"), this, SLOT(about()));
}


void MainWindow::precomp()//预编译
{
FILE *p = fopen(fileName.toStdString().data(),"r");
if(p == NULL) return ;
QString cmd = fileName +".c";
FILE *p1 = fopen(cmd.toStdString().data(),"w");
if(p1 == NULL) return ;
QString str;
while(!feof(p))
{
char buf[1024] = {0};
fgets(buf,sizeof(buf),p);
str += buf;
}

str.replace("包含","#include");
str.replace("主函数","main");
str.replace("整数","int");
str.replace("开始","{");
str.replace("收工","}");
str.replace("。",";");
str.replace("返回","return");
str.replace("打印","printf");
str.replace("输入输出","<stdio.h>");
str.replace("无声的等待...","getchar()");

fputs(str.toStdString().data(),p1);
fclose(p);
fclose(p1);
}

//程序退出
void MainWindow::on_exit()
{
this ->close();
}

//保存文件
void MainWindow::on_save()
{
if(fileName.isEmpty())
{
fileName = QFileDialog::getSaveFileName(this,"保存文件");
}
if(!fileName.isEmpty())
{
FILE *p = fopen(fileName.toStdString().data(),"w");
if(p == NULL) return ;
QString str = editor->toPlainText();
fputs(str.toStdString().data(),p);
fclose(p);
}
}
//新建文件
void MainWindow::on_new()
{
if(is_changed == true)
{
on_save();
is_changed = false;
}
fileName = "";
editor->setText("");
}
//IDE的复制功能
void MainWindow::on_copy()
{
editor->copy();
}

void MainWindow::on_paste()
{
editor->paste();
}

void MainWindow::on_cut()
{
editor->cut();
}

void MainWindow::on_allselect()
{
editor->selectAll();
}

void MainWindow::on_changed()
{
is_changed = true;
}
//编译并运行按钮
void MainWindow::on_comp()
{
if (is_changed == true)//在点击编译按钮,如果文本内容发生变化,就自动保存
{
on_save();
}
precomp();//自动以预编译
QString cmd;
const char *s = fileName.toStdString().data();
cmd.sprintf("gcc -o %s.exe %s.c",s,s);
system(cmd.toStdString().data());//先编译

//如何删除那个临时文件呢
cmd = fileName.replace("/","\\") + ".c";
remove(cmd.toStdString().data());


cmd = fileName + ".exe";
system(cmd.toStdString().data());//再运行
}

void MainWindow::on_run()
{
QString cmd;
cmd = fileName + ".exe";
system(cmd.toStdString().data());
}

添加浮动窗口

mainwindows.cpp里修改

1
2
3
4
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
}

在这里面添加浮动窗口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
....#省略前面的代码
connect(run_comp,SIGNAL(triggered()),this,SLOT(on_run()));//当文本内容发生变化时,触发on_changed函数
#在上一行代码后添加如下内容
//浮动窗口---------------------------------------------------------------------
QDockWidget *dock = new QDockWidget(this);
addDockWidget(Qt::RightDockWidgetArea, dock);

//给浮动窗口添加控件
QTreeView *treeView = new QTreeView(this);
dock->setWidget(treeView);
}

给代码添加高亮

在文件上右键选择add new...
图2

图3

class name命名为highlighter
.pro文件修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
QT += widgets
requires(qtConfig(filedialog))

HEADERS = highlighter.h \
mainwindow.h
SOURCES = highlighter.cpp \
mainwindow.cpp \
main.cpp

# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/richtext/syntaxhighlighter
INSTALLS += target


highlighter.h的代码修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

#ifndef HIGHLIGHTER_H
#define HIGHLIGHTER_H

#include <QSyntaxHighlighter>
#include <QTextCharFormat>
#include <QRegularExpression>

QT_BEGIN_NAMESPACE
class QTextDocument;
QT_END_NAMESPACE


class Highlighter : public QSyntaxHighlighter
{
Q_OBJECT

public:
Highlighter(QTextDocument *parent = 0);

protected:
void highlightBlock(const QString &text) override;

private:
struct HighlightingRule
{
QRegularExpression pattern;
QTextCharFormat format;
};
QVector<HighlightingRule> highlightingRules;

QRegularExpression commentStartExpression;
QRegularExpression commentEndExpression;

QTextCharFormat keywordFormat;
QTextCharFormat classFormat;
QTextCharFormat singleLineCommentFormat;
QTextCharFormat multiLineCommentFormat;
QTextCharFormat quotationFormat;
QTextCharFormat functionFormat;
};


#endif // HIGHLIGHTER_H

highlighter.cpp里的代码修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

#include "highlighter.h"


Highlighter::Highlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent)
{
HighlightingRule rule;

keywordFormat.setForeground(Qt::darkBlue);
keywordFormat.setFontWeight(QFont::Bold);
QStringList keywordPatterns;
keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b"
<< "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b"
<< "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b"
<< "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b"
<< "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b"
<< "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b"
<< "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b"
<< "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b"
<< "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b"
<< "\\bvoid\\b" << "\\bvolatile\\b" << "\\bbool\\b";
foreach (const QString &pattern, keywordPatterns) {
rule.pattern = QRegularExpression(pattern);
rule.format = keywordFormat;
highlightingRules.append(rule);

}

classFormat.setFontWeight(QFont::Bold);
classFormat.setForeground(Qt::darkMagenta);
rule.pattern = QRegularExpression("\\bQ[A-Za-z]+\\b");
rule.format = classFormat;
highlightingRules.append(rule);

singleLineCommentFormat.setForeground(Qt::red);
rule.pattern = QRegularExpression("//[^\n]*");
rule.format = singleLineCommentFormat;
highlightingRules.append(rule);

multiLineCommentFormat.setForeground(Qt::red);

quotationFormat.setForeground(Qt::darkGreen);
rule.pattern = QRegularExpression("\".*\"");
rule.format = quotationFormat;
highlightingRules.append(rule);

functionFormat.setFontItalic(true);
functionFormat.setForeground(Qt::blue);
rule.pattern = QRegularExpression("\\b[A-Za-z0-9_]+(?=\\()");
rule.format = functionFormat;
highlightingRules.append(rule);

commentStartExpression = QRegularExpression("/\\*");
commentEndExpression = QRegularExpression("\\*/");
}

void Highlighter::highlightBlock(const QString &text)
{
foreach (const HighlightingRule &rule, highlightingRules) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}

setCurrentBlockState(0);

int startIndex = 0;
if (previousBlockState() != 1)
startIndex = text.indexOf(commentStartExpression);


while (startIndex >= 0) {

QRegularExpressionMatch match = commentEndExpression.match(text, startIndex);
int endIndex = match.capturedStart();
int commentLength = 0;
if (endIndex == -1) {
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
} else {
commentLength = endIndex - startIndex
+ match.capturedLength();
}
setFormat(startIndex, commentLength, multiLineCommentFormat);
startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
}
}



mainwindow.h里添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//添加include文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "highlighter.h"

#include <QMainWindow>

#include <QTextEdit> //文本
#include <QMenu> //加入菜单
#include <QMenuBar> //加入菜单栏
#include <QAction> //加入菜单栏
#include <QFileDialog>


找到private:添加

1
Highlighter *highlighter;

如图
图4

修改mainwindow.cpp

1
2
highlighter = new Highlighter(editor->document());

位置如图
图5