1、概述
源码放在文章末尾
该项目利用Qt+C++实现了一个简易的python编译器,类似pycharm或vsCode这样的编译器,该python编译器支持如下功能:
(1)支持编写python程序
(2)编写代码时有代码补全提示
(3)程序运行到每行时该行高亮显示
(4)可以加载python脚本执行
(5)可以在程序运行的过程中随时中断
(6)有输出窗口实时显示程序执行的状态或执行程序的打印显示等
(7)支持在界面上打断点调试,该条在开发中...
下图为Python编译器的demo演示图:
项目分析:
(1)支持编写python程序
cpp
class CodeEditor : public QPlainTextEdit
{
Q_OBJECT
public:
CodeEditor(QWidget *parent = 0);
~CodeEditor();
//行号和断点绘制
void lineNumberAreaPaintEvent(QPaintEvent *event);
//获取行号区域宽度
int lineNumberAreaWidth();
//获取位置编号
int getBlockNumberAtPosition(const QPoint& pos);
//触发断点
void toggleBreakpoint(int blockNumber);
这里通过继承QPlainTextEdit类的形式来实现在QPlainTextEdit界面上编写python脚本的功能。在界面执行run的功能时会通过信号槽的形式获取QPlainTextEdit界面上的内容并传入PyRun_SimpleString函数中执行。
(2)补全提示
补全提示的功能直接调用python的jedi库,所有通过pip安装的python库都能够通过jedi的库的补全功能提示出来,非常方便,如果要使用该功能需要在本地电脑安装:pip install jedi
(3)高亮显示
程序运行到每一行时都会高亮显示,或鼠标放在某一行也会高亮显示。
cpp
void ShowLine(int line)
{
QMetaObject::invokeMethod(g_pSmartPython, [=]() {
QTextCursor tc = g_pScriptPlainTextEdit->textCursor();
int position = g_pScriptPlainTextEdit->document()->findBlockByNumber(line - 1).position();
tc.setPosition(position, QTextCursor::MoveAnchor);
g_pScriptPlainTextEdit->setTextCursor(tc);
QList<QTextEdit::ExtraSelection> extraSelections;
QTextEdit::ExtraSelection selection;
QColor lineColor = QColor(220, 220, 220);
selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = g_pScriptPlainTextEdit->textCursor();
selection.cursor.clearSelection();
extraSelections.append(selection);
g_pScriptPlainTextEdit->setExtraSelections(extraSelections);
}, Qt::BlockingQueuedConnection);
执行每一行时都会触发ShowLine回调函数,内部获取行号并进行颜色标注该行实现高亮显示。
(4)加载python脚本
(5)随时中断运行的程序
(6)当程序运行过程中点击stop会触发
cpp
int MyTrace(PyObject* obj, PyFrameObject* frame, int what, PyObject* arg)
{
if (g_isExection)
return 0;
if (g_isAbort)
{
if (!m_isInterrupt)
{
qDebug() << "User abort.";
//PyErr_SetString(PyExc_KeyboardInterrupt, "User abort.");
if (scriptThreadState)
{
PyGILState_STATE gstate = PyGILState_Ensure();
PyThreadState_SetAsyncExc((unsigned long)scriptThreadState->thread_id, PyExc_KeyboardInterrupt);
PyGILState_Release(gstate);
}
m_isInterrupt = true;
在程序运行过程中会一直调用MyTrace函数追踪状态,当点击stop会执行PyThreadState_SetAsyncExc((unsigned long)scriptThreadState->thread_id, PyExc_KeyboardInterrupt);
该程序会强制中断python程序。
(7)断点调试程序
目前已经实现了在界面上打断点,效果如下:
断点单步调试功能还在开发中...