i have this code but it is not working.i am trying to update progressbar while my video is converting.video conversion is fine but progessbar is not updating
void MainWindow::on_pushButton_clicked()
{
QString alienpath="ffmpeg";
QStringList argument;
argument<<"-i"<<ui->lineEdit->text()<<"/home/suraj/a.flv";
QProcess *alien=new QProcess(this);
alien->start(alienpath,argument);
int p;
p=alien->readAll().toInt();
ui->progressBar->setMaximum(0);
ui->progressBar->setMinimum(100);
ui->progressBar->setValue(p);
}
plz help
First, your progressbar seems to be never updated after it was configured in your code. You may want to use QTimer or readyRead/readyReadStandardOutput signal connecting to some slot in MainWindow or C++11 lambda, but I'm not sure what the output will contain in each time, so I can't tell if this will work.
Second, your toInt() is likely to fail. It works only if your output contains pure number like 67; the application usually produces a lot of output. Use QRegExp or QRegularExpression (Qt5) to extract digits and convert only them. toInt() supports checking if a conversion error has occured, see documentation.
Related
In the main thread of a Gui Application I am starting a QProcess of another GUI application that will log some messages over time in stdout using fputs(). The problem is that after some time the GUI application started with QProcess will freeze because it's output is not consumed by the parent. I know that this is the problem because if I am starting the QProcess with QIODevice::NotOpen or QIODevice::Unbuffered argument, it will not get stuck but the output will never be reached.
I've tried to connect the readyRead, readyReadStandardError, readyReadStandardOutput signals of the subprocess to a slot in the parent, but for some reasons the signals are never emitted. I am also flushing the stdout after each write.
My question is how to force QProcess to send some data in real time without closing it?
The connection of the signals, (T- is a wrapper for QProcess):
process->setWorkingDirectory(workingDir);
process->start(prog, argumentsList);
process->waitForStarted();
T* reciver = new V8QProcess(process);
QObject::connect(process, &QProcess::readyRead, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardError, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardOutput, reciver, &V8QProcess::OnMessageRecieved);
The code of the subprocess that will log in stdout:
QByteArray bytes = LogMsg::getDisplayable(logMsg, 0).toUtf8();
fputs(bytes.constData(), stdout);
fflush(stdout);
The code of the OnMessageRecieved:
if (!p) { // p is the QProcess
return;
}
QByteArray output;
output.append(p->readAllStandardError()).append(p->readAll());
QString message = QString::fromStdString(output.toStdString());
This approach is working when running a shell script or other simple program.
I found out what the problem was on my case:
Because I was starting the QProcess in a std::Thread, the events(signals) that occur were skipped because std::Thread don't have a queue of events as QThread or QApplication does.
The solution that I use is:
1. Use QThread instead of std::thread
2. Call QCoreApplication::proccesEvents() from time to time.
The proper solution is to use QThread::exec() in order to create an event loop, but this approach would block the GUI Application, so in my case is no good.
I have a Qt GUI-based full application but now I need to use this application in a sort of pipeline in batch mode (console). I've tried several approaches but none of them worked as expected. Here is what I have now:
QApplication a(argc, argv);
MyMainWindow *w = new MyMainWindow();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
a.exec();
Here is what I need:
QApplication a(argc, argv);
QString project_path = argv[1];
MyMainWindow *w = new MyMainWindow();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
w->loadPrjFile(project_path);
w->analyze();
w->exportResults();
a.exec();
So, basically what I need is to allow the application to get the project_path through command line (not file dialogs) and execute the methods that a user would usually follow using the GUI. The problem is that these methods should block, in the sense that one should wait for the previous one to finish.
The application itself should block, in the sense that, when executed in the shell, it should wait for the whole execution to finish before quitting. As it should work as a console application the interface should also be hidden.
If you know a way to do that, I would really appreciate a code sample of how this can be done.
The problem you have is that you're trying to develop a console app, but still using Gui widgets, such as QMainWindow. You need to start by separating the Gui classes from everything else in your main project.
I recommend you create a class, derived from QObject, which handles the processing of what you need; loadPrjFile, analyze and exportResults.
Then use an instance of this new class in your MainWindow for the GUI project and use it directly for the console project.
class Worker : public QObject
{
Q_OBJECT
public:
void loadPrjFile(const QString& path);
void analyze();
void exportResults();
};
class MyMainWindow : QMainWindow
{
private:
Worker m_pWorkerObject;
};
If you're developing a console project that doesn't need a Gui, you can use QCoreApplication, instead of QApplication.
Be aware that calling app.exec() starts Qt processing messages, so you only need that if you need a message loop to process events, which may not be the case for a console application, depending on what your app does.
This answer shows the solution that I came up with after a while. I'll put it here because it can be useful to others. The code looks like this:
QApplication a(argc, argv);
QString project_file = argv[1];
MyMainWindow *w = new MyMainWindow();
w->setVisible(false);
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
w->setBatchMode(true);
QObject::connect(w,SIGNAL(loadingFinished()),w,SLOT(analyze()));
QObject::connect(w,SIGNAL(analysisFinished()),w,SLOT(exportResults()));
QObject::connect(w,SIGNAL(exportingFinished()),w,SLOT(close()));
w->loadPrjFile(project_file);
a.exec();
The main considerations are:
w->setVisible(false) was used to hide the MainWindow as also pointed out by #Dissident penguin.
w->setBatchMode(true) was used to set a class variable that is used to supress all the other dialogs throughout the code as also pointed out by #Dissident penguin. Inside the functions I just wrapped the dialog code with an if statement like:
if (!_batchMode) { //show dialog }
Meeting the requirement of sequencial execution was not that easy. I had to create two signals: loadingFinished(), analysisFinished() and exportingFinished(). Then I emit them in the end of loadPrjFile(), analyze() and exportResults() functions respectively. This way I garantee that they are executed in order and that one waits for the other. This is needed because slots are executed asynchronously in Qt.
Finally, I could not take out the method a.exec() because if I do that the program doesn't run properly. I think this is because I'm still using the GUI, it's just hidden. This way, a.exec() is still needed.
To read arguments from the command line in an app with a GUI, you can use the global pointer qApp anywhere in your code. This is particularly useful if you want, for example, to be able to associate your GUI application with a file type, since the file name will be pipleined by the OS to your app (at least it works in Windows).
You can see a detailed answer I gave to the same question in this thread, together with the links to the appropriate documentation, which for some reason is not in the latest versions of Qt.
The second part is not that easy.
You can use w->setVisible(false) before calling a.exec(); to hide your main window, but you will have, to the best of my knowledge, to modify every method that has a dialogue to either react to the command line argument if detected, and disable the dialogue, or use the normal dialogues if no related arguments are detected.
If you only need to call methods of the main window that have no interaction with the user, then it won't be that much work, and you might get away with not calling a.exec (if and only if no part of your code is using signals and slots in batch mode), which in reality starts the main loop of the GUI and won't be needed in that case.
Something like this might work:
QApplication a(argc, argv);
MyMainWindow *w = new MyMainWindow();
if(1 < qApp->arguments().count()) //Command line arguments detected
{
QString project_path = qApp->arguments().at(1);
w->loadPrjFile(project_path);
w->analyze();
w->exportResults();
}
else //No command line arguments detected
{
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
a.exec();
}
If, on the other hand, the functions loadPrjFile(), analyze(); and exportResults() are slots and not, as your code suggests, methods of your main window, they will not be called sequentially and you will have no choice but using signals and slots so each function can notify the next one that it finished its job, and therefore will have to call a.exec
I have a QTableWidget with row selection, and i'm trying to treat 3 signals:
cellClicked
cellDoubleClicked
customContextMenuRequested
Things seem to be fine in code: i had in mind the connect syntax, type params are correct and match, etc; and to be more specific, i "know" that the code is correct because i have the following situation:
if i connect the 3 signals to their respective slots, only the single click and the context menĂº work.
if i connect just one signal each time i compile the code and i run the program, that signal is working well (for the 3 of them).
if i connect the single click signal and the context menu, commenting the connect macro for the double click, they work well. Same for double click and context menu.
BUT if i connect the single click and the double click, the double click is not being treated by my custom slot.
Just to clarify, each signal has a different slot, and as i meantioned above, they work well if i just connect one of them and comment the other 2 in code.
So my question is:
is there any bug with the cellClicked and cellDoubleClick working simultaneously? do i have to set some flag, attribute or whatever that belongs to the QTableWidget?
I'm running out of ideas, thanks for the help!
And also, maybe the code should help:
table and slots declaration:
QTableWidget * table;
public slots:
void tableChange(int row, int column);
void tableChangeDbl(int row, int column);
void PopupMenuTableShow(const QPoint &);
the connects:
connect(table, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(tableChangeDbl(int, int)));
connect(table, SIGNAL(cellClicked(int, int)), this, SLOT(tableChange(int, int)));
connect(table, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(PopupMenuTableShow(const QPoint &)));
I've got a QT problem.
I want to make my program stop at place where I define, let`s say for 3 seconds. I couldn't manage to do that. I need that because earler my program generates file and it is used by a program which I call a bit later. Problem is, that file doesn't seem have enough time to create. My code looks like this:
void MainWindow::buttonHandler()
{
QFile ..... (creating a text file);
//Making a stream and writing something to a file
//A place where program should pause for 3 seconds
system("call another.exe"); //Calling another executable, which needs the created text file, but the file doesn`t seem to be created and fully written yet;
}
Thanks in advance.
Some possibilities:
1) Use another slot for the things to do after the sleep:
QTimer::singleShot(3000, this, SLOT(anotherSlot());
...
void MyClass::anotherSlot() {
system(...);
}
2) Without another slot, using a local event loop:
//write file
QEventLoop loop;
QTimer::singleShot(3000, &loop, SLOT(quit()) );
loop.exec();
//do more stuff
I would avoid local event loop and prefer 1) though, local event loops can cause a plethora of subtle bugs (During the loop.exec(), anything can happen).
Try void QTest::qSleep ( int ms ) or void QTest::qWait ( int ms )
Looking into the source of these functions is also useful if you do not want the overhead of QTest.
More info at http://doc.qt.io/qt-5/qtest.html#qSleep
Maybe you just need to close the written file before you call the other program:
QFile f;
...
f.close();
(This also flushes internal buffers so that they are written to disk)
For signal and slot of below type
signals:
void textChanged(const QString &);
public slots:
void setText(const QString & text)
the type of argument of textChanged and setText seems to work invarable of const and &. Does the constant and reference qualification make any difference compared to just using QString ?
QObject::connect(a,SIGNAL(textChanged(QString)),b,SLOT(setText(QString)));
QObject::connect(a,SIGNAL(textChanged(const QString &)),b,SLOT(setText(const QString &)));
EDIT:
I did not notice the output window showing error messages when there is incompatible type being used in SIGNAL or SLOT. I thought the signal slot mechanism is capable of detecting argument type error at compile time.
Qt checks a normalized signature, meaning
Normalization reduces whitespace to a
minimum, moves 'const' to the front
where appropriate, removes 'const'
from value types and replaces const
references with values.
Disclaimer: My qt is rather rusty, but the signal/slot mechanism is still just C++ function calls. If the signal/slot mechanism actually copies objects into internal storage, my apologies (you'll need to check the Qt pages, there's a big one on signals/slots afaik) - as the bits below will only be relevant in a C++ context, not in a C++ + Qt context.
If you leave out the reference, the string will be copied (and having the const would not matter, any changes made to it will remain in the function alone).
If you leave in the reference but take out the const, you allow the method to modify the string that you give it. They both work, but do different things to the object you pass (amount of copying/possibility of retaining changes).
I suggest you read the following resources:
(on const correctness) https://isocpp.org/wiki/faq/const-correctness
(on references) https://isocpp.org/wiki/faq/references
to understand exactly what passing a parameter is and how
void foo(const A&)/
void foo(const A)/
void foo(A&)/
void foo(A)
are all different.