How to run Python script from QT creator and print output to GUI - c++

void MainWindow::on_pushButton_clicked()
{
QProcess p;
// get values from ini file
settings->setValue("EMail", ui->lineEditEMail->text());
settings->setValue("Password", ui->lineEditPassword->text());
settings->setValue("Chronological", ui->checkBox->isChecked());
settings->setValue("Current_info", ui->checkBox_2->isChecked());
settings->endGroup();
settings->sync();
// launch python code for login
QString program( "C:/projects/build-test3-Desktop_Qt_6_4_0_MinGW_64_bit-Debug/venv/Scripts/python.exe");
QStringList args = QStringList() << "index.py";
QProcess::execute( program, args );
}
I have this function that is executed after a button is clicked and I need to print the output of "index.py" in to my app. What widget should I use and how? From what I read QTextBrowser should do the trick but I'm not sure how to use it.
This is how my GUI looks like. I'd like to use to output my results somewhere in button right. I didn't add the widget yet, because I'm not sure QTextBrowser is the one I need

The widget you could use for this purpose is QTextEdit (you can set it to be read-only from the graphical user interface).
But if you want to get the output of the execution, you will need a proper instance of QProcess and call the QProcess::readAllStandardOutput() member function to get the standard output.
You may also be interested by QProcess::readAllStandardError() to get the errors in case of failure.
Edit (simple/basic example):
QProcess p;
p.start("path/to/python.exe", QStringList("script.py"));
p.waitForFinished();
QByteArray p_stdout = p.readAllStandardOutput();
QByteArray p_stderr = p.readAllStandardError();
// Do whatever you want with the results (check if they are not empty, print them, fill your QTextEdit contents, etc...)
Note: If you don't want to be blocking with QProcess::waitForFinished(), you can use a signal/slots connection on QProcess::finished() signal.

Related

showing cmd terminal in qt widgets application

