removeEventHandler() is ok, but what if I don't keep reference on handler ?
Can I remove any event handler(filter) by event type or even all handlers from my JavaFX. scene.Node instance? I guess that somewhere a list of handlers existed, and I can traverse it, and remove what I want.
Can I remove any event handler(filter) by event type or even all handlers from my javafx.scene.Node instance?
I don't think you can remove an event handler or filter which you didn't have a reference to originally. You can add extra event filters to filter out processing for events by type or you can set your own event dispatcher on the node and have your custom dispatcher only forward the events you want to the node's standard event dispatcher.
I guess that somewhere a list of handlers existed, and I can traverse it, and remove what I want.
Yes, but that is buried within the private implementation of the Node, so you probably don't want to hack the private Node code to do that.
I came across this question while looking for how to create event handlers that remove themselves. The answer to my question was here, I don't know if it will help you.
javafx have an eventfilter remove itself
Here is an example
EventHandler<MouseEvent> object_clicked=new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
// on click actions here
my_node.removeEventFilter(MouseEvent.MOUSE_CLICKED, this); // at the bottom
}
};
my_node.addEventFilter(MouseEvent.MOUSE_CLICKED, object_clicked); // add the eventhandler to the node
Related
Is there a way to detect which node is being rendered when the user selects a link within the pages detail app and only the iframe changes? If just the the iframe is changing I need a mechanism that can call the parent page and send the path of the node that is being rendered in the iframe. We run Magnolia EE 5.6.11.
My issue is that I have a ValueChangeListener in a ComboBox that I use as a versionSelector in a PageBar extension in the pages detail app.
// Create a selection component;
private ComboBox versionSelector = new ComboBox();
private Listener listener;
private boolean isSettingValue;
public VersionSelectorViewImpl(){
construct();
}
private void construct() {
versionSelector.setVisible(false);
versionSelector.setSizeUndefined();
versionSelector.setImmediate(true);
versionSelector.setNullSelectionAllowed(false);
versionSelector.setTextInputAllowed(false);
//setup listener for the selected item
versionSelector.addValueChangeListener(new Property.ValueChangeListener() {
#Override
public void valueChange(Property.ValueChangeEvent event) {
if (listener != null) {
listener.versionSelected((Object) event.getProperty().getValue());
}
}
});
}
The implementation is similar to the LanguageSelector or VariantSelector. When someone activates a hyperlink in the page template the iframe changes and the valueChange method retrieves the wrong value (ie. the event is from the previous page).
When someone activates a link, the PagesEditorSubApp#updateNodePath calls the updateLocationDependentComponents which calls the PageBar.onLocationUpdate. This calls in our case the VersionSelector#setCurrentVersion method. At this point I would need to reload the page detail subapp so that the listener is correctly set to the new page. I tried using the pageEditorPresenter.refresh() method in the setCurrentVersion method but it didn't do it.
In Magnolia 5.x you need to fire ContentChangeEvent to trigger the refresh (and hope that subapp you want to refresh listens to it, which in case of page detail subapp shouldn't be a problem).
Or, since you mention LanguageSelector, you can indeed try to call PageEditorPresenter directly as it does from info.magnolia.pages.app.editor.pagebar.languageselector.LanguageSelector#languageSelected, tho unless you need to modify something in the presenter (eg. locale in the example above), it seems rather unnecessary coupling of the code.
Once you are migrating your code to Magnolia 6.x and new UI framework, you have more convenient way of triggering notification of datasource change which all the views consuming data from given source listen to and facilitating refresh that way (as is shown eg in PasteComponentAction here.
Is there something like an onFocus() method, which I could override like the onDock() and onCreate() in the view class?
In the documentation there is only written about live reloading of views.
I tried combining that with, the onDock() and onCreate() method, but, even though it "works", it's not a very neat way of replicating onFocus behaviour.
Is there a simple way to have a "listener" method that's called when the view/fragment comes to front/on focus?
The View is a container, and not an UI element in the sense of the JavaFX context, so it cannot receive an onFocus callback. However, you can register one with the current window or even the root node of the View. If you're opening a window, you could register such an even with the currentWindow property. If you're not opening a window, you could register it with the root property of the View. Here is an example listening for a single focus change event from the currentWindow:
override fun onDock() {
currentStage?.focusedProperty()?.onChangeOnce {
}
}
I search all through the internet and all topics about taking control of the back button in views are saying same thing:
override protected function backKeyHandler():void
{
//Block native 'back' behavior.
}
But when I write this code into my views I always taking same error:
1020: Method marked override must override another method.
I look for this but didn't find a solution.
If the method isn't defined in some parent; then it can't be overriden. Just remove the 'override' keyword from your method:
protected function backKeyHandler():void
{
//Block native 'back' behavior.
}
This method will do nothing unless you add an event listener for it to be called. If you're using an MXML View, you can add your listener to the backKeyPressed event:
<s:View backKeyPressed="backKeyHandler()">
</s:View>
I'll add that this is for mobile applications only.
I can't comment on specific code you found on the Internet without actually knowing what that code or documentation was.
A good article about Back button issue: http://theorynine.com/labs/taking-control-of-the-back-button-in-views-adobe-air-flex-mobile/
Do I need to remove event listeners on AsyncResponder events?
i.e.
public function DeleteItem():void
{
var asyncResponse:AsyncResponder = new AsyncResponder(DeleteItem_Result, DeleteItem_Fail);
_myService.DeleteWorkout("test", asyncResponse);
}
private function DeleteItem_Result(event:Event):void
{
//If I do need to remove them, how do i remove the async responder event listeners?
}
If I do need to remove them, how do I do it?
Do I need to remove event listeners on AsyncResponder events?
No, you do not. If you are creating the AsyncResponder and using ot over and over again, then by all means leave the listeners in there.
However, in some cases, if you won't be reusing the component over and over; I would recommend you do remove the event listeners, as that will remove a dependency pointing at the asyncResponder which may allow it to be released for garbage collection as appropriate.
In the Adobe Flex Framework it is pretty common to add and remove listeners "as needed." We use the approach in the Flextras Calendar, for example, when dealing with effects. Before starting the effect we add some event listeners for 'effect end'. Those listeners are removed in that effect end method.
Update:
To remove an event listener you would use code similar to this:
asyncResponder.removeEventListener('result' ,UpdatePics_result);
asyncResponder.removeEventListener('fault' ,UpdatePics_fault);
I'd like to arrange things so that I have a chain of keyboard event handlers in my flex application, all of whom are queried when key down events occur. Basically, when a visual component is on screen, it is a candidate for handling a key press event. Something like this (clearly this is pseudocode):
<application handles_keys="F5, F6">
<tabGroup>
<tab1 handles_keys="pgup, pgdn">
<control handles_keys="0,1,2,3,4,5,6,7,8,9" />
</tab1>
<tab2 handles_keys="pgup, left, right"/>
</tabGroup>
</application>
I have a class written that will respond to the key events the way I want it to, so how do I register one or more instances of this class to have the results I want? Also, note that there are some situations where this class should receive events that would ordinarily be handled by a UI component. The TAB key is the main example; I have a few cases where I want my key down event handler to fire even when the focus is on a text field.
The way you have your pseudocode setup right now, you'd have to subclass all the different containers and add a handles_key property to each one. You may want to externalize the functionality to a separate class like this:
<KeyHandler target="{tab1}" handlesKeys="pgup,left,right"/>
As for actually catching the events, you'll need to add a KeyboardEvent.KEY_DOWN listener on the UIComponent you're wanting to listen to. You'll need to set the useCapture argument of addEventListener() to true as well. This will let you capture the event and prevent it instead of the event hitting the object and bubbling up.
target.addEventListener(KeyboardEvent.KEY_DOWN, target_onKeyDown, true);
Inside your target_onKeyDown event, check to see if you have a match for one of your keys you want to handle and if there is a match, call event.stopImmediatePropagation() or event.preventDefault() depending on what you need to do.
The Flex 3 Language Reference gives a good explanation of event propagation and keyboard events:
http://livedocs.adobe.com/flex/3/langref/flash/events/Event.html
The correct approach turns out to have been a global keyboard event manager, added as a key down listener to the stage when the application's creationComplete event is called. This then dispatches domain events for each keypress or combination thereof. Sadly, the filtering per-component model didn't work out.
I'm going to be porting this app to the Cairngorm framework, which should work really well once I'm done it.
when the displayed object is added to screen then start listen for stage keyboard events
when the object was removed from the screen the remove the keyboard event listener
on keyboard events filter the events you need :)
The code for a Canvas class you need should look like this:
class MyCanvas extends Canvas
{
public function MyCanvas(){
super();
}
override protected function createChildren():void{
super.createChildren();
this.systemManager.stage.addEventListener(KeyboardEvent.KeyUp, onKeyUpHandler);
}
private function onKeyUpHandler(e:KeyboardEvent):void{
// handle your code
switch(e.charCode){
case Keyboard.1:
case Keyboard.2:
case Keyboard.3:
case Keyboard.4:
case Keyboard.5:
case Keyboard.6:
case Keyboard.7:
case Keyboard.8:
case Keyboard.9:{
// do my stuff
break;
}
case Keyboard.F1:{
// do other stuff
break;
}
}
}
}
public function destroy():void{
//don't forget to remove listeners for stupid flash garbage collector
this.systemManager.stage.removeEventListener(KeyboardEvent.KeyUp, onKeyUpHandler);
}
}
Ignore any miss-spells :D I wrote the code from my mind :))