I'm trying to get the IFrameCommTest example (from the Flex-IFrame site) to work in Flex 4, and, while the IFrame itself works, the communication does not. In particular, I need to get the included HTML page to call functions from the flex app (I already have a way to get the Flex app to talk to the HTML).
I've exported the project to facilitate your help.
The problem, I suspect, is that the "parent.FABridge" doesn't exist. My guess is that something in flex4 changed with regard to how things are located in the DOM.
(This post is related to the earlier post about FABridge.
I thought this would be a clearer example of the problem. )
Thanks,
Brian
I've solved this my own self :D
The difference over the mechanism above is in the getFlexApp() function, and it provides a way to, well, get the flex object. Once the objecty it gotten, I just call the EIButtonClicked() function, and pass a value to it.
function getFlexApp(appName) {
if (navigator.appName.indexOf ("Microsoft") !=-1) {
return window.top[appName];
} else {
return window.top.document[appName];
}
}
function callFlexFunction() {
var sTxt ;
sTxt = document.getElementById('txt1').value;
alert('HTML/Javascript wants to tell you about ' + sTxt);
getFlexApp('iframeCommTest').EIButtonClicked(sTxt) ;
}
Meanwhile, the flex side has an external interface callback established. You can see that the "EIButtonClicked" referenced in the JS above is matched by the label for the callback in the AS below.
/**
* When the button is clicked.
*/
public function onEIButtonClicked(data:String):void {
Alert.show("Flash wants to tell you about " + data);
}
protected function application1_creationCompleteHandler():void {
// TODO Auto-generated method stub
if (ExternalInterface.available) {
ExternalInterface.addCallback("EIButtonClicked", onEIButtonClicked);
}
}
Related
Google's new DayDream samples are using the Event System to detect if the pointer is on an object.
Previously it wasn't working like that at all, it was a reticle, and you would then create a Raycast between the Camera and the reticle, such as:
Vector3 rayDirection = GvrController.Orientation * Vector3.forward;
if (Physics.Raycast(origin, rayDirection, out hitInfo, Mathf.Infinity)) {
And then you detect if a specific Object is between the reticle and the Camera.
This way doesn't exactly work anymore. Google is now using the event system, and then checking if the reticle is positioned on an object.
Is there a way for me to check that for any object without using the Event System.
The Event System is a good method, it's just I have about 40 different objects that all work the same way, and implementing an event point/click for these 40 different objects seems like an overkill when previously I could just check an object by tag.
Anyone was able by any chance to be able to detect if the pointer is positioned on an object without using the Event system?
Raycasts don't seem to properly work anymore as the pointer seems to be more of a 2D object, just like a Mouse.
This works approximately, but not very well:
Vector3 origin = Head.transform.position + GvrController.ArmModel.wristPosition;
Vector3 rayDirection = GvrController.ArmModel.pointerRotation * Vector3.forward;
Any help would be appreciated :)
If you don't want to use EventTrigger component, you can simply use your same old script and implement IPointerEnterHandler, IPointerExitHandler, OnPointerClickHandler etc and use same compare tag method for every object.
I think its much more easy to use than custom raycast. As there is always a Graphics Raycaster (or Physics Raycaster for 3D Objects) at work so why not use what it has to offer.
public class MyOldScriptWhichUsedRaycasting: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
public void OnPointerEnter (PointerEventData eventData)
{
if(gameObject.CompareTag("Grabable"))
{
//do stuff here.
}
}
public void OnPointerExit (PointerEventData eventData)
{
if(gameObject.CompareTag("Grabable"))
{
//do stuff here.
}
}
public void OnPointerClick (PointerEventData eventData)
{
if(gameObject.CompareTag("Grabable"))
{
//do stuff here.
}
}
}
Hope this helps
I can't catch the thrown error in my simplified code below. Why is that?
According to requirements of the stackoverflow I must insert some more info but this example is very simple. Can you help me with this example?
package com.myserver {
public class ReturnInfo extends Sprite {
public function ReturnInfo(urlParamsArr:Array) {
try {
var client:HttpClient = new HttpClient();
var uri:URI = new URI("http://valid-url.com/aaa.php");
client.listener.onData = function(event:HttpDataEvent):void {
throw new Error();
};
client.listener.onError = function(event:IOErrorEvent):void {
trace("error");
};
client.postFormData(uri, variables);
}
catch (e:Error){
trace("Error was caught.");
}
}
} //class
} //package
I tried also:
try {
new ReturnInfo(urlParamsArr);
}
catch(e:Error){
trace("caught error");
}
It didn't work either.
The code does not work because the code that throws error is executed later, so you need to use try-catch in the client.listener.onData handler. That handler I assume is called sometimes later so there when you parse or handle the data,make sure to catch/handle the errors
Adding on to what Simion said, the problem is method closure. In order for an exception to be caught somewhere in the "food chain" the catch needs to be in the stack - you will know what is in the current stack by getStackTrace(). In this example, there is no stack pointer that sits at the constructor (or any method) like there is one for client.listener.onData - which is why the postFormData will execute. When the event is triggered it's stack pointer goes back to the origination point of what actually started the event trigger in the first place (not the method that declared it). This is also why the 2nd attempt was unsuccessful.
Add on to the fact that the FP executes discrete chunks in frames (think of this like a heap), anything that executes in the scope of the dispatchEvent will generally have a very small or no stack at all (eg the first stack pointer is usually the dispatcher itself - not a method that actually called it).
try-catch is best attempted within the same scope of a method.
A pseudo example:
function getOrCreateWidget():Widget {
var a:Widget;
try {
a = getWidet();
}
catch(e:TypeError) {
a = createNewWidget();
}
//finally can be debatable - most of us leave it off
//bc it executes anyway just as it would in the function scope.
finally {
a.property = 'foo';
}
return a;
}
If this isn't possible - a last ditch effort is to attach a listener to the loaderInfo.uncaughtErrorEvents. Generally associating this with the systemManager is the best option because the SM knows about every branch of the display tree right down to the root stage. It's neither good practice nor practical to assign all deviations in this method because a lot of context to the programmer is usually lost. It's more an "oh S#!) sorry user, our app just verped."
Sorry for my english, but I have the next problem. I am writing a window manager using Qt 4.7 and Xlib. I have class Manager that inherits QApplication and reimplemented method X11EventFilter in it. In X11EventFilter method I catch necessary events from XServer. When I receive MapRequest event, I catch appearing of new window and reparent it to my own widget. And when I create that widget and call QWidget::show() or QWidget::winId() methods, program crashes. What is the problem?
Here is a method where widget is creating. I wonder, when this function calls few times on start of program, everything is OK.
void Manager::createClientWindow(Qt::HANDLE pWinID)
{
QMWindowWidget *lWindowWidget = new QMWindowWidget(pWinID);
/*some code*/
lWindowWidget->show();//crash is here
Qt::HANDLE widgetId = lWindowWidget->winId();//and here
/*some code*/
}
Here is a x11EventFilter method where createClientWindow function is called
bool Manager::x11EventFilter(XEvent *pEvent)
{
switch(pEvent.type)
{
/*some code*/
case MapRequest:
{
Qt::HANDLE lWindow = pEvent->xmaprequest.window;
QMWindowWidget* lWidget = findWidget(lWindow);
if (!lWidget)
{
lWidget = dynamic_cast<QMWindowWidget*>(QWidget::find(lWindow));
}
if (lWidget)
{
XMapWindow(QX11Info::display(), lWindow);
lWidget->show();
XRaiseWindow(QX11Info::display(), lWidget->winId());
return true;
}
else
{
createClientWindow(lWindow);//here is where function is called
return true;
}
}
break;
/*some code*/
} //switch
return false;
}
The problem most likely resides in the code represented by /*some code*/. Since it is not known what's there, it's very difficult to pinpoint the exact cause of the problem. If you cannot show all the code, you will have to track the problem down yourself.
You will need to build in debug mode and link with the debug version of Qt. Then when the crash happens, look at the exact line of Qt source and analyse the broken data structures with a debugger and try to figure out why they are broken. Maybe set a watchpoint on a problematic variable and find out what code writes an invalid value there.
In order to program in low level languages such as C and C++ one has to learn how to do this stuff.
Problem is resolved! I paste this two strings before QApplication::exec()
XClearWindow(QX11Info::display(), QX11Info::appRootWindow());
XSync(QX11Info::display(), false);
I use a unit of work pattern a lot in my flex projects. I'll have a class that might call a web service, put the data in a sqlite db, refresh a model with the data then raise an event.
I usually call these inline and pass in some singleton classes:
protected function CareerSynced():void
{
var process:ProcessWorkouts = new ProcessWorkouts(_dataModel, _trainerModel, _databaseCache, _database.Conn);
process.addEventListener("AllWorkoutsProcessed", AllWorkoutsProcessed);
process.UpdateAllUnprocessed();
}
I'll then get the response like this:
private function AllWorkoutsProcessed(event:DataReceivedEvent):void
{
//do something here
}
My question is, am I adding that event listener correctly? I think I might be causing a memory leak, but I'm not sure. I've also thought about using a weak reference. I'm confused about when to use them. Would this be one of those cases?
Should it be like this?
process.addEventListener("AllWorkoutsProcessed", AllWorkoutsProcessed,false, 0, true);
I would either go with the weak reference or just remove the listener:
private function AllWorkoutsProcessed(event:DataReceivedEvent):void
{
event.target.removeEventListener("AllWorksoutsProcessed",AllWorkoutsProcessed);
}
I could list out my reasons but I'll just point you to this.
I have a flex app that used to be an internet based app. In it I have a function that creates tooltip error messages when I tell it to create an error message. I pulled this app out verbatim to a desktop app and restructured things a bit to get it to run, but I did not mess with the core fundamentals of the mxml file that utilizes this aside from changing the root tag from a type of 's:Group' to 's:Window'
Everything runs correctly, but the tooltips are not displaying. I can't seem to figure out why, so I thought I'd run this by you guys. Here's the tooltip code (inline mxml code in the fx:script cdata tag):
import mx.controls.ToolTip;
import mx.managers.ToolTipManager;
public var errorTip:ToolTip;
private function createErrorMsg(errorMsg:String, object:Object):void {
if (errorTip){ToolTipManager.destroyToolTip(errorTip);};
errorTip = ToolTipManager.createToolTip(errorMsg,object.getBounds(root).x + object.width,object.getBounds(root).y) as ToolTip;
errorTip.setStyle("styleName", "errorTip");
errorTip.visible = true;
errorTip.enabled = true;
}
Basically, I pass the function a string and an object (text input, checkbox, button, etc...etc...) and it positions it and displays the error message. This fully works in my web version, but not in my desktop version.
Here's the code that instantiates the window:
var window:LoginWindow = new LoginWindow();
Window.systemChrome = NativeWindowSystemChrome.NONE;
Window.transparent = true;
Window.open(true);
Window.maximize()
Any ideas?
On a side note, I check to see if the errorTip exists at the beginning of the function and then destroy it so that the higher scoped variable 'errorTip' always equals the reference to the currently displayed error. This allows me to just destroy that error tip on form validation and then error check again, but it only allows one tooltip to be displayed at a time. Is there a better way to query the tooltip manager for all of it's currently displayed tooltips and destroy them all?
To resolve this you must change the line that calls 'createTooltip' to the following:
errorTip = ToolTipManager.createToolTip(errorMsg,object.getBounds(root).x + object.width,object.getBounds(root).y, null, object as IUIComponent) as ToolTip;
The idea behind this is that you can now just call 'createErrorMsg("myError",myComponent)' and it'll display an error message there, which you can then add another function:
private function clearError():void
{
if(errorTip) errorTip.visible = false;
}
to actually remove the error message. The down side of this is that it only displays one message at a time but I'll tweak it a bit to change that up. So here's my better resolution:
Error messages will (traditionally) only be displayed in a batch set. (Basically you will only have a handful of tooltips displayed at one point in time and they will all be related to the form you are on). This won't always be true, but that's not my concern here. I created a utility class that performs error message handling:
package Utils
{
import mx.controls.ToolTip;
import mx.core.IUIComponent;
import mx.managers.ToolTipManager;
public class ErrorUtils
{
private static var errorCache:Array = new Array();
public function ErrorUtils()
{
}
public static function createErrorMsg(errorMsg:String, object:Object):void {
var errorTip:ToolTip = ToolTipManager.createToolTip(errorMsg,object.getBounds(object.root).x + object.width,object.getBounds(object.root).y, null, object as IUIComponent) as ToolTip
errorTip.setStyle("styleName", "errorTip");
errorTip.visible = true;
errorTip.enabled = true;
var position:int = errorCache.length;
errorCache.push(errorTip);
}
public static function clearAllErrors():void
{
for each(var error:ToolTip in errorCache)
{
ToolTipManager.destroyToolTip(error);
}
}
}
}
To use the class you simply call ErrorUtils.createErrorMsg("my message",invalidComponent), and to clear the errors you simply call ErrorUtils.clearAllErrors()
That way if you have a form and you have a validation function for it, you simply call that function every time it comes back as invalid. The only thing that this is missing is any kind of way to clear a specific error, but to handle that you could place all of the creation calls inside of a master validation function that validates all the fields in your form, then call that each time you gain or loose focus on a field and call 'ErrorUtils.clearAllErrors()' at the beginning of the function.
BTW:
this is the source of the original tutorial I received to do this, I just abstracted it a bit
http://aralbalkan.com/1125
so credits go to the above site for the original code