AS3 Project - Mouse Move Listener Reacting Outside of Application - apache-flex

I'm getting an unusual behavior that I can't seem to get to the bottom of. When I run this, if I move in the swf area it traces normally on mouse move. To be expected.
But it's tracing for the move event when I click anywhere on screen. If I click and drag, it traces as if I were moving in the swf area of the browser.
Here's the code. I've simplified to it's barebones. Just put this in in an empty AS3 project in Flex called "Engine" - sans quotes obviously.
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
[SWF(width='640', height='360', backgroundColor='#888888', frameRate='31')]
public class Engine extends Sprite
{
public function Engine()
{
// Add the mouse handlers
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
public function mouseMoveHandler(evt:MouseEvent):void
{
trace("move");
}
}
}
As a workaround I've add the MOUSE_MOVE one MOUSE_OVER and remove it on MOUSE_OUT. But the behavior still seems quite unusual and I'd be interest in understanding why it's happening.
Can anyone tell me how I can keep the events constrained to the actual stage of the application?

As already mentioned, you can't stop these events from firing. They are triggered until you release the mouse.
What you can do is compare the coordinates of the MouseEvent with the bounds of the stage and ignore those outside.
public function mouseMoveHandler(evt:MouseEvent):void
{
if (evt.stageX >= 0 && evt.stageX <= stage.stageWidth &&
evt.stageY >= 0 && evt.stageY <= stage.stageHeight)
{
trace("move");
}
}

If you click inside your flash movie and drag the mouse outside of it, MOUSE_MOVE event will continue to trigger until you release your mouse. MOUSE_LEAVE will trigger only when you release the mouse outside the player. This is how Flash Player works.
Maybe I'm wrong but I don't think you can change this behaviour.

Ok, This is a known bug that only happens with Mac.
There is a fix here :
http://www.visible-form.com/blog/transformmanager-fix-for-mac-firefox/

Related

Make JavaFX window active

I am trying to make a JavaFX application (running in the background to show up (set visible)) by a specific keystroke and to make the window the active window immediately. Therefore I set the primary stage alwaysOnTop-property true, call stage.toFront() and finally call stage.requestFocus(). Afterwards I request focus for a text field. When the window is made visible I would like to instantly start typing into the text field.
However, when I for example have a Ubuntu-terminal selected and make the window visible and start typing, the application is shown on top of everything, however, the typing goes to the terminal. The application window is not active! Nevertheless, the focused property of the stage is true. Is that a bug or am I missing something? Is it OS related?
Edit: I am willed to give my little hack-around for this problem that I am using at the moment, because the internet is suggesting, that a lot of people are facing this problem: Since I am working on a linux maschine I have access to the wonderful tool wmctrl. It is part of most standard repositories. wmctrl -a WINDOWNAME sets the window with the name WINDOWNAME active. For now, I simply call this tool from my source code when I need the window to be active. Since this is more of a dirty hack than any thing else, I sure want to get rid of it.
Not perfect, but it works:
Platform.runLater(() ->
{
//primaryStage.setAlwaysOnTop(true);
//primaryStage.setAlwaysOnTop(false);
primaryStage.setIconified(true);
primaryStage.setIconified(false);
});
If your node is not getting focused, try wrapping requestFocus() in a Runnable and call Platform.runLater():
final TextField text = new TextField();
Platform.runLater(new Runnable() {
#Override
public void run() {
text.requestFocus();
}
});

Adobe Flex PopUpManager -- multiple instances of a TitleWindow opened

