Can't update Text Edit Text QT - c++

I'm having an issue. My textEditBox doesn't seem to be updating when my Addtext function is called.
Here's my Addtext:
void CTextBox::AddText(QString string, QString spriteString)
{
textBrowser->setText(string + spriteString);
update();
}
Another class then calls the function and it should add text to the textbox but it doesn't.

How do you call CTextBox::AddText()? update() only schedules a paintEvent() for later, when the program returns to the event loop. That means that
you actually need to have an event loop, ie. at some point you need to call qApp->exec();
you need to allow the programm some time to qApp->processEvents() (insert that after update()), if you want any paining done within a blocking while() {...} or something like that.
Edit: Come to think of it, you shouldn't even need to call update() nor processEvents() if your program returns to the event loop some time after AddText, so there really seems to be an issue with the event loop. Post your main.cpp, will you?

Here is a trivial example of what it sounds like you are trying to do. Maybe you can see where your design differs?
Notice: no explicit update() is needed. I think that's a red herring. I think it far more likely that (1) you are somehow calling your AddText method with empty strings, or (2) your real text edit is a different variable, and have somehow created two of them and are updating one that just exists in memory and was never added to a layout. Perhaps the code of your FileLoaderQT would help? (You can edit your question rather than posting in comments.)
#include <QtGui>
int main(int argc, char **argv) {
QApplication app(argc, argv);
QMainWindow w;
QTextEdit *edit = new QTextEdit;
w.setCentralWidget(edit);
edit->setText("Hello world!");
w.show();
edit->append("Hello world again!");
return app.exec();
}

Related

QTCreator 5.0.2, parallel run of two window, C++

I went throught suggested "questions" about my problem. However neither does not solve it.
I program two windows. The second window is opening from first window. I need active the both windows, however to start the first window(MainWindow) I use:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.setWindowModality(Qt::NonModal);
return a.exec();
}
As was mentioned, the second window is started from pushButton, which is situated in first window(MainWindow) by same way.
void MainWindow::on_pushButton_2_clicked()
{
Graphics gr;
gr.setWindowModality(Qt::NonModal);
gr.exec();
}
I changed modality to NonModal,however the problem is without change. The Non-Modal mean:"The window is not modal and does not block input to other windows." <- from documentation
By documentation is recommended to avoid used .exec(). The alternatives are .show() and open(), which i tried. After the modification, the second window is shut down immediately after opening. after open immediately shut down.
Do you have any idea, how to solve that?
Graphics gr; defines a local variable, so the object is destructed as soon as it goes out of scope (at the end of your function).
In Qt, the typical approach is to work with pointers to Qt widgets (and, more generally, QObjects), but have a parent for each – the parent will clean it up.
Try this instead:
auto gr = new Graphics(this);
gr->setWindowModality(Qt::NonModal); // this is the default, no need for this call
gr->show();
This way the window will survive until your main window is destructed. In Qt there is also a mechanism for widgets/objects to self-destruct:
this->deleteLater();
So for example if you want to close and cleanup gr you can use that mechanism (you could also store gr as a member and call gr->deleteLater().

Qt must construct QApplication before a QWidget

Qt recently started crashing without having a reason for it. The most recent one which is currently grinding my nerves down to a pulp is crashing due to starting another form programmatically. The "must construct QApplication before a QWidget" apparently is a common issue with Qt 5.7.* versions and the solutions I have found so far in StackOverflow haven't helped me.
This is a screenshot of the error message I got after the application crashed:
And here is the bit of the code that I remove which allows me to restart the application without any noticeable problems:
#include "operations.h"
Operations o;
void mainWindow::on_thisButton_clicked()
{
o.show();
this->hide();
}
----
The main.cpp as requested :)
#include "mainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
mainWindow w;
w.show();
return a.exec();
}
Try this:
#include "operations.h"
void mainWindow::on_thisButton_clicked()
{
Operations *o = new Operations();
o->show();
this->hide();
}
You might want to declare Operations *o as a member of mainWindow and initialize it the the constructor if you don't want to create a new one each time the button is clicked.
"must construct QApplication before a QWidget" is the standard type of error you get with Qt applications, when linking something incompatible ( like mixing debug/release ).
So in most use cases this indicates a build problem and has nothing to with the code itself.
Don't create Operations object as a global variable, as it will be created as a static BEFORE running main(), therefore the error message is simply correct and relevant. This is a C++ issue, not a Qt one.
All other suggestions work because you now create the object at the right time, after the QApplication...
Okay, I have managed to find a solution, however, it is borderline idiotic as it does not make any sense why it does not work in its prior state. Technically, all you need to do in order to have the error not appearing is to stick the declaration of the form class you are referring within the function itself(ie Operations o;).
Here is the code solution itself:
#include "operations.h"
void mainWindow::on_thisButton_clicked()
{
Operations o;
o.show();
this->hide();
}
Bare in mind that this is not the end of all problems as I currently have the problem of the new form closing in the very same 1 second period it opens. If I manage to solve it I will update my solution.

