Real time disabling widgets in Qt - qt

I have two radio buttons. When clicking one of them it should disable some widgets and activate some other. What should I do for that?
e.g If I check radioButton1 then it should disable a lineEdit instantly and if I check radioButton2 it should enable the first line edit and disable lineEdit2.
All this in real time.

Without having much to go on at the moment, a general answer would be the following:
Handle the appropriate signal of your radio buttons. Using this signal you can trigger a method/loop where you set your widgets to be disabled using setEnabled(false).
Given your situation you could have something similar to the following two methods, which you call depending on the signals you receive:
void OnRadioButton1()
{
lineEdit->setEnabled(false);
lineEdit2->setEnabled(true);
}
void OnRadioButton2()
{
lineEdit->setEnabled(true);
lineEdit2->setEnabled(false);
}
It's pretty straight-forward really. I don't understand where this whole notion of "real-time" comes into play. It's a single response to a single input "event".
Of course, this could just as well be a single method with a specific (boolean) argument or whatever. But given that we're discussing a hypothetical example case here that does not necessarily reflect your real code, this should at least provide you with a bit of an idea.

Related

Can I delay/bundle reactions to QPlainTextEditor.textChanged events?

I have a small IDE for a modeling language I wrote, implemented in PyQt/PySide, and am trying to implement a code navigator that let's you jump to different sections in the file being edited.
The current implementation is: (1) connect to QPlainTextEditor.textChanged, (2) any time a change is made, (sloppily) parse the file and update the navigator pane
It seems to work OK, but I'm worried this could cause major performance issues for large files on slower systems, in particular if more stuff is connected to textChanged in the future.
My question: Has anybody here implemented a delayed reaction to events, so that multiple events (i.e. keystrokes) within a short period only trigger a single update (say once per second)? And is there a proper QT way of doing this?
Thanks,
Michael
You can try using timers if you want some "delay".
There would be 2 ways to use them (with different results).
One is only parse after no input has been done for a certain amount of time
NOTE: I only know C++ Qt but I assume the same things are valid for pyqt so this is kind of "pseudocode" I hope you get the concept though.
QTimer timer; //somewhere
timer.setSingleShot(true); //only fire once
connect(timer,QTimer::timeout(),OnTimerDone(...);
OnTextChanged(...)
{
timer.start(500); //wait 500ms
}
OnTimerDone(...)
{
DoStuff(...);
}
This will restart the timer every input, so when you call that and the timer is not done the timeout signal is not emitted. When no input is done for an amount of time the timer timeouts and you parse the file.
The second option would be to have a periodic timer running (singleShot(false)).
Just start the timer for like each second. and timeout will be called once a second. You can combine that with a variable which you set to true when the input changes and to false when the file is parsed. So you avoid parsing when nothing has changed.
In C++Qt you won't have to worry about multi-threading because the slot gets called in the GUI thread. I assume it is the same for python but you should probably check this.

MediaFoundation - Frame is ready?

I am using Media Foundation to play a video, which I need to edit in real time, so I need to know when a frame is ready to be presented, but the callback does not offer such a message.
My only idea is checking the frame rate, then setting a timer to just shy of that and using GetPosition to check where I am against where I was the last time the timer was called, but there must be a better way than this.
Thanks!
Matt
Why can't you inject your own IMFStreamSink instance in the topologoy, do the editing in your implementation of IMFStreamSink::ProcessSample and passing the edited to whatever output node you are using currently?
Also, if you are using EVR, you could make a custom presenter - see this article on MSDN.
I found an easy solution. Set the playback speed on the session, then create a presentation clock from the session. Set a timer, and check the presentation clock. When time has passed equal to the playback speed for one tick, a new frame is being presented.

When to emit dataChanged from a QAbstractItemModel

In Qt, I have a model subclassing QAbstractItemModel - it's a tree displayed in a QTreeView.
The model supports various forms of change which all work OK. The two of relevance are:
1) Some data in a small number of related rows changes
2) A visualisation change means that the majority of rows should change their formatting - in particular they have a change of background highlighting. Their DisplayRole data does not change.
The current design deals with both of these in the same way: for every row that has any change the model emits dataChanged(start_of_row_index,end_of_row_index). I emit the signal for both parent rows that change and for any of their children that have changed.
However, this performs badly in case 2 as the model gets big: a very large number of dataChanged signals are emitted.
I have changed the code so that in case 2 the model emits dataChanged only for the (single) row that is the parent of the entire tree.
This still appears to work correctly but does not accord with my understanding of the responsibilities of the model. But I suspect I may be wrong.
Perhaps I am misunderstanding the dataChanged signal? Does it actually cause the view to update all children as well as the specified range? Or can I avoid emitting dataChanged when it is not the DisplayRole that is changing?
Edited with my progress so far
As Jan points out, I ought to emit dataChanged either for most or all of the rows in case 2.
My code originally did this by emitting dataChanged for every changed row but this is too expensive - the view takes too long to process all these signals.
A possible solution could be to aggregate the dataChanged signal for any contiguous blocks of changed rows but this will still not perform well when, for example, every other row has changed - it would still emit too many signals.
Ideally I would like to just tell the view to consider all data as potentially changed (but all indexes still valid - the layout unchanged). This does not seem to be possible with a single signal.
Because of a quirk of the QTreeView class, it is possible (though incorrect according to the spec) to emit only one dataChanged(tl,br) as long as tl != br. I had this working and it passed our testing but left me nervous.
I have settled for now on a version which traverses the tree and emits a single dataChanged(tl,br) for every parent (with tl,br spanning all the children of that parent). This conforms to the model/view protocol and for our models it typically reduces the number of signals by about a factor of 10.
It does not seem ideal however. Any other suggestions anyone?
You are expected to let your views know whenever any data gets changed. This "letting know" can happen through multiple ways; emitting dataChanged is the most common one when the structure of the indexes has not changed; others are the "serious" ones like modelReset or layoutChanged. By a coincidence, some of the Qt's views are able to pick up changes even without dataChanged on e.g. a mouseover, but you aren't supposed to rely on that. It's an implementation detail and a subject to change.
To answer the final bit of your question, yes, dataChanged must be emitted whenever any data returned from the QAIM::data() changes, even if it's "just" some other role than Qt::DisplayRole.
You're citing performance problems. What are the hard numbers -- are you actually getting any measurable slowdown, or are you just prematurely worried that this might be a problem later on? Are you aware of the fact that you can use both arguments to the dataChanged to signal a change over a big matrix of indexes?
EDIT:
A couple more things to try:
Make sure that your view does not request extra data. For example, unless you set the QTreeView's uniformRowHeights (IIRC), the view will have to execute O(n) calls for each dataChanged signal, leading to O(n^2) complexity. That's bad.
If you are really sure that there's no way around this, you might get away by combining the layoutAboutToBeChanged, updatePersistentIndexes and layoutChanged. As you are not actually changing the structure of your indexes, this might be rather cheap. However, the optimization opportunity in the previous point is still worthwhile taking.

