C++与QML编写Lua的简易集成开发环境

C++与QML编写Lua的简易集成开发环境,第1张

        好久没有写博客了,鸽了好久(咕咕咕),已经基本完成了毕业设计的全部的基本功能。下面说一下目前为止实现的功能,设计思路,方案,和一部分错误。

一.题目要求以及完成情况

        题目名称:lua语言简易集成开发环境

        课题要求:完成以下功能: 1、支持工程; 2、代码编辑; 3、即时调试。

        课题简介: 开发一个简易lua集成开发环境,完成基本的代码编辑、运行、运行结果展示及代码调试。

        目前完成情况:

        目前已经实现了本地文件的读取,修改,即时保存以及另存为功能;实现了代码编辑,代码高亮显示,行号显示,以及实现部分快捷键(譬如ctrl+c,ctrl+v);实现了代码运行,打开指定工作区的终端,实现断点运行,断点调试,显示中间变量以及此时运行的行号;集成了一个Lua的相关帮助文档,内容是根据我的Lua语言学习经验和菜鸟教程结合而成,做了个小型界面,点击按钮实现页面跳转。

工具:qt creator(c++,qml和javascript)

二.功能介绍(思路,方法,代码,及部分错误) (1)本地文件的读取,修改,即时保存以及另存为功能

        可以说,这项功能是实现课题的基础之基础,也是重中之重。在写的时候,因为明确使用的语言是c++和qm,所以当时想过主要两种思路,一方面是可以用c++的文件 *** 作功能,另一方面可以使用qml的文件 *** 作。因为本着学习新知识的目的,所以学习并使用了qml对文件的相关 *** 作。

        qml进行本地文件 *** 作主要使用的是QFile类,QFile类提供了一个用于读取和写入文件的接口,通过QFile类来实现相应的功能。同时在网上我看到有些人还会使用QTextStream类, QTextStream类为读写文本提供了一个方便的接口。但是我没有用。我直接使用了QFile中的open(),write(),read()等函数对文件的读写。同时这个转码,转类型问题,一定要谨记此时各个量的类型,在本次课题中出现了大量的QString和String的使用和转换,本地资源url类型与string的相关 *** 作,还有toUtf8等类型变幻的问题。

        代码如下:

        File.h

#ifndef QT_HUB_FILE_H
#define QT_HUB_FILE_H
#include 

class File : public QObject
{
    Q_OBJECT
public:
    File();

    Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
    Q_PROPERTY(QString text   READ text   WRITE setText   NOTIFY textChanged)

    QString source() const;
    void setSource(const QString &source);

    QString text() const;
    void setText(const QString &text);

signals:
    void sourceChanged();
    void textChanged();

private slots:
    void readFile();

private:
    QString m_source;
    QString m_text;
};

#endif // FILE_H

File.cpp

#include "File.h"
#include 
#include 

File::File()
{
    connect(this, SIGNAL(sourceChanged()), this, SLOT(readFile()));
}

void File::setSource(const QString &source)
{
    m_source = source;
    emit sourceChanged();
}

QString File::source() const
{
    return m_source;
}

void File::setText(const QString &text)
{
    QFile file(m_source);
    m_text="";
    if (!file.open(QIODevice::WriteOnly)) {
        m_text = "";
        qDebug() << "Error:" << m_source << "open failed!";
    }
    else {
        qint64 byte = file.write(text.toUtf8());
        if (byte != text.toUtf8().size()) {
            m_text = text.toUtf8().left(byte);
            qDebug() << "Error:" << m_source << "open failed!";
        }
        else {
            m_text = text;
        }

        file.close();
    }

    emit textChanged();
}

void File::readFile()
{
    QFile file(m_source);
    if (!file.open(QIODevice::ReadOnly)) {
        m_text = "";
        qDebug() << "Error:" << m_source << "open failed!";
    }

    m_text = file.readAll();
    emit textChanged();
}

QString File::text() const
{
    return m_text;
}

      main.cpp (别忘了注册类型)