I'm trying to pass some cmd commands using system() and I would like to be able to "communicate" with cmd, say I code in system("dir") in my mainwindow.cpp under my clicked function
this is what it looks like for example
void MainWindow::on_pushButton_login_clicked()
{
std::string platform_server_ip = ui->lineEdit_platform_server_ip->text().toStdString();
if (platform_server_ip == "dir"
{
QMessageBox::information(this,"Login", "all required log in details are correct");
close();
const char* c = platform_server_ip.c_str();
system(c);
system("ipconfig");
}
I would like to know why it behaves like this and if that's normal. I've included CONFIG += console
in my project file, and checked "run in terminal" (tried it also without) but it never shows me my desired outcome.
Instead what I get, is a blank terminal that pops up along side my GUI, and then when I enter "dir" in my GUI and hit enter, a cmd window pops up really fast and in less than a second, its gone. I've even tried it with system("ipconfig")andsystem ("pause")
as well as with one system command like this system("ipconfig" "&pause")
desired outcome: is just a normal execution of system("ipconfig"), followed by other system commands, that display the same result as typing them in cmd itself.
I've also tried all this in "qt Console application" and I either get the same result, or the output (what would normally be as output on cmd) is then found in "application output" of qt creator.
Is there another better way I can achieve what I want?
I'm truly a noob and would really appreciate some guidance.
You can try
system("cmd /k ipconfig");
This will open another terminal window which will stay open (k stands for keep) at the end of the command execution.
I think you don't need the CONFIG += console project setting, to achieve this. Calling system will start another process, which isn't related at all with the calling application.
If you want to start external programs from within a Qt application, you can use QProcess class, which lets you somehow interact with the started processes through standard in/out. For a very simple example, have a form with a push button and a text edit called textEdit; in the push button clicked slot:
QProcess process;
process.start("ipconfig");
process.waitForReadyRead();
ui->textEdit->setText(process.readAll());
process.waitForFinished();
This way, you won't see additional console windows, and the command output will be shown directly in your text edit.
This can be generalized in a function like this:
bool exec(QString command)
{
QProcess process;
process.start(command);
if(!process.waitForStarted())
{
return false; //the process failed to start
}
//etc...
return true;
}
Depending on whether this is not just a quick hack/tool, you can look at QProcess for more indepth control over your process so that you can read / write the child process pipes.

How to show a process result on QT?

I am using QT program test run some background process in Ubuntu.
I know how to display the Qprocess result details after the process is completed.(Using QbyteArray).
Is there any way for me to show the Qprocess progress while the process is running in the background.(ie in message box or any other such informational sub window.)
You can read process output asynchronously. For it you should connect QProcess::readyReadStandardOutput() or QProcess::readyReadStandardError() signal to your slot.
QString program = "ping";
QStringList arguments;
arguments << "google.com";
myProcess = new QProcess(parent);
connect(myProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readyR()));
myProcess->start(program, arguments);
In your slot you can read data from standart output writen by process and do what you want.
void YourClass::readyR()
{
qDebug()<<myProcess->readAllStandardOutput();
}

How to start a process in Windows using QT?

I'm trying to start a console application on Windows using QProcess's method 'start'. Official documentation says I can do it like this:
QProcess process;
process.start("C:/Windows/System32/cmd.exe");
I expect that a standard greeting message will appear in the calling application's console, but this does not happen, though the called process is running. What is wrong here?
use of bellow example :
QProcess *process = new QProcess(this);
QString program = "explorer.exe";
QString folder = "C:\";
process->start(program, QStringList() << folder);
also you can use of system() as bellow :
system("C:/Windows/System32/cmd.exe");
How about this static call?
QProcess::startDetached(FilePath,Arguments,StartInDir);
No need to create any objects!

Display QProcess output in another window

I'm using the QT Creator on Ubuntu.
I have GUI with a mainwindow and another window called "progress".
Upon clicking a button the QProcess starts and executes an rsync command which copies a folder into a specific directory. I created a textbrowser which reads the output from the rsync command. Also clicking the button causes the "progress" window to pop up.
So far so so good, now my problem.
Instead of showing the rsync output in my mainwindow i want it to be in progress.
I've tried several methods to get the QProcess into the progress via connect but that doesn't seem to work.
mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
if (ui->checkBox->isChecked()
)
m_time ="-t";
QObject parent;
m_myProcess = new QProcess();
connect(m_myProcess, SIGNAL(readyReadStandardOutput()),this, SLOT(printOutput()));
QString program = "/usr/bin/rsync";
arguments << "-r" << m_time << "-v" <<"--progress" <<"-s"
<< m_dir
<< m_dir2;
m_myProcess->start(program, arguments);
}
progress.cpp
void Progress::printOutput()
{
ui->textBrowser->setPlainText(m_myProcess->readAllStandardOutput());
}
I know it's pretty messy iv'e tried alot of things and haven't cleaned the code yet also I'm pretty new to c++.
My goal was to send the QProcess (m_myProcess) to progress via connect but that didn't seem to work.
Can you send commands like readyReadAllStandardOutput via connect to other windows (I don't know the right term )?
Am I doing a mistake or is there just another way to get the output to my progress window ?
m_myProcess is a member of the class MainWindow and you haven't made it visible to the class Progress. That's why you have the compilation error
m_myProcess was not declared in this scope
What you could do:
Redirect standard error of m_myProcess to standard output, such that you also print what is sent to standard error (unless you want to do something else with it). Using
m_myProcess.setProcessChannelMode(QProcess::MergedChannels);
Make the process object available outside MainWindow
QProcess* MainWindow::getProcess()
{
return m_myProcess;
}
Read the process output line by line in Progress. It needs to be saved in a buffer because readAllStandardOutput() only return the data which has been written since the last read.
... // somewhere
connect(window->getProcess(), SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput())
...
void Progress::printOutput(){
//bigbuffer is member
bigbuffer.append(myProcess->readAllStandardOutput();)
ui->textBrowser->setPlainText(bigbuffer);
}

My Qt code doesn't compile with "cannot call member function without object"

So i'm struggling to find a solution to this and don't know where i'm going wrong. I'm new to QT (today) and i'm not sure if i'm doing the right thing.
I'm trying to create a GUI for an already created c program (an image scraper). The image scraper works but I am trying to implement the GUI which allows a user to input a website to scrape images from into a line edit box (lineEdit), and then on click of a push button (pushButton) it takes the input text from the line edit box and uses it as the argument to run the C program in the background. Except I can't get that far because of the issue mentioned above.
Any assistance will be appreciated. Below is my code, the header and main files haven't been changed, and any changes that have been made have been done through the GUI designer over manual changes.
#include "mainwindow.h"
#include "ui_mainwindow.h"
char *arguments;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QString program = "~/Desktop/IS";
QString arguments = QLineEdit::text(); //error on this line
QProcess *myProcess = newQProcess(parent);
myProcess->start(program, arguments);
}
All errors are in on_pushButton_clicked().
A space is missing between new and QProcess.
There's no parent variable in scope. There is, of course, a parent() member of QObject. You can simply parent the process to the window itself.
You can't call QLineEdit::text without an object, as the error says. Only you know what object you need. Let's pretend for now that the object is ui->myLineEdit.
The tilde expansion is done by the shell. The kernel has no idea what a tilde is, neither does a QProcess. You need to provide full path to the executable.
The home directory is not always available from the HOME environment variable either. It should be obtained from the portable QDir::homePath().
QProcess::start() does not take two strings. It needs a list of strings as the second parameter. Since you only intend to provide one argument, it's a simple matter to wrap it up in a string list.
void MainWindow::on_pushButton_clicked()
{
QString program = QDir::homePath() + "/Desktop/IS";
QProcess *myProcess = new QProcess(this);
myProcess->start(program, QStringList(ui->myLineEdit->text()));
// The variant above is slightly shorter then the equivalent line below:
myProcess->start(program, QStringList() << ui->myLineEdit->text());
}
On your MainWindow Form just create a lineEdit somewhere called 'InputWebSite'
and then replace
QString arguments = QLineEdit::text();
With
QString arguments = ui->InputWebSite->text();