I have some questions about the general usage of Qt events. I'm new to Qt, and I am going to try out making a custom event. The questions I ask are related to this article: Qt 4.8: The Event System
When does an event “occur”? In Qt's built in events, mouse clicks and key presses are put into a queue and then the functions are executed at the next frame. I’m especially wondering about this for custom events, because I’m not sure if it always occurs when a mouse is clicked. For custom events, is it when you send the event into the queue and then waits to be processed by the event() function at the next frame?
To create a custom event, must you make a class that inherits from QEvent and register an event with registerEventType() function? Is this the standard process, or can an event simply be a class? How does this function, registerEventType(), work?
Do custom events have a QEvent::Type? Is this the number between 1000 and 6563 that is given when using the registerEventType() function?
What is the recipient of an event? It seems to be in functions' parameters like postEvent(), sendEvent(), etc. However, I am not sure what this object is for.
Where is the actual code that is executed when an event is fired?
Is it a function, or is it in the event() function of QObjects.
Also any working examples of Qt events (both built-in or custom) in action would be helpful.
You should look at Qt Examples online or in QtSDK, there are tons of them.
IMO you didn't search hard.
Ad.1. It occurs after you fire it with QApplication::postEvent() or QApplication::sendEvent(). Not immediately of course, because it has to go through the main loop, etc. The order of events should be preserved, though.
Ad.2. Look at this, second anwser.
Ad.3. Go to Ad.2.
Ad.4. This object will receive this custom event in QObject::customEvent() handler.
Ad.5. Go to Ad.4.
Related
I just recently started exploring Qt (version 5 at the moment) and I came across an issue to which I could not find any solution:
I would like to send a custom event to the main window such that the event is then propagated to the entire object tree (given by QObject::dumpObjectTree()). Then, certain parts of the object tree can choose to react to the event.
Is there a method to do so in Qt?
What you're looking for (a kind of broadcast event) does not exist in Qt. Events are targeted to specific objects.
Signals are closer to what you want. You can generate a signal without specifying who it's for. Then any other object is able to connect a slot to that signal if it's interested in it.
I'm trying to implement MVC in Qt using a data model ported from another platform. I have several widgets onscreen that each listen to the same model to render the data. The user can also interact with these widgets, edit them, and thus push changes back into the model.
The specific problem I have is that if my (ported) data model changes and I push data into eg a QTreeWidgetItem with setData, the widget emits an itemChanged signal. This in turn triggers the controller code that is monitoring user edits, and causes it to push the same data back to the model. Unless I insert data comparison somewhere, I end up with an infinite loop.
Is there some way for the controller to quietly update the item's data without emitting itemChanged? Alternately, is there a better way to distinguish between user edits on a widget and programmatic changes? I am simply listening for itemChanged.
Is there some way for the controller to quietly update the item's data
without emitting itemChanged?
I hope not. I would not like it if I had a view, which shows wrong data because someone secretly changed the model. I am afraid, you have to conjure up something yourself. You have to modify your controller. Not emitting itemChanged when it does.... horrible idea.
I was thinking, what you could do. Expect no complete solution. I just looked around how I would do it. You must subblass your model and override the setData method. Then you can distinguish changes by the role. Qt::EditRole or you can create your own user defined role. The itemChanged signal must be emitted in any case. Else your views would be wrong. But in your model subclass you could implement a new signal 'dataChangedByUser' or whatever, which could be emitted additionally to itemChanged. How your controller handles this....
I'm stepping through my code to figure out why a certain function takes more time to run the first time it gets called than on successive calls. The code flow for each function call is the same up to when a dispatchEvent gets called. I'm pretty sure it's different afterwards, as that call takes a lot more time the first time around. Unfortunately, I have no idea which other parts of the code chew on this specific event and thus cannot step through the handling of such event.
The question: is there a way to either figure out who handles such events or magically step through the handling code without explicitly setting breakpoints there?
thank you!
Not in an easy fashion, no. It's a pro and con of Flash (or any event based framework). You don't know when it's fired, where it's fired from (think bubbling), or who is listening for it. But at the same time, anyone could listen for any event, from anywhere (so long as it's within the display tree).
Normally what I do is just do a workspace search (ctrl+H in Flash Builder) and search for that specific event (you should be using static constants for dispatching/listening event types) and see who's doing what.
In my mathematical application I am using timers to regularly perform certain actions. These actions can also be configured by my users. Now I don't want these actions to be executed if there is already another action busy.
E.g. if the user just started a complex calculation by selecting a menu entry, I don't want to execute the actions behind my timers.
Problem is that the user can execute an action via a lot of different ways (via the menu, by clicking somewhere, via popup menu, via drag-and-drop, ...). What I effectively want is to prevent the timers from going off if the application is currently not in the main event loop.
I will give a more concrete example to make it clearer:
At startup I create the timers
If a timer goes off, I execute some actions which, in practice, could access almost every bit in may application's data structure.
Now suppose the user starts a mathematical algorithm (via the menu, by clicking or by dragging elements on the screen, it doesn't matter how he started it).
The algorithm will perform lots of calculations (in the main thread). Since they are executed in the main thread, the timer events will not go off.
Now the algorithm shows a message box (could be a warning or a question).
While the message box is open, events are processed again, including my timer events, which could possibly perform incorrect calculations because there is already another algorithm running.
Reworking my application so that I move logic to a separate worker thread, or adding checks to all of my actions isn't possible at this moment. So please don't suggest to completely rework my application.
What I tried so far is the following:
Using postEvent to send an event, hoping that this event would only be executed in the main event loop. Unfortunately, also the message box's event loop seems to process posted events.
Using the QEvent::WindowBlocked and QEvent::WindowUnblocked events to see when a modal dialog was opened. In my timer-event-logic I can check whether we are between QEvent::WindowBlocked-QEvent::WindowUnblocked calls or not. Unfortunately, these events only work for modal dialogs created by Qt itself, not for other dialogs (e.g. the Windows MessageBox, or the system's printer configuration dialog). Also, this trick would not help if there would be other event loops created by sub routines.
What I actually need to solve my problem is a simple function, that:
If the application is handling an event in the main event loop returns true
If the application is handling an event in another [sub] event loop, it returns false
An alternative could be to return a level that indicates the 'depth' of the handled event.
Anyone suggestions?
You could hook into the event loop of your main thread/application using QAbstractEventDispatcher. Conditionaly filter out QTimer-events based on your application state.
On occasion, I have wanted to push a closure onto ActionScript's event stack so that it will be executed after the current event handler. Right now I use setTimeout(closure, 0). Is there a more direct way of doing this?
setTimeout(closure, 0) is creating a new event stack. I don't understand your objective if this solution isn't working for you. What is the goal you're trying to accomplish?
Flex has ENTER_FRAME events, Timer, callLater, setTimeout, setInterval, all which delay calls and create new execution stacks.
Are you trying to inject code into the current stack? If so, you might need to look at something like this: http://en.wikipedia.org/wiki/Active_object. The idea being that you push functions (closures) into an array, and the active object controller pulls the next one off the list when the previous one has run to completion. That's the simplest case. You can write a more complicated one that will have priority stacks like high, medium, low, with your own schedule management system. (e.g., low get promoted after waiting too long).
But hey! The devil is in the details. What's the goal?
Take a look at capture and bubbling phases of the as3 events.
I found this nice chapter that explains clearly the proccess: http://books.google.com/books?id=yFNZGjqJe9IC&lpg=PA250&ots=oPB9HXIby7&dq=flash%20event%20bubbling%20phase&pg=PA250#v=onepage&q=&f=false
And also check the EventDispatcher class documentation that explain the use of this different phases.