#include "File.h"
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    qmlRegisterType("wenzi", 1, 0, "File");
    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

 部分经验和错误:

        (1)在实现选择本地文档读取,修改,保存,另存为关键的功能,不仅仅只有对本地文件进行读写这个功能很重要,获取指定文件的路径也十分重要。在课题中我使用了FileDialog控件,实现了打开文件选择器,在点击文件后(omAccepted),能够获得一个文件的路径,类型为url,差点给我整不会了(第一次见这种类型的变量),后来写了一个简单的JavaScript将他转化为了string赋值给了指定变量(指定file.source)代码如下:

        mian.qml

 MenuBar{//功能栏
        id:gongnenglan
        Menu{
            id:wenjian
            title: "文件"
            property string midurl: ""

            MenuItem{
                text: "打开文件"
                onTriggered: fileDialog1.open()
            }
            MenuItem{
                text: "另存为"
                onTriggered: fileDialog2.open()
            }
            MenuItem{
                text: "退出"
                onTriggered: Qt.quit()
            }

            function changeurl(FileDialog){
                wenjian.midurl=(fileDialog1.file).toString();
                var mid=(wenjian.midurl).toString();
                var midurlchange=mid.substring(8);
                file.source=midurlchange;
            }

            function savebyurl(FileDialog){
                wenjian.midurl=(fileDialog2.file).toString();
                var mid2=(wenjian.midurl).toString();
                var savebyurl1=mid2.substring(8);
                savefile.source=savebyurl1;
            }

            FileDialog {
                id: fileDialog1
                folder: StandardPaths.standardLocations(StandardPaths.DesktopLocation)[0] //默认打开桌面文件夹
                fileMode: FileDialog.OpenFile
                onAccepted: {
                    wenjian.changeurl(fileDialog1)
                    t1.text=file.text
                }
            }
            FileDialog {
                id: fileDialog2
                folder: StandardPaths.standardLocations(StandardPaths.DesktopLocation)[0] //默认打开桌面文件夹
                fileMode: FileDialog.OpenFile
                options: FileDialog.SaveFile
                onAccepted: {
                    wenjian.savebyurl(fileDialog2)
                    savefile.text=t1.text
                }
            }
        }


            File {
                id: file

                source: "F:/Luap/learn/choosepath.lua"
                onSourceChanged: {
                    t1.text=file.text
                }
            }

            File{
                id:savefile
                source: ""
            }

        与上述问题非常类似的问题还有,下面还会登场。

(2)代码编辑,代码高亮显示,行号显示,以及实现部分快捷键(譬如ctrl+c,ctrl+v)

        如果实现了本地文件读取,那么代码编辑功能的基础工作就算完成了。接下来就是选择使用什么控件来显示代码,可以用TextArea,TextEidt两种控件,带是需要实现代码编辑,那么最好使用TextEdit。选择了TextEdit作为代码显示和编辑的控件后,我们要考虑在文本变化后需要保存,加载后代码会是什么状态,同时还要考虑如果文件代码行数太多,如何显示超出显示屏范围的代码。行号显示则是非常好实现。

        最后则是代码高亮,为什么单独分出一段说,是因为这东西足足花了两周的时间才完成(明明是很简单东西)。在网上我找到了三种实现方法:使用文本块拼接,使用富文本标签,以及QSyntaxHighlighter类实现。网上有人说可以用文本块拼接,找了半天资料都不知道咋拼接。第二种方法使用富文本标签,确实也能实现功能,但是由于我此时实现了本地读取和即时保存,它会直接污染本地文件,出现类似于html的头部内容,内容全部消失。第三种方法是使用QSyntaxHighlighter类,QSyntaxHighlighter类允许定义语法突出显示规则,此外,还可以使用该类查询文档的当前格式或用户数据。在使用时到最后一定要导入文本格式,使用setDocument,就这个问题纠结了好久。

        代码如下:

        HighLighter.h

#ifndef CODEHIGHLIGHTER_H
#define CODEHIGHLIGHTER_H

#include 
#include 
#include

class HighLighter: public QSyntaxHighlighter
{
    Q_OBJECT

public:
    HighLighter(QTextDocument *parent = 0);
    Q_INVOKABLE void setDocument(QQuickTextDocument *pDoc);

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

private:
    struct HighlightingRule
    {
        QRegExp pattern;
        QTextCharFormat format;
    };
    QVector highlightingRules;

    QRegExp commentStartExpression;         //多行注释开始标识符
    QRegExp commentEndExpression;           //多行注释结束标识符

    QTextCharFormat keywordFormat;          //关键字
    QTextCharFormat classFormat;            //类
    QTextCharFormat singleLineKey;          //单行关键字
    QTextCharFormat singleLineValue;        //单行值
    QTextCharFormat singleLineCommentFormat;//单行注释
    QTextCharFormat multiLineCommentFormat; //多行注释
    QTextCharFormat quotationFormat;        //字符串标识符
    QTextCharFormat functionFormat;         //方法标识符
};

#endif // CODEHIGHLIGHTER_H

        HighLighter.cpp

#include "HighLighter.h"
#include 
#include

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

    //对于下面正则表达式,标记为紫色,类名称
    classFormat.setFontWeight(QFont::Bold);
    classFormat.setForeground(Qt::darkMagenta);
    rule.pattern = QRegExp("\\b[A-Za-z]+:\\b");
    rule.format = classFormat;
    highlightingRules.append(rule);
    rule.pattern = QRegExp("\\b[A-Za-z]+\\.\\b");
    rule.format = classFormat;
    highlightingRules.append(rule);

    //字符串,标记深红色
    quotationFormat.setForeground(Qt::darkRed);
    rule.pattern = QRegExp("\".*\"");
    rule.format = quotationFormat;
    highlightingRules.append(rule);
    rule.pattern = QRegExp("'.*'");
    rule.format = quotationFormat;
    highlightingRules.append(rule);

    //函数标记为斜体蓝色
    functionFormat.setFontItalic(true);
    functionFormat.setForeground(Qt::blue);
    rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()");
    rule.format = functionFormat;
    highlightingRules.append(rule);

    //关键字
    QStringList keywords = {
        "and", "break", "do", "else", "elseif", "end", "false",
        "for", "function", "if", "in", "local", "nil", "not", "or",
        "repeat", "return", "then", "true", "unitl", "while", "goto"
    };
    //对于下面关键字部分,标记为深蓝色
    keywordFormat.setForeground(Qt::darkBlue);
    keywordFormat.setFontWeight(QFont::Bold);
    QStringList keywordPatterns;
    for(int i=0; i= 0) {
            int length = expression.matchedLength();
            setFormat(index, length, rule.format);
            index = expression.indexIn(text, index + length);
        }
    }

    setCurrentBlockState(0);

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


    while (startIndex >= 0) {
        int endIndex = commentEndExpression.indexIn(text, startIndex);
        int commentLength=0;
        if (endIndex == -1) {
            setCurrentBlockState(1);
            commentLength = text.length() - startIndex;
        } else {
            commentLength = endIndex - startIndex
                    + commentEndExpression.matchedLength();
        }
        setFormat(startIndex, commentLength, multiLineCommentFormat);
        startIndex = commentStartExpression.indexIn(text, startIndex + commentLength);
    }
}