Qt: display window content on slow startup

It feels like this question has been asked about a hundred times before (e.g. here) but I haven't found a working solution yet..
I have a Qt5 program (Linux) which takes some time (about 2sec) for initialization. I don't want to spawn a thread (for several reasons) and before initialization is done the program is not usable anyway.
Currently the program starts and it shows a black window, until initialization is done.
I'd like to have the window content be drawn as soon as possible and queue a method which does the rest which gets executed right after the main window has been drawn.
This is what I tried:
class my_window : public QMainWindow {
Q_OBJECT
explicit my_window(QWidget *parent = 0) : QMainWindow(parent) {
initializeUI();
/// UI is ready and should be drawn. initializeRest() should
/// be queued
/// tried to repaint() or update() the MainWindow and to 'force'
/// processing outstanding events - with no effect
update();
repaint();
QApplication::processEvents();
/// don't call - just queue
QMetaObject::invokeMethod(this, "initializeRest", Qt::QueuedConnection);
}
void initializeRest() {
// do stuff which takes a while
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
But the main window stayes black until initializeRest() has been executed.
How can I tell Qt to execute initializeRest() right after the window has been constructed?
I can think of starting a timer (bad, introduces extra latency) or an event handler which reacts on some kind of "WindowDrawn" event (bad, complicated).
What's the Qt-way to do this?
Update:
I've also tried to put the initializeRest() method into the main() function like suggested by Murphy:
my_window::my_window(QWidget *parent = 0) : QMainWindow(parent) {
initializeUI();
}
int main(int a_argsc, char *a_argsv[]) {
QApplication l_application(a_argsc, a_argsv);
my_window mainWindow;
mainWindow.show();
QApplication::processEvents();
mainWindow.initializeRest();
return l_application.exec();
}
With same results: Waiting for a couple of seconds inside initializeRest() makes show up the initially black main window and be drawn right after initializeRest() returned (which seems to be logical to me because the event loop has not been started yet..)
Note: This suggestion doesn't solve the issue; it's left here for completeness.
You can split the startup into smaller steps in main():
Create the QApplication instance.
Instantiate the main window (I'll call the variable mainWindow here). You can safely remove all that repaint-workaround stuff after initializeUI(); from the constructor of your code example.
Call mainWindow.show() to enforce showing the main window, followed by a call to QApplication::processEvents() to enforce the paint events being handled.
Do all the other initialization stuff of your application.
Start the event loop as usual by calling QApplication::exec().
Be aware that with complex applications/main window implementations it can get quite hairy to do everything in the right order; a QSplashScreen would surely be the less tedious solution.
I have the same problem. I think the problem is based not on show() function. Try to run the next code.
If add a button to boxLayout the application starts fast. But if I try setGeometry() the application takes a long time to start.

QPropertyAnimation not running immediately when QAbstractAnimation::start() is called

I am trying to make a simple multi-page widget with QStackedWidgets in Qt Creator with Qt 4.8.6. The goal is to have a QLabel and QProgressBar fade away after the progress bar reaches full value. I thought the best way to achieve this was using QGraphicsOpacityEffect and QPropertyAnimation in tandem as seen below.
void MainWindow::AnimateStartScreen()
{
//QSound::play("./Audio/THX-DeepNote-48Khz.wav");
sleep(5);
logoEffect = new QGraphicsOpacityEffect();
logoAnimation = new QPropertyAnimation(logoEffect, "opacity");
ui->startLogo->setGraphicsEffect(logoEffect);
logoAnimation->setDuration(2000);
logoAnimation->setStartValue(1);
logoAnimation->setEndValue(0);
logoAnimation->start();
progressBarEffect = new QGraphicsOpacityEffect();
progressBarAnimation = new QPropertyAnimation(progressBarEffect, "opacity");
ui->startProgressBar->setGraphicsEffect(progressBarEffect);
progressBarAnimation->setDuration(2000);
progressBarAnimation->setStartValue(1);
progressBarAnimation->setEndValue(0);
progressBarAnimation->start();
sleep(3);
}
Which is then called by the main method:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.HideTitleBar();
w.CenterWidget();
//QMainWindow::showFullScreen();
w.show();
w.IncrementProgressbar();
w.AnimateStartScreen();
w.ChangePageTo(1);
return a.exec();
}
Here lies the problem. I want this animation to finish before I change the page like so:
void MainWindow::ChangePageTo(int page)
{
ui->stackedWidget->setCurrentIndex(page);
}
Is there a way I can delay page change until my animation is complete? When I comment out the page change, the animation doesn't seem to even start until QApplication::exec() is called in my main method, evident by a 8 second waiting period (the combination of both sleep calls), rather than a 5 second delay before QAbstractAnimation::start() is called.
I believe what is happening is that the sleep(3) line is stopping the thread in which the GUI is running on, hence delaying the start of the animation for three seconds. When the sleep call has completed, I wonder if the animation tries to continue, but because of the page change,there is just no visible effect from the quick transition.
How can I make a 3 second delay without stopping the thread that the animation is running off of? Or are there any other suggestions that will produce the same effect?
I believe what is happening is that the sleep(3) line is stopping the thread in which the GUI is running on
Almost certainly. For the animation to run you need to keep the message queue running which, in the code you've posted, won't occur until the subsequent call to a.exec().
If you really need to block execution of MainWindow::AnimateStartScreen until the animation has completed then perhaps a better idea would be to replace the call to sleep(3) with...
while (progressBarAnimation->state() != QAbstractAnimation::Stopped)
QCoreApplication::processEvents();
(Although you might have to play about with the flags pass to QCoreApplication::processEvents to get the precise behaviour you require.)
Use next pattern for non-blocking waiting (instead of sleep):
QEventLoop loop;
connect( progressBarAnimation, &QAbstractAnimaion::finished, &loop, &QEventLoop::quit );
loop.exec();

Simple sound (.wav) playing application in QT (C++)

I am new to Qt and was trying to write a simple qt class that can plan a wav file.
After some reading and looking around I wrote the class and the code is as below. Questions follow after code
#include <QtGui/QApplication>
#include "playsound.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
playSound w;
int ch = 2;
int ready = 1;
cout<<"ready"<<ready<<endl;
// w.show();
w.playwav(ch);
return a.exec();
}
Source code for playsound.cpp
#include "playsound.h"
playSound::playSound(QWidget *parent): QWidget(parent) {}
playSound::~playSound() {}
void playSound::playwav(int ch)
{
switch (ch)
{
case 1: {QSound::play("/home/alok/qtworkspace/sounds/abc.wav"); break;}
case 2: {QSound::play("/home/alok/qtworkspace/sounds/xyz.wav"); break;}
case 3: {QSound::play("/home/alok/qtworkspace/sounds/abc.wav"); break;}
case 4: {QSound::play("/home/alok/qtworkspace/sounds/aaa.wav"); break;}
case 5: {QSound::play("/home/alok/qtworkspace/sounds/nnn.wav"); break;}
}
}
Problems and questions:
1) I want to close the application once the sound is played.As of now it says program running and I have to forcefully close it using the red button in the "Application Output" area in Qt creator. I tried using close() from Qwidget and quit() from QApplication but probably I am doing it wrong. How to go abt this?
2) Can there be a simpler implementation for this functionality? You know something that does not involve event loops. I was trying to do it in old school C++ style where I call a function when I need to play a sound and be done with it but could not get it done. Suggestions most welcome on this one.
Thanks
I can offer an answer using PyQt4 (since I'm a python coder), but the idea is the same.
1) QSound is a very basic interface for playing sounds. It doesn't have any useful signals (though I think it really should). In order to know when the QSound is complete, you have to keep checking its isFinished() method. You could either do this in a loop in your main thread, or get more advanced and create a QThread which will play your sound, go into the loop, and then emit its own custom signal when its complete. The QThread is preferred because you should never block your main thread. You would then be able to connect this custom soundIsFinished() SIGNAL to say the close() SLOT of your widget, or any other handler.
If you want more advanced options, you can use the phonon module, which does have all of these various signals built in. Its a litte more annoying to set up, but then you won't need a QThread.
2) Event loops are the core concept of how Qt functions. Your main application always enters an event loop so that widgets can post their events and have them processed. You could technically use Qt without an event loop, but then its really pointless because you are just fighting against the framework and losing everything that its capable of.
To exit from an application, you have to close the top level widget (if you're App has the property verbosely named quitOnLastWindowClosed set to true, but this is default so you don't have to worry with it) or emit a quit signal to the QCoreApplication you've created.
In the example below, I've taken the easy way: emit a close signal.
As stated by jdi, it would be better to create a Thread, but I've understood that you're only learning Qt and wrote this as an example, so busy waiting for isFinished is good enough. Below an example of how it should go:
#include "playsound.h"
playSound::playSound(QWidget *parent): QWidget(parent) {}
playSound::~playSound() {}
void playSound::playwav(int ch)
{
QSound *player = 0; // Creates an object so that you can call player.isFinished()
// the isFinished function is not static.
switch (ch)
{
case 1: {player = new QSound("/home/alok/qtworkspace/sounds/abc.wav"); break;}
// other cases
}
if(!player)
this->close();
while(!player->isFinished()); // waits until the player has finished playing
delete player;
this->close(); // closes this widget, and
// as this Widget has no parent, i.e. it's the "top-level" widget,
// it'll close the app.
}
edit: Shame on me for not reading the docs how I should have. QSound does not have a default constructor, I've edited the code.
A few notes: as this is only a test for you to learn how to use Qt, I've created a pointer to QSound and deleted it afterward. This is not a good approach, you should not play with pointers as I did there, a much better solution would be only instantiating the object you would use. Having to delete things manually is not good, and it's really better to rely on the good ol' stack for that.