QTreeView: how to be inform of the beginning/end of item expansion?

I have a QtreeView that is displaying file lists (using a model derived from QFileSystemModel). As the building of the file list needs a lot of time (I must read the content of each file to determine if the file is visible or not) I want to display the wait cursor during the analysis process. The wait cursor must starts when the user select an item (directory), and stays as long as all the list is not displayed.
For this I did a lot of tries:
using the expanded signal. But this signal is not related to drawing. Hence it arrves almost immediately,
managing the cursor in data() function of my model. But in this case I have an horrible blinking cursor,
managing the cursor by overridding the painEvent. In this case I have a small blinking, and the cursor appears lately
...
So, none of my "solutions" is perfect. Hence, do you have a way to do what I want?
Thanks a lot.
One more idea, but i did't try it:
Try to check QAbstractItemView::State in a timer after QTreeView::expanded() signal.

How to create a custom multi-progress bar in Qt

I am working on a multi -segment download manager. I want to display the segmentation procedure. QGraphicsScene works fine but , unfortunately it slows the download. Is there any better option, other than using QProgressBars.
I am using QNetworkAccessManager to download files. If I connect the downloadProgress signal of QNetworkManager object to a slot of Main Gui Thread which draws on QGraphicsView, the download speed decreases even upto 10 times in some cases
// a custom progress bar
void Download::showGProgress(int num, float prgrss) //slot
{
prgrss=prgrss/100;
x_coord=(ui->graphicsView_2->width()-3)*prgrss;
for(float b=0;b<=x_coord;b=b+0.5)
{
progress.addRect(0,0,x_coord,y_coord);
}
}
QNetworkAccessManager is not threaded. It is asynchronous, using the current threads eventloop. It is the HTTP requests which it create that are the threaded aspect.
This would explain why anything you do in your main thread could theoretically slow down the operations of the download. Though not necessarily the underlying threaded download itself, but rather the signaling response time that would allow you to have fast feedback about it.
What you should probably do is create your own QThread subclass, and create the QNetworkAccessManager in the run() method. And then create a QEventLoop in the thread and call exec()
In a nutshell, you need to create your own Threaded QNetworkAccessManager.
create your own widget to do what you would like
this is easier than it sounds.
Make a class that subclasses from a QWidget. And in this widget make a Horizontal Sizer that contains 100 Qlabels (store the QLabels in a vector). Give it slots to 'update' the current progress by setting the background color of each QLabel to a different color. This should be fairly easy to do progressively, meaning you store the current 'percentage' as a member variable and then only adjust the fields that are necessary to get to the percentage that you're looking for (This will eliminate some flickering if you were to do it from scratch every time).
Add functions that will switch the sizer to a vertical one instead of a horizontal one to make it even more customizable.
This allows you to get creative in the what you can do for the progress bar as each element could be a different picture, or a different color, or whatever you would like.
Did you try QProgressBar? Maybe you can write a subclass of it to handle your own properties.

Resources