void HighLighter::setDocument(QQuickTextDocument *pDoc)
{
    QSyntaxHighlighter::setDocument(pDoc->textDocument());
}

        main.qml

 Flickable{
            id:flicka
            x: -352
            y: -738
            height: 660
            anchors.rightMargin: 0
            anchors.bottomMargin: 0
            anchors.leftMargin: 0
            anchors.topMargin: 0
            anchors.fill: parent
            contentWidth: t1.paintedWidth
            contentHeight: t1.paintedHeight
            clip: true
            function ensureVisible(r)
            {
                if (contentX >= r.x)
                    contentX = r.x;
                else if (contentX+width <= r.x+r.width)
                    contentX = r.x+r.width-width;
                if (contentY >= r.y)
                    contentY = r.y;
                else if (contentY+height <= r.y+r.height)
                    contentY = r.y+r.height-height;
            }

            File {
                id: file

                source: "F:/Luap/learn/choosepath.lua"
                onSourceChanged: {
                    t1.text=file.text
                }
            }

            Column{
                id:showlinecount
                property string duandian:"";
                property int duandiannum: 0;
                property string midduandian: "";
                //property int midindex: 0;
                x: 15
                y: 15
                width: 24
                height: 943

                Repeater{
                    model: t1.lineCount


                    Rectangle{
                        width: parent.width
                        height: 34
                        color: "red"

                        Rectangle{
                            id:kuang
                            anchors.fill: parent
                            width: parent.width
                            height: parent.height
                            radius: 0
                            color: "#E5E4E2"
                            //visible: fasle
                      }

                        Text{
                            id:showlinenum
                            anchors{
                                horizontalCenter: parent.horizontalCenter
                            }
                            text: index+1
                            color: "black"
                        }

                        MouseArea{
                            anchors.fill: parent
                            width: parent.width
                            height: parent.height
                            onClicked: {
                                jiajianduandian();
                             }

                            function jiajianduandian(){

                                if(kuang.visible==false)
                                {
                                    kuang.visible=true
                                    var midduandian2=showlinecount.duandian.split(" ");
                                    showlinecount.duandiannum=showlinecount.duandiannum-1;
                                    showlinecount.duandian="";
                                    //var mindindex=index

                                    for(let i=0;i

        部分经验和错误:

        (1)给TextEdit加滚动条显示超出显示屏范围的文字有两种方式,一种是在TextEdit外面套Flickable,使整个区域可以移动拖拽,另一种是在TextEdit外面套ScrollView,使其中的内容实现滚动,我这里使用的是第一种方式,在后面Lua文档处使用了第二种方式。

        (2)要及时更新t1和file的text内容,详情请看第二、三篇,因为在文件源更换时没有及时更新t1.text导致会出现切换文件时需要点击两次才能更换的情况

(3)实现了代码运行,打开指定工作区的终端,实现断点运行,断点调试,显示中间变量以及此时运行的行号

        要想实现Lua代码运行,首先肯定要安装Lua的环境。设置完Lua语言的环境变量后,测试能否运行Lua文件,Lua环境情况。打开cmd,输入lua会进入lua的交互式界面。

        在本次课题中我主要使用了c++的system()直接运行,将获取到的file.source和lua字符串拼接到一起,然后将拼接器的字符串传入system()中运行,系统控制台输出结果。

        打开终端,这个功能有四种实现方式(我知道的),第一种直接system(“cmd.exe”);第二种利用ShellExecuteA函数,通过该函数能够打开外部程序;第三种是获取当前窗口句柄,然后可以修改控制台位置,颜色,背景等;第四种可以利用QProcess类打开外部程序。此处我使用了第二种, 代码如下:

 ShellExecuteA(NULL, "open", "cmd.exe", NULL,"F:/Luap/learn/", SW_SHOW);

        断点运行和断点调试,事实上我们可以使用Lua自带的debug库来帮助我们完成功能,但是首先我们要先完成行号显示这一功能,在行号的每个所在区域添加MouseArea,时期被点击后有相应的信息让我们知道断点已被设置,设置在何处。以我目前的知识来看,想要实现断点等相关功能有三种方法,三种思路。第一种是cpp文件中导入Lua,使cpp内容能够实现对Lua相应函数,然后在cpp文件中使用c++结合相应的Lua函数实现断点;第二种是使用外部的Lua文件,在相应的工作夹中调用相应的Lua文件,利用Lua中的trace实现调用其他Lua文件中已经写好的函数,最后一种是直接在源文件中修改,在第一行加入响应函数,在后面调用。我也了解到其他调试器断点是如何实现的,有的是利用int3指令实现int3断点,还有一系列内存断点,条件断点。在这里我选择的是第三种方法。

        断点功能是如何实现的呢。如果是简单的断电运行可以通过Lua的debug库中的debug.debug()实现,它会使用户进入一个交互界面,程序运行到这里是会暂停,可以输入一些简单的调试命令,输入cont来进行下一部分程序。但是断点调试又是另一回事了,在断点调试中,我们不仅需要显示此时中间局部变量的情况,还需要显示此时在第几行,同时还需要每一行执行都需要汇报。这里我们需要首先定义自己的hook函数,以备后面调用时使用。我写的hook函数如下:

function hook(event,line) 
    i=1 --全局变量,建议大写,初始化i
    print('table of local variable:') 
    repeat local k,v = debug.getlocal(2,i) 
    print(k,v) --打印局部变量
    i = i + 1 
    until not k 
    i=1 --初始化i
    print('running location:') 
    print('event   line') 
    print(event,line) --打印行数
    debug.debug() --断点交互
end 

        在后面时就可以直接调用,使用debug.sethook()函数设置hook函数,其中debug.sethook()的三种调用方式中,我们选择"l",这样会使我们写的hook在sethook后的每一行(包括自己)都会被调用。

        代码如下:

        Run.h

#ifndef RUN_H
#define RUN_H
#include 
#include 
#include

class Run : public QObject
{
    Q_OBJECT
public:
    Q_PROPERTY(QString source)
    Q_PROPERTY(QString duandian)
    Q_PROPERTY(int duandian_num)
    Q_INVOKABLE void runLua(const QString &source);
    Q_INVOKABLE QString chuliquanwen(const QString &text);
    Q_INVOKABLE QString duandianyunxing(const QString &text,const QString &duandianji,const qint32 &duandiannum);
    Q_INVOKABLE QString shanduandian(const QString &duandian,const qint32 midindex);
    Q_INVOKABLE QString duandiantiaoshi(const QString &text,const QString &duandianji);
    //Q_INVOKABLE QString showlocal(const QString &text,const QString &duandianji,const qint32 &duandiannum);

    //QStringList duandian;
    //qint32 duandian_num;
    Q_PROPERTY(QString midtext1)

    //Q_PROPERTY(int duandian_num1)
    QString s[100];
    QString t[100];

private:
    QString midtext1;
    QString midduandian1;

};

#endif // RUN_H

        Run.cpp

 //#include
#include
#include"Run.h"
#include
#include
#include
#include

using namespace std;

void Run::runLua(const QString &source){
    string a=source.toUtf8().toStdString();
    string b="lua ";
    //string d=" >F:/Luap/learn/1.txt";
    b.append(a);
    //b.append(d);
    char c[100]={""};
    strcpy(c,b.data());
    system(c);
    //QString::fromLocal8Bit(p.readAllStandardOutput())
}

QString Run::chuliquanwen(const QString &text){
    midtext1="";
    for(int i=0;i<100;i++){
        s[i]="";
    }
    for(int i=0;i<100;i++){
        s[i]=text.section("\n",i,i);
        if(s[i]=="")
            continue;
    }
    for(int i=0;i<100;i++){
        if(s[i]=="\n"||s[i]=="\t"||s[i]=="")
            continue;
        else if(s[i].contains("function")||s[i].contains("end")||s[i].contains("--")||s[i].contains("if")||s[i].contains("else")||s[i].contains("return"))
            s[i]=s[i]+"\n";
        else
            s[i]="debug.debug()"+s[i]+"\n";
    }
    for(int i=0;i<100;i++){
        if(s[i]=="")
            continue;
        else
            midtext1=midtext1+(QString)s[i];
    }
    return midtext1;
}

QString Run::shanduandian(const QString &duandian,const qint32 midindex){

//    for(int i=0;i<100;i++){
//        t[i]="";
//    }

    for(int i=0;i<100;i++){
        t[i]=duandian.section(" ",i,i);
        if(t[i]=="")
            continue;
    }

    midduandian1="";

    for(int i=0;i<100;i++){
        if(t[i]==midindex){

        }
        else{
            midduandian1=midduandian1+" "+t[i];
        }
    }

    return midduandian1;
}

QString Run::duandianyunxing(const QString &text,const QString &duandianji,const qint32 &duandiannum){
    midtext1="";

    for(int i=0;i<100;i++){
        s[i]="";
    }

    for(int i=0;i<100;i++){
        t[i]="";
    }

    for(int i=0;i<100;i++){
        s[i]=text.section("\n",i,i);
//        if(i==0)
//            s[i]="function hook(event,line) i=1 repeat local k,v = debug.getlocal(2,i) print(k,v) i = i + 1 until not k print(event,line) debug.debug() end"+s[i];
        if(s[i]=="")
            continue;
    }

    for(int i=0;i<100;i++){
        t[i]=duandianji.section(" ",i,i);
        if(t[i]==""){
            //aa=i-1;
            break;
        }
    }

    for(int i=0;i<100;i++){
        for(int j=(duandiannum-1);j>=0;j--){
            if(i==t[j].toInt()){
                if(s[i]=="\n"||s[i]=="\t"||s[i]==""){
                    continue;
                }
                else if(s[i].contains("function")||s[i].contains("end")||s[i].contains("--")||s[i].contains("if")||s[i].contains("else")||s[i].contains("return")){
                    s[i]=s[i]+"\n";
                }
                else if(s[i].contains("debug.debug()")){
                    s[i]=s[i];
                }
                else{
                    s[i]=(QString)"i=1 repeat local k,v = debug.getlocal(1,i) print(k,v) i = i + 1 until not k debug.debug() i=1"+(QString)" "+s[i]+"\n";
                    i=0;
                    t[j]="";
                }
            }
            else if(i!=t[j].toInt()){
                if(s[i].contains("\n")){
                    s[i]=s[i];
                }
                else
                    s[i]=s[i]+"\n";
                //break;
            }

        }
    }

    for(int i=0;i<100;i++){
        if(s[i]==""){
            continue;
        }
        else if(s[i].contains("\n")){
            s[i]=s[i];
        }
        else{
            s[i]=s[i]+"\n";
        }
    }

    for(int i=0;i<100;i++){
        if(s[i]==""||s[i].contains("--"))
            continue;
        else
            midtext1=midtext1+(QString)s[i];
    }

    return midtext1;
}
QString Run::duandiantiaoshi(const QString &text,const QString &duandianji){
    midtext1="";
    QString a;
    for(int i=0;i<100;i++){
        s[i]="";
    }

    for(int i=0;i<100;i++){
        s[i]=text.section("\n",i,i);
        if(i==0){
            a=s[i];
            s[i]="function hook(event,line) i=1 print('table of local variable:') repeat local k,v = debug.getlocal(2,i) print(k,v) i = i + 1 until not k i=1 print('running location:') print('event   line') print(event,line) debug.debug() end "+a+"\n";
        }

//        if(s[i]=="")
//            continue;
    }

    for(int i=0;i<100;i++){
        t[i]="";
    }

    t[0]=duandianji.section(" ",0,0);

    for(int i=0;i<100;i++){
        if(i==t[0].toInt()){
            if(s[i]=="\n"||s[i]=="\t"||s[i]==""){
                continue;
            }
            else if(s[i].contains("function")||s[i].contains("end")||s[i].contains("--")||s[i].contains("if")||s[i].contains("else")||s[i].contains("return")){
                s[i]=s[i]+"\n";
            }
            else if(i==0){
                s[0]="function hook(event,line) i=1 print('table of local variable:') repeat local k,v = debug.getlocal(2,i) print(k,v) i = i + 1 until not k i=1 print('running location:') print('event   line') print(event,line) debug.debug() end debug.sethook(hook,'l') "+a;
            }
            else{
                s[i]=(QString)"debug.sethook(hook,'l')"+(QString)" "+s[i]+"\n";
            }
        }
        else if(i!=t[0].toInt()){
            if(s[i].contains("\n")){
                s[i]=s[i];
            }
            else
                s[i]=s[i]+"\n";
            //break;
        }
    }

    for(int i=0;i<100;i++){
        if(s[i]==""){
            continue;
        }
        else if(s[i].contains("\n")){
            s[i]=s[i];
        }
        else{
            s[i]=s[i]+"\n";
        }
    }

    for(int i=0;i<100;i++){
        if(s[i]==""||s[i].contains("--"))
            continue;
        else
            midtext1=midtext1+(QString)s[i];
    }

    return midtext1;

}

        Terminal.h

#ifndef TERMINAL_H
#define TERMINAL_H
#include 
#include 
#include
#include

class Terminal:public QObject
{
    Q_OBJECT
public:
    Q_INVOKABLE void zhongduan();
private:
    QProcess myProcess;
};

#endif // TERMINAL_H

        Terminal.cpp

#include"Terminal.h"
#include
#include
#include
#include
#include

using namespace std;

void Terminal::zhongduan(){
    ShellExecuteA(NULL, "open", "cmd.exe", NULL,"F:/Luap/learn/", SW_SHOW);

}

        部分经验和错误:

        (1)JavaScript中我QString类型的数据无法处理,直接停了,JavaScript引擎等待下一步指令,我JavaScript不是特别熟,不是特别明白,所以我在JavaScript的function外将QString类型数据先转换成String类型再处理。

        (2)由于Qt版本过高(应该是这个原因),我在使用QProcess打开cmd.exe无法d出d窗窗口,但是任务管理器显示它在,而且还在运行。

(4)集成了一个Lua的相关帮助文档,内容是根据我的Lua语言学习经验和菜鸟教程结合而成,做了个小型界面,点击按钮实现页面跳转

        为了增加我的工作量,使课设更完善一点,于是我给它加了个界面,同时还集成了一个Lua帮助文档,里面内容是我的Lua学习总结和Lua菜鸟教程。

        界面的话,我有两个思路,第一个是写在不同的qml文件中,在main.cpp加载时先加载界面的qml文件,在点击按钮后跳转到另一界面,第二个是直接写在一个qml文件中,利用窗口Window的visible属性实现页面的切换。我选择的是第一种方法,在点击按钮后还会动态加载main.qml,同时隐藏界面的窗口。

        截图如图1:

图1 界面

         点击打开文件按钮后会跳转到代码区,如图2:

                                                                  图2 代码区

        是不是感觉右边空荡荡的,那确实是,所以我就想加一个Lua的帮助文档,此时点击其他按钮会d出一个Lua文档,如下图:

         点击退出后能够关掉帮助文档,之前是因为点这个小窗口的关闭按钮会父窗口和子窗口都观点,结果加了退出按钮后点关闭按钮就只关子窗口了。

        点击上面的文本会跳转到相应的位置,这一点可以通过点击后改变光标位置(cursorPosition)来实现。同时这里TextArea使用的是ScrollView来实现文本的滚动,上下翻阅。

代码如下:

        login.qml 界面的实现

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.14
import Qt.labs.folderlistmodel 2.2
import QtQuick.Shapes 1.12
import Qt.labs.platform 1.1
import QtQuick.Window 2.14
import wenzi 1.0

Window{
    id:login
    width: 1920
    height: 1030
    visible: true
    color: "gray"
    property int filenum: 1

    Image {
        id: loginbac
        fillMode: Image.PreserveAspectFit
        width: 1920
        height: 1030
        visible: true
        source: "file:\F:\qtp\test2\loginbcak.png"
    }

    File{
        id:file1
        source: ""
    }
    
    Button{
        id:choose
        x: 1502
        y: 882
        text: "打开文件"
        onClicked: {          
            login.showmain();
            //close("qrc:/login.qml")
        }
    }
    
    function showmain(){
        panelLoader.setSource("qrc:/main.qml");
        login.visible=false;
    }
    
    Loader{
        id:panelLoader

        function setSource(source){
            panelLoader.source=source
        }
    }

    Text {
        id: biaoti1
        x: 605
        y: 136
        width: 711
        height: 80
        text: qsTr("Lua简易集成开发环境")
        font.pixelSize: 80
        font.bold: true

    }

    Rectangle {
        id: rectangle
        x: 309
        y: 260
        width: 430
        height: 662
        color: "#ffffff"

        Text {
            id: gongneng
            x: 0
            y: 8
            width: 430
            height: 60
            text: qsTr("目前已实现主要功能:")
            font.pixelSize: 40
        }

        Text {
            id: gongnenglieju
            x: 4
            y: 108
            width: 422
            height: 335
            font.pixelSize: 40
            text:qsTr("1.本地文件的读取,修\n改,存储\n2.代码运行功能\n3.代码高亮显示功能\n4.断点运行和单步调试\n功能")
        }

        Image {
            id: lua_pic1
            x: 115
            y: 435
            width: 200
            height: 200
            visible: true
            source:"file:\F:\qtp\test2\luapic.png"
        }

    }
    
}

        main.cpp 不要忘记修改首先打开的qml文件

const QUrl url(QStringLiteral("qrc:/login.qml"));

         main.qml

        Window{
            id:luawendang
            x: 1546
            y: 110
            width: 369
            height: 920
            visible: true//fasle
            color: "#ffffff"


            Rectangle{
                id:sousuokuang
                x: 0
                y: 0
                width: parent.width
                height: 40
                color: "gray"

                Button{
                    id:selectbt2
                    x:0
                    y:0
                    width: parent.width
                    height: parent.height
                    text:"退出"
                    onClicked: {
                        luawendang.visible=false
                    }
                }
            }

            File{
                id:luawendang_file
                source:"f:/Luap/learn/luahelp.txt"
            }

            Rectangle{
                id:mulu
                x:0
                y:40
                width:369
                height: 180
                Text{
                    id:jiaocoheng
                    anchors.top: parent
                    x: 0
                    y:0
                    height: 20
                    width: 180
                    text: qsTr("Lua教程")
                    MouseArea{
                        anchors.fill: parent
                        onClicked: {
                            luawendang_text.cursorPosition=0; //光标位置根据自己的情况调整
                        }
                    }
                }

                Text {
                    id: anzhuang
                    width: 180
                    x:180
                    y:0
                    text: qsTr("Lua基本语法")
                    MouseArea{
                        anchors.fill: parent
                        onClicked: {
                            luawendang_text.cursorPosition=2395;
                        }
                    }
                }
                Text{
                    id:jibenyufa
                    anchors.top: parent
                    x: 0
                    y:20
                    height: 20
                    width: 180
                    text: qsTr("Lua数据类型")
                    MouseArea{
                        anchors.fill: parent
                        onClicked: {
                            luawendang_text.cursorPosition=4150;
                        }
                    }
                }

                Text{
                    id:shujuleixing
                    anchors.top: parent
                    x:180
                    y:20
                    height: 20
                    width: 180
                    text: qsTr("Lua变量")
                    MouseArea{
                        anchors.fill: parent
                        onClicked: {
                            luawendang_text.cursorPosition=8650;

                        }
                    }
                }

                Text{

                    id:luabianliang
                    anchors.top: parent
                    x:0
                    y:40
                    height: 20
                    width: 180
                    text: qsTr("Lua循环")
                    MouseArea{
                        anchors.fill: parent
                        onClicked: {
                            luawendang_text.cursorPosition=12000;
                        }
                    }
                }
            }

            ScrollView{
                id:luawendang_scro
                x: 0
                y:220
                width: 369
                height: 690


                TextArea{
                    id:luawendang_text
                    cursorVisible: true
                    height: 690
                    x: 0
                    y:180-mulu.height
                    width: 369
                    textFormat:TextEdit.AutoText
                    text: luawendang_file.text
                    wrapMode: Text.WordWrap
                    selectByMouse: true
                }
            }
        }
    }

部分经验和错误:

        要注意ScrollView的使用,如果没必要最好有确定的位置和宽高,最早一版直接按照上面矩形框显示的x,y,高宽设置的,结果跑半天飞了,下面出现空白,最后上滚下滚一个来回后文字位置就对不上了,且无法点击文本,点了直接拉到最后。

        qml照片使用的资源路径,三种路径三种方法要牢记。

        以上就是目前的工作进度,准备写论文了,大概十几天后就会答辩,大学四年挺快的,说实话。希望我们都能有光明的未来。

        PS:大概最后还会发一期来完善一下。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/872946.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)