为 Windows 上现有的基于控制台的应用程序创建 QT 应用程序作为 GUI

2021-12-09 00:00:00 shell user-interface qt command-line c++

我正在尝试使用 Qt 为要在 Windows 命令行中运行的现有应用程序设置 GUI.这不仅仅是运行应用程序system() 命令,但我需要通过命令行与现有应用程序交互.

i'm trying to set up a GUI with Qt for an existing application which is meant to be run in the windows commandline. It's not just running the app with the system() command, but i need to interact with the existing application via command line.

当我启动现有的可执行文件时,system() 命令会阻止 GUI.如何在后台运行此可执行文件并通过我自己的 GUI 元素(例如按钮)触发一些输入?

The system() command blocks the GUI when i start the existing executable. How can i run this executable in the background and trigger some inputs via my own GUI-Elements such as a button?

我想为我的一些同事简化这个命令行工具的使用.

I want to simplify the usage of this command line tool for some of my colleagues.

它主要用于windows.

It would be mainly used on windows.

感谢您的帮助.

推荐答案

我找到了满足我需求的解决方案并且可以做我想做的事情.. 其实我有点失望.我认为它会更复杂.

I found a solution for my needs and can do what i want to do.. Actually i'm a bit disappointed. I thought it would be something more complex.

首先我得说这是一个 QtQuick 应用程序 .. 也许我应该早点说.

First i have to say it's an QtQuick Application .. Maybe i should have said that earlier.

我只是将流程功能外包给另一个班级.此类通过 qmlRegisterType<>() 函数传递给 QML.我将来自进程的一些信号 ( QProcess ) 连接到我自己类中的插槽,并编写了自己的函数来处理从控制台应用程序读取数据和向控制台应用程序写入数据.通过 QML-onClicked 事件,我可以将参数和字符串传递给控制台应用程序.通过一些应用程序逻辑,我可以处理输入/输出请求和时间.

I simply outsourced the process functions to another class. This class is passed to QML via the qmlRegisterType<>() function. I connected some signals from the process ( QProcess ) to slots in my own class and wrote my own functions to handle reading/writing data from and to the console application. With the QML-onClicked events i can pass my parameters and strings to the console app. And with some application logic i can handle the in/out requests and timings.

WrapperClass.h

class WrapperClass: public QObject
{
    Q_OBJECT

public:
    explicit WrapperClass(QObject *parent = nullptr);

    QProcess *process;
    QString str_proc_output;

    Q_INVOKABLE void startProcess();
    Q_INVOKABLE void stopProcess();

    Q_INVOKABLE QString getOutput();
    Q_INVOKABLE void writeByte(QString str);


    Q_INVOKABLE QString getAllOutput();
private:

signals:

public slots:
    void mReadyRead();
    void mReadyReadStandardOutput();
    void mFinished(int code);
    void mBytesWritten(qint64 written);

};

WrapperClass.cpp

WrapperClass::WrapperClass(QObject *parent) : QObject(parent)
{
    process = new QProcess();
    process->setProgram("untitled.exe");
    process->setProcessChannelMode(QProcess::MergedChannels);

    str_proc_output = "";

    connect(process, SIGNAL(readyRead()), this, SLOT(mReadyRead()));
    connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(mReadyReadStandardOutput()));
    connect(process, SIGNAL(finished(int)), this, SLOT(mFinished(int)));
    connect(process, SIGNAL(bytesWritten(qint64)), this, SLOT(mBytesWritten(qint64)));

}

void WrapperClass::startProcess() {
    if(process->state() == QProcess::Running) {
        stopProcess();
    } else {
        process->open(QProcess::ReadWrite);
    }
}

void WrapperClass::stopProcess() {
    process->close();
}



QString WrapperClass::getOutput() {
    return str_proc_output;
}


QString WrapperClass::getAllOutput() {
    QString str = process->readAll();

    std::cout << str.toStdString() << std::endl;
    return str;
}


void WrapperClass::writeByte(QString str) {

    char cArr[str.length()] = {};

    memcpy(cArr, str.toStdString().c_str(), str.length());

    QByteArray arr = QByteArray(cArr, -1);
    process->write(arr);
}




void WrapperClass::mReadyRead() {
    QString s = QString(process->readAll());

    std::cout << "ReadyRead: " << s.toStdString() << std::endl;
    str_proc_output = s;
}

void WrapperClass::mReadyReadStandardOutput() {
    QString s = QString(process->readAllStandardOutput());

    std::cout << "ReadyReadStandardOutput: " << s.toStdString() << std::endl;

}

void WrapperClass::mFinished(int code) {
    std::cout << "Process finished! (" << code << ')' << std::endl;
}


void WrapperClass::mBytesWritten(qint64 written) {

    std::cout << "Bytes written: " << written << std::endl;

}

Main.cpp

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<WrapperClass>("com.example.WrapperClass", 0, 1, "WrapperClass");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

通过将 Cpp-Class 注册到 QML,我能够通过来自 QML-MouseAreaButton 的 Click-Events 触发读/写功能.

With registering the Cpp-Class to QML i'm able to trigger the read/write functions via Click-Events from QML-MouseArea or Button.

相关文章