PyQt4 : Sync between QSpinbox and QSlider - pyqt

I make a relation between QSpinbox and QSlider.
QSpinbox has a range -10.0 to 10.0, and QSlider has a range -100 to 100.
So, the value of QSlider divided by 10 is connect to QSpinbox, and vice versa.
I use "valueChanged()" SIGNAL to each other.
And I want to type "3.5" in QSpinbox, in this case when I type just "3", QSpinbox's "valueChanged" change QSlider's value, and QSlider do again. So, QSpinbox lose it's focus.
I can't type "3.5" in one shot.
"valueChanged()" SIGNAL works too diligently :)
How can I solve this issue?

The valueChanged() signal is indeed meant to fire actively as it is being changed. If you want a signal fired when editing has finished, there is a signal specifically for that called editingFinished: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qabstractspinbox.html#editingFinished
You may have overlooked it because its a member of the superclass QAbstractSpinBox. Note that this signal will fire once the widget loses focus or the user hits enter. If that is not the behavior you want either, then the only remaining option is to use a QTimer with a short delay that restarts everytime valueChanged fires, and once the user waits long enough the timeout will actually then update your slider.
I also noticed that you are trying to use non-integer values with a QSpinBox, which is designed for ints. You might want to try a QDoubleSpinBox that is designed for floating precision. The valueChange() might behave slightly better as its expecting the decimal. Though I am just making a guess as I haven't tested it: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qdoublespinbox.html

Related

Articulate non-blocking to blocking events in pyglet

I'm developing a game in pyglet, that scheduled by a simple text file like :
0:00:01;event1
0:00:02;event2
0:00:03;event3
The fact is that, among these events, some might be blocking (for instance event2 might consist in displaying instructions until a key is pressed). As a consequence, event3 might not be executed at the proper time (i.e., during the event2). For now, my strategy is to schedule one event after the other :
Execute the first event
Once the first event is finished, compute the remaining duration between the first and the second event (delta_duration)
Schedule the second event with a delay of delta_duration
... and so on
For now, I did not succeed in implementing properly a blocking event with this strategy. It seems that anything blocking the event_loop (like a sleep call during event2) is preventing even the graphical elements of event2 (text instructions) to be displayed. On the other hand, if I do not put any blocking routine (sleep) in the event2, I'm able to see the vertices, but the scheduler keeps on scheduling (!), and so the event3 comes too soon.
My question is : what would be a general strategy, in pyglet, to articulate non-blocking to blocking events ? More precisely, is it possible (desirable) to use multiple clocks for that purpose ? The pyglet documentation mentions that multiple clocks can be used but it is not very well explained.
I don't want a solution that is specific to my events example but, rather, general indications about the way to go.
It's really up to your program on what blocks. If you are using input from Python for the console window, then yes that will block because it's blocking execution of Python in general. If you have a label popup in the window that is waiting for input from an on_key_press window event, then that is completely different as it's not blocking the pyglet loop, it was scheduled within it.
If your event is a 20 second long math calculation, then that should probably be ran in a thread. You will probably have to separate the types of events in order to differentiate how they should be ran. It's hard to say because without a runnable example or sample of code, I am just guessing at your intentions.
Although it sounds more like you are wanting some sort of callback system. When execution of func1 is declared done, go to func2. There is nothing built into pyglet like this, you would have to have a clever use of scheduling. There are examples of this using pure python though. I personally use Twisted Deferred's for this.

Qt: Sometimes wheelEvent() is not called immediately when rotating the mouse wheel

