I want to dispatch a custom event when the two files are downloaded or uploaded successfully. I use
fileRef.addEventListener(Event.COMPLETE, completeHandler);
fileBigRef.addEventListener(Event.COMPLETE, completeHandler);
to listen the complete event with only 1 handler.
function completeHandler(event:Event):void{
var e:Event=new Event("addInfoDone");
dispatchEvent(e);
fileBigRef.removeEventListener(Event.COMPLETE,completeHandler);
fileRef.removeEventListener(Event.COMPLETE,completeHandler);
}
I want the event to be dispatched only once when both of the fileRef and fileBigRef are complete transfered. Any ideas?? My brain is fry now and can't think of anything..... Thanks for the help.
For a quick and dirty solution, how about defining a counter that increments each time completeHandler is fired. Once the counter reaches the number of files you're expecting (sounds like you're expecting 2), you fire your addInfoDone event:
var fileRefCounter:Number = 0;
function completeHandler(event:Event):void{
fileRefCounter++;
if(fileRefCounter == 2)
{
// both files have downloaded; fire your custom event, or whatever
}
}
Related
In order to verify that all changes made by the user have been saved I want to intercept the exiting/quitting of a JavaFX application.
Is there a common way-to-go to achieve this like overriding an event or is there more to it?
As they have already said, this is done by intercepting WindowEvent.WINDOW_CLOSE_REQUEST. You can then stop the suspension by calling event.consume().
This is an example of how to capture the event and display a confirmation dialog. Depending on the user's choice, you can take serialization actions if you wish.
primaryStage.setOnCloseRequest(event -> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.initOwner(primaryStage);
alert.initModality(Modality.APPLICATION_MODAL);
alert.setHeaderText("Exit");
alert.setContentText("Do you want to exit?");
alert.getDialogPane().getButtonTypes().setAll(ButtonType.OK, ButtonType.NO);
Optional<ButtonType> optional = alert.showAndWait();
if(optional.isPresent() && optional.get() == ButtonType.OK) {
// save data
return;
}
event.consume();
});
In order for the implementation to be complete, you need to implement a logic for clear exit from the application from control. For example, when choosing from the File menu -> Close. When capturing the event, you must run WindowEvent.WINDOW_CLOSE_REQUEST to trick the exit logic.
closeMenuItem.setOnAction(event -> {
Window window = menuBar.getScene().getWindow();
window.fireEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSE_REQUEST));
});
In the class Application there is the stop method which you can override possibly.
The code bellow generates an Alert Dialog with two buttons, Ok and Cancel; and it also works as expected: if I click Ok, the system exits, otherwise the dialogs vanishes.
The strange thing is: if I ommit the else block handling the event, the platform will always exit, not considering the button I clicked.
Is that really the expected behaviour? Am I missing something?
private void setCloseBehavior()
{
stage.setOnCloseRequest((WindowEvent we) ->
{
Alert a = new Alert(Alert.AlertType.CONFIRMATION);
a.setTitle("Confirmation");
a.setHeaderText("Do you really want to leave?");
a.showAndWait().ifPresent(response -> {
if (response == ButtonType.OK) {
Platform.exit();
} else {
we.consume();
}
});
});
}
Here is the documentation for windows.onCloseRequest:
Called when there is an external request to close this Window. The installed event handler can prevent window closing by consuming the received event.
So, if you don't consume the close request event in the close request handler, the default behavior will occur (the window will be closed).
You don't really need to invoke Platform.exit() in the close request handler because the default behavior is to exit, so you could simplify your logic. You only need to consume the close request event if the user does not confirm that they want to close:
stage.setOnCloseRequest((WindowEvent we) ->
{
Alert a = new Alert(Alert.AlertType.CONFIRMATION);
a.setTitle("Confirmation");
a.setHeaderText("Do you really want to leave?");
Optional<ButtonType> closeResponse = alert.showAndWait();
if (!ButtonType.OK.equals(closeResponse.get())) {
we.consume();
}
});
There is a similar fully executable sample in the answer to the related StackOverflow question:
How can I fire internal close request?.
I'm building a Flex app which requires me to download files.
I have the following code:
public function execute(event:CairngormEvent) : void
{
var evt:StemDownloadEvent = event as StemDownloadEvent;
var req:URLRequest = new URLRequest(evt.data.file_path);
var localRef:FileReference = new FileReference();
localRef.addEventListener(Event.OPEN, _open);
localRef.addEventListener(ProgressEvent.PROGRESS, _progress);
localRef.addEventListener(Event.COMPLETE, _complete);
localRef.addEventListener(Event.CANCEL, _cancel);
localRef.addEventListener(Event.SELECT, _select);
localRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _securityError);
localRef.addEventListener(IOErrorEvent.IO_ERROR, _ioError);
try {
localRef.download(req);
} catch (e:Error) {
SoundRoom.logger.log(e);
}
}
As you can see, I hooked up every possible event listener as well.
When this executes, I get the browse window, and am able to select a location, and click save. After that, nothing happens.
I have each event handler hooked up to my logger, and not a single one is being called! Is there something missing here?
The problem seems to be with my command being destroyed before this could finish.
For a proof of concept, I set my localRef variable to be static instead of an instance variable, and everything went through successfully! I guess Cairngorm commands kill themselves asap!
I am trying to learn Flex and now i have the next code: http://pastebin.com/rZwxF7w1
This code is for my login component. I want to get a special string for encrypting my password. This string is given by my authservice. But when i login i get a multiple times a alert with Done(line 69 in the pastebin code or line 4 in the code on the bottom of this question). But i want that it shows one single time. Does someone know what is wrong with this code?
Tom
protected function tryLogin():void {
encryptStringResult.addEventListener('result', function(event:ResultEvent):void {
var encryptString:String = event.result.toString();
Alert.show('Done');
});
encryptStringResult.token = auth.getEncryptString();
}
It's possible that tryLogin is called multiple times, meaning that you'd be adding multiple event handlers that does the same thing to the same event.
You could try the following:
protected function tryLogin():void {
if (encryptStringResult.hasEventListener('result'))
return;
encryptStringResult.addEventListener('result', function(event:ResultEvent):void {
encryptStringResult.removeEventListener('result', arguments.callee);
var encryptString:String = event.result.toString();
Alert.show('Done');
});
encryptStringResult.token = auth.getEncryptString();
}
It will first check wether or not there already is an event listener for 'result' in which case it will simply return. Also, it will remove the (anonymous) event listener that gets added when the event has been dispatched.
I used Flash player 10, and Flex SDK 3.4. The code as followings:
// Following comes callbacks
function imageLoadOpenCallback(evt:Event):void
{
trace("in--open");
}
function imageLoadCompleteCallback(evt:Event):void
{
trace("in--load");
var fr:FileReference = evt.target as FileReference;
trace(fr.data);
}
function imageLoadErrorCallback(evt:IOErrorEvent):void
{
trace("in--ioerror");
}
function imageSelectCancelCallback(evt:Event):void
{
trace("in cancel");
}
function imageSelectCallback(evt:Event):void
{
trace("in -- select");
for (var i:int=0; i<frl.fileList.length; i++)
{
frl.fileList[i].addEventListener(Event.OPEN, imageLoadOpenCallback);
frl.fileList[i].addEventListener(Event.COMPLETE, imageLoadCompleteCallback);
frl.fileList[i].addEventListener(IOErrorEvent.IO_ERROR, imageLoadErrorCallback);
frl.fileList[i].load();
trace(frl.fileList[i]);
trace(frl.fileList[i].creationDate);
trace(frl.fileList[i].creator);
trace(frl.fileList[i].data);
trace(frl.fileList[i].name);
}
}
// Following comes UI handlers
function onAddPictures():void
{
var imageFilter:FileFilter = new FileFilter("Images", "*.jpg;*.png");
frl.addEventListener(Event.SELECT, imageSelectCallback);
frl.addEventListener(Event.CANCEL, imageSelectCancelCallback);
frl.browse([imageFilter]);
}
Only the imageSelectCancelCallback handler get called when I select some files in the dialog. But no load/open/io_error handler get called at all. I have Google some code example, in which it used FileReference instead of FileReferenceList. I don't know the reason, could you please help me?
In Air the fileReference objects in fileReferenceList do not fire the complete event when doing fileList[i].load(). In a Flex project it works fine. Adobe has not responded to bug reports on this appropriately.
Make sure in your compiler settings for flex, that you have at least 10.0.0 for "Use a specific version".
The main reason to use FileReferenceList instead of FileReference would be if you need to upload multiple files at once. If you only want to allow uploading one file at once, simply use FileReference.
Some clarification: imageSelectCallback(), and NOT imageSelectCancelCallback(), should get called when you select some files in the file browser AND click OK. imageSelectCancelCallback() is only called when you click Cancel.
Other than that, I never used the load() API, but I did use the upload(URLRequest) API. I am not sure what's your use case, but if you need to upload an image to a server, you should use the upload() method.
Speaking of upload events, I experienced some reliability issues when listening to Event.COMPLETE events, so I actually got better results listening to DataEvent.UPLOAD_COMPLETE_DATA.