Setup: My Flex application is one consisting of several "subapps". Basically, the main application area is an ApplicationControlBar with buttons for each of the subapps. The rest of the area is a canvas where the subapps are displayed. Only one subapp is visible at a time. When switching between subapps, we do a canvas.removeAllChildren(), then canvas.addChild(subAppSwitchedTo). It's essentially a manual implementation of a ViewStack (the pros and cons of which are not the topic of this, so refrain from commenting on this).
Problem: In one of my subapps (let's say subapp "A"), I have a search function where results are displayed in a TitleWindow that gets popped up. Workflow is like enter search criteria, click search button, TitleWindow pops up with results (multiple selection datagrid), choose desired result(s), click OK, popup goes away (PopUpManager.removePopUp), and continue working. This all works fine. The problem is if I switch to a different subapp (say "B" -- where A gets removeAllChildren()'d and B gets added), then switch back to A and search again, when the results TitleWindow pops open, there will be TWO stacked on top of each other. If I continue to navigate away and back to A, every time I search, there will be an additional popup in the "stack" of popups (one for each time A gets addChild()'d).
Has anyone else experienced this? I'm not sure what to do about it and it's causing a serious usability bug in my application. Does this ring any bells to anyone? It's like I somehow need to flush the PopUpManager or something (even though I'm correctly calling removePopUp() to remove the TitleWindow). Please help!
EDIT
Flex SDK = 4.5.1
// Subapp "A"
if (!certificateSearchTitleWindow)
{
certificateSearchTitleWindow = new CertificateSearchTitleWindow;
certificateSearchTitleWindow.addEventListener("searchAccept", searchOKPopupHandler);
certificateSearchTitleWindow.addEventListener("searchCancel", searchClosePopupHandler);
}
PopUpManager.addPopUp(certificateSearchTitleWindow, this, true);
My guess is that the popup is removed from the main display list when you remove its parent (this in the PopUpManager.addPopup() method), but not from its parent display list. Why don't you listen, in your subapps, to the Event.REMOVED event, and then remove your popup ? That would be :
private var pp:CertificateSearchTitleWindow;
private function onCreationComplete():void
{
addEventListener(Event.REMOVED, onRemovede);
}
private function addPopUp():void
{
if (!pp) {
pp = new CertificateSearchTitleWindow();
PopUpManager.addPopUp(pp, this, true);
}
}
private function onRemoved(event:Event):void
{
if (pp) {
PopupManager.removePopUp(pp);
pp = null;
}
}
Thank you to those who gave suggestions. It turned out I was re-registering an eventListener over and over.
I am using a singleton to act as "shared memory" between the subapps. I was setting singleton.addEventListener(someType, listener) in subapp A's creationComplete callback. So everytime I navigated back to A, the creationComplete was running and re-adding this listener. After the search, the listener method (that opened the popup) was being called multiple times, i.e., as many times as the event had been added.
xref: http://forums.adobe.com/message/3941163

Flex: Lose Component Focus

I have a (hopefully) quick question. I've got some stepper boxes. Though really this could apply to any interactive component. I want the selected box to lose focus when when I click anywhere else ( stage included ). Is there an easy way to do this? I can't seem to find an effective way to make it lose focus.
In case anyone else finds their way here seeking a solution to this problem, here is the answer:
private function onGlobalMouseUp(event : MouseEvent) : void {
var fm:FocusManager = new FocusManager(stage);
//Since Flash Player can set focus on subcomponents as well as on components themselves,
//findFocusManagerComponent is used to find the component that either has focus or contains the subcomponent
//that has focus. If, for example, a TextField contained within a TextArea component has focus, findFocusManagerComponent
//will return the TextArea component, and not the TextField. This being the case, we can definitely determine
//whether the target object of the MouseUp event is a component (or is part of a component). If the target
//object is NOT a component (nor contained within one), then we clear all component focus.
if(fm.findFocusManagerComponent(event.target as InteractiveObject) is UIComponent){
//target of MouseUp is either a UIComponent, or is contained within a UIComponent, so do nothing.
}else{
//target of MouseUp is neither a UIComponent, nor is it contained within a UIComponent, so set component focus to null.
fm.setFocus(null);
}
}
So here's the solution I've come up with that works very well. I have a function called add() which has been assigned to applicationComplete. In that function I include:
this.skin.addEventListener( MouseEvent.MOUSE_UP, loseFocus );
Which calls:
private function loseFocus( e : MouseEvent ) : void
{
if ( e.eventPhase == EventPhase.AT_TARGET )
{
this.focusManager.deactivate();
}
}
Simple enough, and does what I was looking for. "Phase" filter is necessary to keep other components from registering the clicks.
As an important note: this.skin needs to be the event target. The stage is never exposed to the mouse in a Flex application.
Example Application Code
If someone has a better solution, please suggest one!
Perhaps you should check out FocusManager.hideFocus().
Maybe tie it into the focusOut event of your UIComponent.
Flex API

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: cannot resize player back from Full Screen

The key event is not listened by my Flex app. Since it is really simple code, I cannot understand where the problem is...
init() {
stage.addEventListener(KeyboardEvent.KEY_DOWN, escHandler);
}
private function escHandler(event:KeyboardEvent):void {
debugF.text = "ESC pressed";
}
thanks
I'm not sure I fully understand your question, but a lot of the user interaction events (including keyboard) are disabled when Flash is in fullscreen mode. Escape is automatically handled by Flash to exit out of fullscreen. I don't believe it will be passed to your listeners.

Resources