I use Qt's wheelEvent to implement scrolling in a custom widget. Normally, this works fine.
However, when dragging the mouse and scrolling with the mouse wheel at the same time, it sometimes happens that rotating the mouse wheel by one step does not do anything at first (no wheelEvent is received). This might even randomly happen a few times successively. The next time the application does receive a wheelEvent, it comes with an accumulated event->angleDelta() of all previous events that were not reported separately. Apparently the events are buffered together in this case. Note that the wheelEvent may happen a long time after the initial mouse wheel rotation(s) in this case: it only happens once the wheel is rotated again.
This is an issue, since it means that my widget sometimes does not properly react to scrolling. Is there any way to avoid this kind of buffering and receive all wheel events immediately instead?
Notably this behavior is only well reproducible if at the same time dragging the mouse within the widget, which performs some non-trivial actions as a result. So I suspect it might happen if the event loop seems busy. But it certainly isn't busy enough to be unable to handle each wheelEvent. So I would like to disable this buffering.
I observe this on Linux with Qt 5.12.0. Any help is appreciated, thanks.
I am answering my own question here since I found the answer after writing it (but was unable to google it before).
The same problem has been reported here (with a somewhat non-descriptive title): Qt QOpenGLWidget wheelEvent strange behaviour
For me, setting Qt::AA_CompressHighFrequencyEvents (see https://doc.qt.io/qt-5/qt.html#ApplicationAttribute-enum) to false seems to have fixed the issue, as posted by #gatis paeglis as an answer to that question.

Is it OK to read Qt Widgets from another thread?

I found many answers say that accessing Qt Gui Widgets from another thread is not safe. I agree with this if we try to modify the widgets. But what if I only read the value of widget, without any modification?
I have designed a GUI tool using Qt, and my working thread reads Widgets directly, for example, get the text of QLineEdit, get the value of QComboBox,etc. And I haven't found any problem.
I pass the pointer of MainWindow to working thread.
Is this really not safe?
First: It is always a bad idea to read properties from another thread without protecting the memory (Mutex, Signal & Slot).
Your situation: If nothing wants to change the value, you should be fine. There are no problems if every thread only reads the value. But if you change the value of the QComboBox (for example) by clicking arrow up, arrow down or selecting a new item (what I expect you will do, because that's the reason of using a QComboBox) the value will be written and then the application can crash if your worker thread wants to read the value in the exact same moment (the possibility of a carsh depends on the frequenz your thread pulls the informations).
Your application never crashed because the condition never appeared.
But that does not mean that this can not happen.

I need a name for something like 'debounce', but not quite the same

Here's an interesting one. I'm working with FRP, and looking at the 'debounce' methods in various libraries (jQuery, Bacon.js). I started working with this, and found it almost does what I need, but with a subtle difference. Here's my understanding of debounce as it relates to event handling:
When an event is happening with at least a certain frequency, don't do anything. Once the events slow down to less than the frequency, fire the event handler. For example (pseudo-code) for key-presses.debounce(1 second) then Alert, we would see nothing happen if keys are pressed within a second of each other, until 1 second after the last key was pressed, then we'd get an Alert.
What I need is something that fires at the start of the sequence, not after the end. So, for the same example, we'd see the Alert immediately, then nothing. If the user starts pressing keys again after at least 1 second, we'd get another alert, then nothing again.
The code is easy - I just want a name for this. It still takes a single argument for the frequency: BeginSequence(1000)? AfterExpiry(1000)?
Any suggestions?
So you want an event when there is an event after a long enough period of no events?
I would call that event a silence-breaking event, so maybe something like breakSilence? I'm not sure that looks right, maybe onBreakSilence, but I'm not familiar with nomenclature of Bacon so I don't know if onX is used.
Another option might be listenAfter.
key-presses.onBreakSilence(1 second) then Alert
key-presses.listenAfter(1 second) then Alert

Busy cursors - why?

Can anyone give me a scenario where they think busy cursors are justified? I feel like they're always a bad idea from a user's perspective. Clarification: by busy cursors, I mean when the user can no longer interact with the application, they can only move their hourglass mouse pointer around and whistle a tune.
In summary, I think that the user should be blocked from doing stuff in your app only when the wait interval is very short (2 seconds or less) and the cognitive overhead of doing multi-threading is likely to result in a less stable app. For more detail, see below.
For an operation lasting less than 0.1 second, you don't usually need to go asynchronous or even show an hourglass.
For an operation lasting between 0.1 and 2 seconds, you usually don't need to go asynchronous. Just switch the cursor to the hourglass, then do the work inline. The visual cue is enough to keep the end-user happy.
If the end-user initiates an operation that is going to take just a couple of seconds, he's in a "focused" mode of thinking in which he's subconsciously waiting for the results of his action, and he hasn’t switched his conscious brain out of that particular focus. So blocking the UI - with a visual indicator that this has happened - is perfectly acceptable for such a short period of time.
For an operation lasting more than 2 seconds, you should usually go asynchronous. But even then, you should provide some sort of progress indicator. People find it difficult to concentrate in the absence of stimulation, and 2 seconds is long enough that the end-user is naturally going to move from conscious ‘focused’ activity to conscious ‘waiting’ activity.
The progress indicator gives them something to occupy them while they are in that waiting mode, and also gives the means of determining when they are going to switch back into their ‘focused’ context. The visual cues give the brain something around which to structure those context switches, without demanding too much conscious thought.
Where it gets messy is where you have an operation that usually completes in X time, but occasionally takes Y, where Y is much greater than X. This can happen for remote actions such as reaching across a network. That's when you might need a combination of the above actions. For example, consider displaying an egg-timer for the first 2 seconds and only then bringing in your progress indicator. This avoids wrenching the end-user from the 'focused' context directly to the 'waiting' context without an intermediate step.
It's not specifically the busy cursor that is important, but it IS important, absolutely, always to give feedback to the user that something is happening in response to their input. It is important to realize that without a busy cursor, progress bar, throbber, flashing button, swirling baton, dancing clown.. it doesn't matter ANYTHING- if you don't have it, and the computer just sits there doing nothing, the computer looks broken to the user.
immediate feedback for every user action is incredibly important.
I think you may well be right: in a decent asynchronous app, you never need to show a busy cursor. The user can always do something even if the big last operation is completing.
That said, sometimes Java apps like Netbeans or Eclipse, or even Visual Studio, hang with no busy cursor and no hope. But in that case, a busy cursor probably wouldn't help much either...but I think you're right: busy cursors are from a non-multithreading era for apps. In Flex apps, for instance, EVERYTHING is automatically event-driven callbacks, so setting a busy cursor would just be meaningless (though possible, of course).
You show a busy cursor when the user can not do anything until the operation is completed - including exiting the application.
I find it interesting that you don't see busy cursors in Web Browsers - perhaps that why people like them so much.
No, wait, I have a better answer. You show a busy cursor when the computer is thinking.
When one hits the Refresh button on a web browser, busy cursor must appear immediately to tell the user to let them know that a page is being loaded.
I think it was Don't Make Me Think that said that the tolerable loading time for human is zero second.
Google says:
Responsive
It's possible to write code that wins
every performance test in the world,
but that still sends users in a fiery
rage when they try to use it. These
are the applications that aren't
responsive enough — the ones that feel
sluggish, hang or freeze for
significant periods, or take too long
to process input.
There are two purposes for it:
Indicate for the user that something is happening.
Indicate for the user that nothing can't be done right now.
Busy cursor is better signal about the operation than nothing. For longer lasting operations something better should be used. For example browsers is still operational when a page is being retrieved and there is even a button to stop the operation. As the user interface is fully functional, there is no need to use busy cursor. However busy cursor can be used even in this kind of situations in the transition phases like when starting the operation or when stopping it.
I try to use them on any action that may take from 0.5 to 3 seconds, for longer actions I think progress indicators with enough information should be used.
I noticed with Fedora 8 at least that when an app sets the "busy" cursor, the "busy interactive" one is actually displayed. I guess this is because the system is still responsive to mouse input (like dragging the window etc.). As an aside, selecting the "busy interactive" cursor explicitly on linux is tricky:
http://www.pixelbeat.org/programming/x_cursors/
The only thing I believe the busy cursor does is it informs the user that ...
I'm not outright ignoring you, I'm just doing something else that may take awhile
While it is absolutely necessary to alert the user that your application is doing something, a busy cursor is only useful for the first few seconds of processing. For a delay of more than about 15-20 seconds, something else must be presented such as a progress bar, status message, message box, whatever. People assume your software has locked up after a minute or so and will try to terminate it. Sometimes, overall visual cues are just as important as a busy cursor.
For example, applications with tabs that do not respond with appropriate highlighting until the operation in the tab completes can be fixed up by updating the tab temporarily until all operations are complete. Sometimes, just a little optimization or refactoring will clean up horrible user interface responsiveness such as this.
I would use them only for quick completing things, like say under half a second. If anything takes longer than that then a progress dialog should popup, or a progress bar should appear in the status bar or somewhere else in the interface.
The user should always be able to cancel the action if it is taking too long to complete.
In response to the comment, the busy cursor would only be visible for the half second or so, as once the progress dialog is up it should change to being one of those "half busy" cursors, or just the normal arrow cursor.
You should avoid having a busy cursor up except in extreme circumstances, and if you think you need one, then think again and redesign.
For example, to indicate that you've clicked on a button, even though it's not done processing the event. If there were not some indication, the user might try to click the button again, causing all manner of badness.

Resources