TextArea issue: GUI freezing
-
I'm in the process of porting my console application to Qt. It displays a lot of various output, so the first thing that I'm trying to create is a sort of "Console" inside my GUI to show what's going on. I've done the basics - created TextArea object in my qml code, in c++ I find a pointer to it and send commands throught my application. But here comes the issue: When my TextArea fills with a lot of text GUI stops responding, although the rest of application is still running.
I assume I've chosen a poor way to handle text output. Each time I want to update TextArea I call setProperty on it with previous text + new string as arguments. So basicly every time I need to add something it redraws entire text area and I guess the larger chunk of text becomes the harder it is for GUI to process it.
What would be the option to just add a new string to existing text without having to redraw entire TextArea?
-
Hi,
You can call append on the "TextEdit":http://doc.qt.io/qt-5/qml-qtquick-textedit.html#append-method from TextArea
Hope it helps<
-
Thanks, it helped, but partially. My application GUI no longer freezes, however, it's still pretty laggy.
I assume this is because my application can generate hundreds of new lines in a matter of seconds and it fills TextArea pretty quickly. Even though my TextArea doesn't seem to redraw itself each time I update it, it still has to deal with a lot of data output.
EDIT (I wasn't clear enough):
I'd like to limit my TextArea like console applications limit their output: Let's say console app can hold maximum of 1000 lines. When line 1000 is reached, line 1 is removed, freeing space for line 1001 and so on. First lines are removed to give space to new lines. What properties and functions do I use for that. -
You can use remove but you should also consider using the model/view paradigm for that. It might be easier to deal with.
-
Looks like remove is what I need indeed, thanks again. I'm trying to use it in a way that won't mess my output at the moment. Though one thing I dislike about it is that it deals with characters, I'd rather remove text by lines.
Never heard of model/view paradigm since I've used nothing but console I/O before Qt, I'll have a look at it.
-
Still pretty laggy. I have an idea, can somebody tell me if that will work?
At the moment my textarea resides in the main thread with the rest of GUI. There is a separate thread that communicates with main thread through signals. This separate thread is constantly updating textarea.
I'm thinking of moving my textarea to a separate qml, then load it separately from c++ in it's own thread. So main GUI and textarea have their own threads. I assume textarea will be separated from the rest of GUI and won't cause lags that way. Is something like this possible?
-
AFAIK, no, you can not modify UI elements in a different thread directly. You have to use signals and slots for that.
Then again, take a look at the model/view doc.
-
[quote author="SGaist" date="1424904005"]...You have to use signals and slots for that.
[/quote]
That's pretty much what I've decided to do at the moment.
I've got it working mostly, but it's not perfect:
Main thread spawns thread 2. Thread 2 spawns infinite loop where major part of the program resides. When a cycle of infinite loop is coming to an end, a signal with QString argument is sent to a slot in class that controls GUI in Main thread. TextArea draws output, cycle repeats again.
I use append() to add text, remove() to limit the buffer of textarea. It works well either with large amount of small messages or moderate amount of big messages. In this cases there is no lag or freezing.
It is something, but it is still not as fast as console output. If there are lots of QStrings with large data output GUI is having hard time processing them.
Windows console was able to process a lot of output calls per second just fine, here I have to bother limiting what data is shown.
[quote author="SGaist" date="1424904005"]
Then again, take a look at the model/view doc.[/quote]
I'm reading that too, haven't found a way to use this yet though.
-
Something like the QStringListModel but a bit more evolved. Each row is a line of then then you can easily removed/add rows where you want
-
That seems like a good option, although I seem to have found another solution myself: I have used QPlainTextEdit widget instead of TextArea qml type and noticed a tremendous increase in performance.
I created a simple QMainWindow witn QPlainTextEdit as child of it, set MaximumBlockCount to 1000. In my app I set option to output as much as possible. Result was very pleasing, GUI could process hundreds, if not thousands of lines per second without any hint of freezing.
Are widgets better in terms of performance? Or is it this particular one? I'm not sure if this is relevant, but when I used TextArea for output I wasn't able to append string to it directly, but rather make a call to function inside qml file through QMetaObject::invokeMethod first. In case of QPlainTextEdit all logic behind output was done inside C++.
My only complaint is that qml syntax is much more appealing to me, rather then html-like syntax of QWidgets. Would there be an option to combine both without loss of performance?