Unsolved run a sh shell while clicking button in QML with QT5.15.0
-
@lxy12345
I don't know anything about QML, butQProcess::start: Process is already running
means that you have a
QProcess
instance where you have set of astart()
but it has not yet completed and you have not waited for it, and now you're trying to set off a newstart()
. You either need to wait for completion of the process instance, or you need to use a new instance ofQProcess
each time. As I say, i don't know QML how to do that, but that's the cause/reason. -
Hi
Since you set the timer to repeat, it will start a new QProcess each time and
10 ms might be too short. try raising it so the other Qprocess gets change to finished.Timer {
interval: 10
repeat: true -
@mrjj
Really it ought have a handler for "process finished" signal, to be robust. I don't know how you do that from QML.OP might have a go at the naughty:
onTriggered: process.start("/bin/cat", [ "/proc/uptime" ]); process.waitForFinished();
with all the caveats. I don't know if that would work simpler.
-
@JonB
Yes i agree as guessing on execution time is bound to fail in many other cases. -
@mrjj finally, I found the reason. I should add console.log() to show output . The post is correct, thanks guys
-
@lxy12345 said in run a sh shell while clicking button in QML with QT5.15.0:
The post is correct
What post is correct?
-
@JonB http://71.254.128.33/qml/process.html This post.
-
@lxy12345
Ah, I see. Yes, that looks reasonable. However, it has no code for waiting for theQProcess::finished
signal. I admitted earlier I do not know how QML works with regard to instances. But if it does not create newQProcess
instances, and if you re-use the one instance before thecat
OS command has completed, you will get theQProcess::start: Process is already running
error you showed earlier. Since the/bin/cat /proc/uptime
completes "quickly" you may get away with it for a while.You may well be using this as just an example to play with
QProcess
, I don't know. But be aware that if you are really trying to do/bin/cat /proc/uptime
, that is a waste of time! All that does is an OS command to read the contents of the file. You would be better doing this by just opening the file/proc/uptime
and reading its content from QML, without anyQProcess
OS command at all. -
@JonB thanks for replying me. The "cat /proc/uptime" cmd is just an example. I change the cmd in my project, I use this code to open a shell which controls some peripherals.
-
Basically close/kill / terminate the process before running a new process
here an example I extracted from one of my projects as I keep "bash" process alive till closing the app itself.
so try to find where you wan to stop the process and close it.cmd.h
#pragma once #include <QProcess> #include <QVariant> class Process : public QProcess { Q_OBJECT public: explicit Process( QObject* parent = Q_NULLPTR ) : QProcess( parent ) { } // If want to use Start with arguments Q_INVOKABLE void start( const QString& program, const QVariantList& arguments ) { QStringList args; // convert QVariantList from QML to QStringList for QProcess for ( const auto& temp : arguments ) { args << temp.toString(); } QProcess::setProcessChannelMode( QProcess::MergedChannels ); QProcess::start( program, args ); } // If wan to start without arguments for Qt > 5.14 Q_INVOKABLE void start( const QString& program ) { QProcess::setProcessChannelMode( QProcess::MergedChannels ); QProcess::setProgram( program ); QProcess::start(); QProcess::open( QProcess::ReadWrite ); } Q_INVOKABLE QByteArray readAll() { return QProcess::readAll(); } Q_INVOKABLE QByteArray readLine() { return QProcess::readLine(); } // if you want to write to an active process, not fully tested! Q_INVOKABLE qint64 write( const QString& data ) { return QProcess::write( qPrintable( data ) ); } private: Q_DISABLE_COPY( Process ) };
In
main.h
qmlRegisterType<Process>( "Process", 1, 0, "Process" );
In
main.qml
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import Qt.labs.platform 1.1 import Process 1.0 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") Component.onCompleted: { py.start("bash") } // use py.close() or py.kill(0 or py.terminate() to kill the process Component.onDestruction: py.close() Process { id: py property string output: "" onStarted: print("Started") onFinished: print("Closed") onErrorOccurred: console.log("Error Ocuured: ", error) onReadyReadStandardOutput: { output = py.readAll() term.text += output } } Page { anchors.fill: parent ScrollView { id: view anchors.fill: parent TextArea { id: term textFormat: TextArea.RichText } } footer: RowLayout { Layout.fillWidth: true TextField { id: input Layout.fillWidth: true } Button { text: "Send!" property string command: input.text.trim() + "\n" onClicked: { py.write(command) term.text += ("<br /><b>" + command + " : </b>") } } } } }
I have run
cat /proc/uptime
as one program command. -
Here is an update to run multiple process as a replay to reddit QA
import QtQuick 2.15 import QtQuick.Controls 2.15 import Process 1.0 ApplicationWindow { visible: true width: 640 height: 480 title: "Run a sh file in CMD!" // prcoess to run and read .sh file Process { id: cmd property string output: "" onStarted: print("Started") // Once reading the .sh finish we will run another process to run the notify-send! onFinished: notify.start("notify-send", ["-t", "4000", "Reading .sh file Completed!"]) onErrorOccurred: console.log("Error Ocuured: ", error) onReadyReadStandardOutput: { output = cmd.readAll() txt.text += output } } // process to run firefox Process { id: fireFox property string output: "" // start notify process once we run firefox! onStarted: notify.start("notify-send", ["-t", "4000", "Starting FireFox!"]) onFinished: print("Closed") onErrorOccurred: console.log("Error Ocuured: ", error) onReadyReadStandardOutput: { output = cmd.readAll() console.log("READING CONSOLE: ", output) } } // process to run notify-osd !! Process { id: notify property string output: "" onStarted: print("Started") onFinished: print("Closed") onErrorOccurred: console.log("Error Ocuured: ", error) onReadyReadStandardOutput: { output = cmd.readAll() console.log("READING CONSOLE: ", output) } } Column { anchors.centerIn: parent TextArea { id: txt text: "" } Row { Button { text: "Run SH!" onClicked: cmd.start("/home/foxoman/file.sh") } Button { text: "Run FireFox!" onClicked: fireFox.start("firefox") } Button { text: "Run Notify" onClicked: notify.start( "notify-send", ["-t", "4000", "OSD Notify From Command Line!"]) } } } }