我的 HMI 螢屏上運行著嵌入式 Qt 應用程式。我正在嘗試執行一些命令以在 cmd 中執行。我只是從 QML 呼叫這個 c 函式。每次我呼叫它時,它都會掛在 process.start() 上。有人對此類問題有任何經驗嗎?請幫忙。我已經創建了一個簡單的函式來列印日期,無論我執行什么 cmd,它仍然掛在 process.start() 上。
cmd.sprintf("date %%F' '%%X");
qDebug() << "cmd: " << cmd;
process.start("sh", QStringList()<<"-c"<<cmd);
process.waitForFinished(1000);
dtval = process.readAllStandardOutput();
process.close();
我在 Ubuntu 18.04.6LTS 平臺上使用 Qt 5.9。
uj5u.com熱心網友回復:
我做了一些進一步的故障排除,我想我在你的啟動命令中發現了一個錯誤。它應該是:
process.start("/bin/sh", QStringList()<<"-c"<<"date"<<" %F %X");
你的錯誤是你的命令date加入了它的引數,而它應該是分開的。
由于您對 QML 感興趣,因此我模擬了以下 C 應用程式,并在其中呼叫了類似的命令:
process.start("/bin/sh", ["-c", "date", " %F %X"], Process.ReadOnly);
我還讓程式分別在呼叫和/onReadyReadStandardOutput或之前監聽和等待。onReadyReadStandardErrorprocess.readAllStandardOutput()process.readAllStandardError()
為方便起見,我還映射了OpenMode標志,以便它們可以在 QML 中使用。
當你運行程式時,會有一個“Go!” 頁腳中的按鈕。當您單擊它時,它會運行process.start(),并且輸出,無論是常規輸出還是錯誤都會顯示在ListView上面。當我運行它時,我看到這樣的輸出:

#qt-process-app.pro
QT = quick
CONFIG = c 11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES = QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES = \
Process.cpp \
main.cpp
RESOURCES = qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS = target
HEADERS = \
Process.h
//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "Process.h"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
qmlRegisterType<Process>("qt.process.app", 1, 0, "Process");
QGuiApplication app(argc, argv);
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();
}
//Process.h
#ifndef __Process__
#define __Process__
#include <QProcess>
#include <QIODevice>
#include <QObject>
class Process : public QObject
{
Q_OBJECT
public:
enum OpenModeFlag {
NotOpen = QIODevice::NotOpen,
ReadOnly = QIODevice::ReadOnly,
WriteOnly = QIODevice::WriteOnly,
ReadWrite = QIODevice::ReadWrite,
Append = QIODevice::Append,
Truncate = QIODevice::Truncate,
Text = QIODevice::Text,
Unbuffered = QIODevice::Unbuffered,
NewOnly = QIODevice::NewOnly,
ExistingOnly = QIODevice::ExistingOnly
};
Q_DECLARE_FLAGS(OpenMode, OpenModeFlag)
signals:
void readyReadStandardError();
void readyReadStandardOutput();
public:
Process(QObject* parent = nullptr);
virtual ~Process();
Q_INVOKABLE void start(const QString& program, const QStringList& arguments = QStringList(), OpenMode mode = ReadWrite);
Q_INVOKABLE QByteArray readAllStandardError();
Q_INVOKABLE QByteArray readAllStandardOutput();
protected:
QProcess* m_Process;
void newProcess();
void deleteProcess();
};
#endif
//Process.cpp
#include "Process.h"
Process::Process(QObject* parent) :
QObject(parent),
m_Process(nullptr)
{
}
Process::~Process()
{
deleteProcess();
}
void Process::newProcess()
{
if (m_Process) return;
m_Process = new QProcess();
connect(m_Process, &QProcess::readyReadStandardError, this, &Process::readyReadStandardError);
connect(m_Process, &QProcess::readyReadStandardOutput, this, &Process::readyReadStandardOutput);
}
void Process::deleteProcess()
{
if (!m_Process) return;
disconnect(m_Process, &QProcess::readyReadStandardError, this, &Process::readyReadStandardError);
disconnect(m_Process, &QProcess::readyReadStandardOutput, this, &Process::readyReadStandardOutput);
delete m_Process;
m_Process = nullptr;
}
void Process::start(const QString& program, const QStringList& arguments, OpenMode mode)
{
if (!m_Process) newProcess();
m_Process->start(program, arguments, static_cast<QIODevice::OpenMode>((static_cast<int>(mode))));
}
QByteArray Process::readAllStandardError()
{
return m_Process ? m_Process->readAllStandardError() : QByteArray();
}
QByteArray Process::readAllStandardOutput()
{
return m_Process ? m_Process->readAllStandardOutput() : QByteArray();
}
//main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import qt.process.app 1.0
ApplicationWindow {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Page {
anchors.fill: parent
ListView {
id: listView
anchors.fill: parent
clip: true
model: ListModel {
id: _console
function appendMsg(msg, col) {
append({msg, col});
listView.currentIndex = count - 1;
}
function log(...params) {
console.log(...params);
appendMsg(params.join(" "), "black");
}
function error(...params) {
console.error(...params);
appendMsg(params.join(" "), "red");
}
}
ScrollBar.vertical: ScrollBar {
width: 20
policy: ScrollBar.AlwaysOn
}
delegate: Frame {
width: ListView.view.width - 20
background: Rectangle {
color: (index & 1) ? "#eee" : "#ccc"
}
Text {
width: parent.width
text: msg
color: col
}
}
}
footer: Frame {
Button {
text: qsTr("Go!")
onClicked: go()
}
}
}
Process {
id: process
onReadyReadStandardError: {
let data = readAllStandardError();
_console.error(data);
}
onReadyReadStandardOutput: {
let data = readAllStandardOutput();
_console.log(data);
}
}
function go() {
process.start("/bin/sh", ["-c", "date", " %F %X"], Process.ReadOnly);
}
}
qtquickcontrols2.conf:
[Controls]
Style=Material
[Material]
Theme=Light
和 qml.qrc:
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>qtquickcontrols2.conf</file>
</qresource>
</RCC>
uj5u.com熱心網友回復:
我發現,問題是除錯模式。如果我創建發布并按下運行按鈕(Ctlr R),那么它絕對沒問題(不是除錯按鈕,而是 QtCreator 上的運行按鈕)。無需對我的代碼進行任何更改。我不知道這會對應用程式產生什么影響。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/531682.html
