Flex Mobile Back Button - apache-flex

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/

Related

Tornadofx onFocus listener

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 {
}
}

how to get event type that is fired

I am working on Flex project these days and having java background. In my current task, same pop up is opened when two different types of custom events are being fired and I have to hide a button for one event type. So, how i can get event type.
Thanks in advance.
The Event class has a property called type wich is a string stating what kind of event it is.
function eventHandler(event:Event):void {
trace(event.type);
}
Generally speaking, you can get it this way:
mc.addEventListener(MouseEvent.CLICK, myMethod);
function myMethod(evt){
trace(evt.type);
}

Qt-Right click mouseReleaseEvents aren't caught by eventfilter,other events though are caught

My application consists of a WebView widget. A mouse click on the widget is not handled by the mousePressEvent() of my application, but by the WebView widget. So, I installed an event filter to receive the events. Now, I get notified of all events, except the mouseReleaseEvent for the right click (Everything works fine for left clicks and mousePressEvent for the right click is also getting registered). I guess it has got something to do with context events getting generated by right clicks (a pop-up menu gets generated). But since I am using a filter, the event should first be sent to me. The following is the code for the event filter
in Jambi, but I hope I can modify an answer given in Qt for Jambi.
public boolean eventFilter(QObject o,QEvent event)
{
if (event.type()==QEvent.Type.MouseButtonPress) // One can call the mousePressEvent() functions from here,which can do this work but speed
{
if (((QMouseEvent)event).button()==Qt.MouseButton.LeftButton)
{
mousebuttontype=1;
clickedorpressed=1;
}
else
if (((QMouseEvent)event).button()==Qt.MouseButton.RightButton)
{
mousebuttontype=2;
System.out.println("right");
}
t1=QTime.currentTime();
t1.start();
}
else
if (event.type()==QEvent.Type.MouseButtonRelease)
{
if (t1.elapsed()>900)
{
switch(mousebuttontype)
{
case 1: browser.back();
break;
case 2: browser.forward();
break;
}
}System.out.println("choda");
}
return false;
}
MY BASIC AIM IS GETTING THE TIME INTERVAL FOR WHICH THE RIGHT CLICK WAS PRESSED. ANY WORKAROUND ?
Some digging around certainly seems to suggest that there may be no right-mouse release event being generated if that is the trigger for a context menu on your particular system. These are conveyed as a QContextMenuEvent.
This Qt Labs post hints about this too.
A work around may be tricky if it is system dependent. Have you tried overriding event() in the QApplication class to see if the event comes through there? Some events don't necessarily get to the children but everything goes through QApplication::event().
Another option for you is, subclass Qwebview and override mouseReleaseEvent event
I've found a fix for this that I dont think will be system dependent.
My particular case was using mouseReleaseEvent in order to catch the events, and use them myself. I didn't get these events.
On all child widgets of the widget that I want to handle the event, I added to the class definition:
protected:
void mouseReleaseEvent(QMouseEvent *event) {event->ignore();}
This overrides the default implementation for context menu's, and sends the mouseReleaseEvent back up the parent chain like it would for other mousebuttons.
http://doc.qt.io/qt-5/qevent.html#ignore
This shows that it will probably propagate to the parent widget. As the link indicates, this fixed it for me at Qt 5.9, but I think it should work for virtually all version.
(I am aware this question is literally 7 years old, but it doesn't contain the fix that I think would be the best fix, and shows up as result 2 on google(qt not getting mouse release event on rightclick). So I think it deserves an up to date answer.)
Without going in to broader implementation explanations, the core problem I needed to solve related to this issue was that I needed to know if a context menu swallowed the right-click so I could ensure some custom state was handled properly. The simplest workaround I was able to find was to implement contextMenuEvent, which gets called after mousePressEvent, to detect if the event was accepted (a context menu was opened somewhere in my QGraphicsScene/Items). Here is a minimal example in Python to demonstrate how the event state might be used:
def contextMenuEvent(self, event):
event.setAccepted(False)
super(MyGraphicsView, self).contextMenuEvent(event)
self.__context_menu_used = event.isAccepted()
Note you can also skip running the the base class contextMenuEvent entirely to block the scene/items from opening a context menu. This is handy if you want to do 3D-DCC-like alt-RMB-zooming without accidentally opening a context menu, e.g.:
def contextMenuEvent(self, event):
# Block context menus if alt is held down
if event.modifiers() & QtCore.Qt.AltModifier:
return
event.setAccepted(False)
super(MyGraphicsView, self).contextMenuEvent(event)
self.__context_menu_used = event.isAccepted()

Flex 3 keyboard event handling

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 :))

Error #2099: The loading object is not sufficiently loaded to provide this information

I have a Flash app made up of AS3 components that I am trying to run in Flex.
In Flash, after the main component is added to the stage, the loader object (loaderInfo.loader) is null which is fine and I handle that.
In Flex, on the applicationComplete event I add the the main component to the stage and the loader object's getter throws an exception - Error #2099: The loading object is not sufficiently loaded to provide this information.
Also, the INIT event, which is dispatched when the properties and methods of a loaded SWF file are accessible, is not firing which is probably part of the problem. But I can't figure out why it is not being dispatched.
Any ideas why the same code has two different results?
Mmm, that seems like a frustrating problem. When you say "main component", I presume you mean the document class in Flash?
I'm not sufficiently knowledgeable about flex to comment on the problem you described, but I can suggest that you try using ADDED_TO_STAGE instead of INIT as your event...
public class MainFlashClass extends Sprite {
public function MainFlashClass() {
addEventListener(Event.ADDED_TO_STAGE, onInit);
}
public function onInit(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, onInit);
// do your initialisation code here
}
}
This might work for both scenarios. I've found ADDED_TO_STAGE to be more helpful because it always gets fired, whether the class is already loaded when the swf is executed (like the document class), or if it's being loaded with a Loader.
I'm not sure if this is what's going on with INIT event, but I do know that in flash player 9, which I'm assuming is the version of your SWF? There's a bug with referencing the loader through its own evt target. Basically if you are loading something and you try and access properties of the loader though evt.target.loaderInfo.loader it never can find itself and throws the error you described in your question. I believe it's a known bug for flash player 9 that was fixed with the release of CS4 and flash player 10.
Here's a link to a thread describing some of the problem, hopefully it helps
http://www.actionscript.org/forums/showthread.php3?t=137599
You definitely need to post code so we an see better.
With that said, after addChild are you attempting to grab the loaderInfo for the "main component" or for your mx:Application?
Pseudo
//onApplicationComplete event handler
var myswf:SWFLoader = new SWFLoader();
myswf.load(...);
addChild(nmyswf);
trace(myswf.loaderInfo.loader);
//end onApplicationComplete
Is that what you're doing? If so, you need to add an event listener to your "main component" (assuming an externally loaded swf) to find out when Event.COMPLETE happens.
var myswf:SWFLoader = new SWFLoader();
myswf.addEventListener(Event.COMPLETE, onMySWFComplete);
//..rest of code
Hope that helps. If not, post code.

Resources