I've found myself in the following situation: I've got an NSTableView subclass with an active cell. when I click elsewhere on the user interface, the delegate method (i) is fired, this in turn fires (ii) (my own method) cocoa then proceeds to process the click, resulting in the final two calls. I was surprised and disappointed by this sequence, since I had assumed the mouse click would be the first rather than the last event processed. It also causes me a problem because the ideal implementation of manageState is dependent on some of the processing I do in mouseDown:, but of course when manageState is called mouseDown: has not yet been executed.
Is their a way to delay the execution of manageState until mouseDown has returned? For example, in manageState I'd say something like Stop! a mouse down event might be in the events queue. Wait until it's finished, then resume. As the previous sentence implies, it's also possible that this method could be triggered by something other than a mouse down. In this situation, there's no need to look out for a mouse down event and processing can continue as normal.
MOUSE CLICK on NSTextView while NSTableView cell has focus...
+-------------------------+--------------------------------------------------------+
|Event |Triggered because |
+=========================+========================================================+
|controlTextDidEndEditing:|The mouse click ends the editing session |
| |of the active cell in my table view |
+-------------------------+--------------------------------------------------------+
|manageState |This method is a selector that belongs to a notification|
| |that is fired from within controlTextDidEndEditing: |
+-------------------------+--------------------------------------------------------+
|becomeFirstResponder |I clicked on the NSTextView instance |
+-------------------------+--------------------------------------------------------+
|mouseDown: |Finally, the click that started it all is processed |
+-------------------------+--------------------------------------------------------+
I figured this one out for myself. I feared I'd have to cobble together a threads-based solution, but a bit more docs-scouring turned up the NSEvent class method addLocalMonitorForEventsMatchingMask:handler.
When my app starts I call this method, define the associated block, and 'tell' the method what events I want to look out for. Then, whenever one of these events is detected, the block runs. Crucially ,this happens before any of the processing precipitated by the event is set in motion. In the block you have the opportunity to stop the event in its tracks, or let processing continue, you also have access to the event itself . Going back to my question, this means I am effectively inserting an additional row at the top of the table. This was perfect since it allows me to act on the event before any of the subsequent event executes.
[NSEvent addLocalMonitorForEventsMatchingMask:NSLeftMouseDownMask
handler:^NSEvent *(NSEvent *event) {
// whenever an event of type NSLeftMouseDownMask is detected, this code
// will run before any other event processing
// do some processing, then...
return event; // or nil, if you want to block the event
}];
Related
I have a tkinter GUI with a fairly large number of nested widgets. I want to rescale parts of it when the window is resized, so I have bound a callback to a resize event:
self.parent.bind("<Configure>", self.onsize)
However, whenever the window gets resized, self.onsize() is getting called ~100 times, slowing everything down and in a few cases causing a crash after max recursion depth is exceeded. I am assuming that this is because it is getting called as every single widgets gets rescaled individually in the process of resizing the parent window.
How can I set this callback up so that it is only called once, after the parent window and all of the internally linked widgets have been resized?
alternatively, how can I tell from the information contained in the event parameter that gets passed, whether or not the event corresponds to the parent window, or to a child of the parent?
I am assuming that this is because it is getting called as every single widgets gets rescaled individually in the process of resizing the parent window.
Maybe, maybe not. It depends on what the parent is, and what you're doing in the bound function. If the bound widget (self.parent in your example) is the root window or an instance of Toplevel, the binding will apply to all child windows. Otherwise, the event will only trigger for the widget it is bound to.
Most likely, your function is doing something to cause the widget to resize while it is responding to the event. This will trigger a new event, and that is why you get a recursion error. In short, you shouldn't be doing something in the bound function to cause the widget which received the event to change size.
How can I set this callback up so that it is only called once, after the parent window and all of the internally linked widgets have been resized?
One solution is to have the bound function schedule another function to be called once tkinter is done redrawing, using after_idle. Whether this will work in your specific case is hard to say since your question doesn't show why you're actually doing. If your function is itself calling update or update_idletasks it probably won't work since those functions process idle events.
alternatively, how can I tell from the information contained in the event parameter that gets passed, whether or not the event corresponds to the parent window, or to a child of the parent?
The widget attribute of the event object will tell you which widget received the event.
I have an issue with designing my application.
On my login form, I fire off an event in my ViewModel that's handled in the View (it displays a progress bar).
Then I query the database
Based on the query result I fire off an event from my ViewModel whose handler displays a message based on the result
The problem is when the query executes so fast that the (async) event handler doesn't even get to initialize the progress bar before the second event gets fired. The second event handler registers that there are no progress dialogues open so it doesn't try to close the open one before displaying the message. And when the user acknowledges the message, he is left with a indeterminate progress dialog which blocks the rest of the UI.
What design pattern should I utilize to avoid this race condition?
I'm trying to create a Chrome Extension that deals with selected text. Some website pages' otherwise selectable text content has click/mouse-up/down event handlers that navigate to a new page.
Is there a way from the background or content script to temporarily disable (and restore) the page's arbitrary event handlers without interfering with the native text selection?
Worst case I'm thinking of is to detach, clone the body html, allow the selection, and then restore the bound original. Seems like trouble.
Thanks!
Most HTML DOM events follow the capture-target-bubble event model. This means, for example, that if you click on a button, that the "click" event is first dispatched at the root, all the way down to the button, then back up. Event propagation can be stopped, which prevents the event listener at the next level from being notified of the event.
The earliest possibility of receiving the event is at the root, often window at the capture phase. To bind an event listener to the capture phase, use addEventListener with the third parameter set to true:
// in a content script, at run_at:document_start
window.addEventListener('click', function(event) {
event.stopImmediatePropagation();
}, true);
Many web pages use jQuery to manage DOM events, which binds the event listeners at the bubbling phase, so the previous method will work on most sites. If the page does not use jQuery, then you have to bind your event listener at document_start to make sure that your event listener is triggered before every other event listener.
What is the difference between the LostFocus and the Leave events of TextBox?
Check the notes section on these links:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.leave.aspx
According to MSDN, there is difference when changing focus of a control. The Leave event occurs before a validation and LostFocus occurs after validation.
UPDATE: 14 Feb 2019
I see that I'm still getting views and upvotes on the answer that I posted couple of years ago. It has now become imperative that I include a (rather important) quote from the MSDN links above to avoid confusion among new programmers (note the difference of order esp. in case of focus by using the mouse or by calling the Focus method):
When you change the focus by using the keyboard (TAB, SHIFT+TAB, and
so on), by calling the Select or SelectNextControl methods, or by
setting the ContainerControl.ActiveControl property to the current
form, focus events occur in the following order:
Enter
GotFocus
Leave <--- before validation
Validating --
|<--- validation
Validated --
LostFocus <--- after validation
When you change the focus by using the mouse or by calling the Focus
method, focus events occur in the following order:
Enter
GotFocus
LostFocus <--- before validation
Leave <--- before validation
Validating --
|<--- validation
Validated --
N.B: Emphasis on text and indicators in the quote added by me
They happen at different points in the control's lifecycle. Depending on the method used, validation happens after Leave and before LostFocus.
See MSDN: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx
Leave() event means that first executes keyboard event and then executes mouse event where as Lost() event means that first executes mouse event and then executes keyboard event.
To sum up, it either won't work for the keyboard or it won't work for the mouse. Considering you can't predict what input method will be used it's not very helpful.
However, that's not my point. LostFocus will happen when the form loads, Leave does not.
This would turn the text box yellow when the form is loaded.
Private Sub txtBox_LostFocus(sender As Object, e As EventArgs) Handles TextBox.LostFocus
txtBox.BackColor = Color.Yellow
End Sub
This would not.
Private Sub txtBox_TextLeave(sender As Object, e As EventArgs) Handles TextBox.Leave
txtBox.BackColor = Color.Yellow
End Sub
I want to minimize my app and after the timer end get it back.
I use code below.
To minimize application use following line of code:
Display.getDisplay (MIDLET_CLASS_NAME).setCurrent (null);
To get the screen back use the following:
Display.getDisplay (MIDLET_CLASS_NAME).setCurrent (myCanvas);
But when phone display is dismissed and going to clock mode my midlet display isn't shown until press any button.
any idea?
From your question it sounds that you expect setCurrent to somehow "force" device to immediately display your screen or maybe return only after screen gets visible.
This is not so, as clearly explained in the API documentation for Display.setCurrent:
Requests that a different Displayable object be made visible on the display. The change will typically not take effect immediately. It may be delayed so that it occurs between event delivery method calls, although it is not guaranteed to occur before the next event delivery method is called. The setCurrent method returns immediately, without waiting for the change to take place...
...if the application is in the background, passing a non-null reference to setCurrent may be interpreted by the application management software as a request that the application is requesting to be brought to the foreground... These are only requests, and there is no requirement that the application management software comply with these requests in a timely fashion if at all...
Consider redesigning your MIDlet to adjust to specified behavior.
If myCanvas is an instance of Canvas, one can use showNotify() events.
For a generic Displayable screen isShown() method checks if the it is actually visible on the display.
Sometimes it could even make sense to let user explicitly confirm return from background, like
display.setCurrent(new Alert("back to foreground", "dismiss to continue...",
null, AlertType.INFO), myCanvas);