I would like to create a button that the user can press during model execution which stops the model and begins running it again from time = 0.
The following code does work, but only some of the time and will sometimes work for two or three presses of the button before the model just hangs.
pauseSimulation();
stopSimulation();
getExperiment().stop();
((Simulation) getExperiment()).button.action();
getExperiment().run();
This sometimes is associated with getEngine().getState() = PLEASE_WAIT, but not always.
I don't know if it's a timing issue, or that I should be doing things is a slightly different order, or with different phraseology.
Any pointers greatly appreciated.
In your button action use
getExperiment().stop();
In your simulation experiment properties, in the Java Actions section, add the following to After Simulation Run:
run();
Related
Good day,
Currently, there are 6 edit boxes, which are connected to specific parameters in the model (and the user can edit these boxes in the model runtime) and a button that doesn't do anything. I want to make this button to restart the simulation, yet if the user previously changed some contents in edit boxes, the new simulation will run based on the user input values. The model name is Simulation.
If anyone knows an example (or specific code) it would be highly appreciated.
Adding to Artem's reply on issue 1: it is actually possible, but you will create a new thread, so a bit advanced. This code will stop the current experiment and restart it:
new Thread() {
public void run() {
getExperiment().stop(); // stops the model
getExperiment().run(); // runs it again
getExperimentHost().setPresentable( getEngine().getRoot() );
}
}.start();
You can make sure to set your params for the new run as Artem discussed.
PS: Would be better to simply make the user press the stop button, feed the values to the experiment page, let the user re-adjust them if needed and let her restart the model as usual.
To clarify, there are two questions:
How to have the button in model that restarts the simulation? - this isn't possible. But what can be done is have a button that calls stopSimulation() and returns the user into the Simulation set up
How to have changes made in model during runtime propagate to the next Simulation run? - save the values from edit fields into internal properties of the model and then access them in Simulation's After simulation run Java action by checking root object
Let me explain my problem with the following vehicle example:
I've got:
IntegerProperty: speed
BooleanProperty: crash
JavaFX slider element: speed_slider. (where I can set a speed from 0-50.)
JavaFX button element: crash_button.
I've successfully done:
Bound speed to the value of speed_slider.
That works. When I'm changing the value of the speed_slider, the speed changes.
But now I want to expand this. I tried the following:
Bound crash to the selectedValue of crash_button.
Bound speed to: if crash false, then value of speed_slider, else value 0.
Up here it works: Whenever crash is true, speed turns 0. If crash is false, it takes the value of speed_slider. And here is the problem:
I want the speed_slider value is automatically changes to 0, when speed does change to 0 due to crash. When I try to bind the value of speed_slider to speed it does not work, it causes an endless loop and fails- how to solve that problem without using listeners?
I think the solution is simple, instead of unidirectional bindings, use bidirectional:
speed.bindBidirectional(speed_slider.valueProperty());
Then you can still do a unidirectional binding with the crash and others etc. All this does is make sure the slider is always in sync with the speed, no matter which of these change.
I run fairly time consuming calculations in a Shiny app once users have selected input parameters. To make sure the calculations don't run unnecessary times I made the following action button:
actionButton('seeData','see Data' )
I then tried to only have this time consuming calculation run once per button click (and never when there is no button click) with the following code:
observeEvent( input$seeData, {
...long, includes several function calls...
})
Within observeEvent I do reference other input parameters.
What I am finding is that the calculation does not run the first time until I press the button, no matter how many times I adjust input parameters. However, once I press the button once, the calculation runs whenever any input parameter is changed. Why is the code running a second, third, fourth time (etc) when I have only pressed the button once?
My goal would seem to be just the typical use case, but I suppose there is something tricky with an observe or isolate aspect of observeEvent that I am not understanding. What am I doing wrong and how can I achieve one click-one calculation functionality?
use enable() and disable() on the action button.
so when the button is clicked (and before the long calculation) disable the button untill the calculation is done....
then at the end re-enable the button again...
Here we can see a description of the uses of observeEvent and eventReactive. The interesting thing is in the example, where you can see how the reactiveness of the function is performed only in the moment when the button is clicked.
The approach is to define an EventReactive variable which contains the data to be displayed. This will make the function to retain its value even if the input changes. It will only change if the button is pressed.
I can't seem to find the answer to what I would have thought was a common problem.
What I want to do this is:
1. Show the Open File Dialog
2. Process the file selected
3. During processing the file, report progress to the User
I have a file defined, and am using the browseForOpen and AddEventListener:
public var fileInput:File = new File();
fileInput.browseForOpen("Open file",[filter]);
fileInput.addEventListener(Event.SELECT, onFileSelect);
// Step 2 - function gets called to process the file
private function onFileSelect(e:Event):void
{
// Step 3 - do some processing, and at intervals report progress to the screen
}
My issue is - any changes to the screen within the event listener do not get done until the function is complete.
Any help would be appreciated,
Thanks
Start a timer perhaps and let it check status of a variable(that denotes processing progress) as a separate running function it would not be predisposed to waiting on the parent function.
[ to be clear Im saying call a sperate function from the timer.]
But I am inclined to agree with Flextras.com in that most times I have done this the processing was milliseconds so just didnt get seen.
In Step 3, if you are doing some cpu intensive job(like huge xml parsing), then you might be seeing this NOT updating problem. As Flex is single threaded, you better make use of Green threading concept.
You can read about Green Threading here.
I'm writing a wizard UI based on the QWizard Qt object. There's one particular situation where I want the user to log in to a service using host, username, and password. The rest of the wizard then manipulates this service to do various setup tasks. The login may take a while, especially in error cases where the DNS name takes a long time to resolve -- or perhaps it may not even resolve at all.
So my idea is to make all three fields mandatory using the registerField mechanism, and when the user hits Next, we show a little throbber on the wizard page saying "Connecting to server, please wait..." while we try to connect in the background. If the connection succeeds, we advance to the next page. If not, we highlight the offending field and ask the user to try again.
However, I'm at a loss for how to accomplish this. The options I've thought of:
1) Override validatePage and have it start a thread in the background. Enter a wait inside validatePage() that pumps the Qt event loop until the thread finishes. You'd think this was the ugliest solution, but...
2) Hide the real Next button and add a custom Next button that, when clicked, dispatches my long running function in a thread and waits for a 'validation complete' signal to be raised by something. When that happens, we manually call QWizard::next() (and we completely bypass the real validation logic from validatePage and friends.) This is even uglier, but moves the ugliness to a different level that may make development easier.
Surely there's a better way?
It's not as visually appealing, but you could add a connecting page, and move to that page. If the connection succeeds, call next() on the wizard, and if the connection fails, call previous() and highlight the appropriate fields. It has the advantage of being relatively straightforward to code.
My final choice was #2 (override the Next button, simulate its behavior, but capture its click events manually and do the things I want to with it.) Writing the glue to define the Next button's behavior was minimal, and I was able to subclass QWizardPage with a number of hooks that let me run my task ON the same page, instead of having to switch to an interstitial page and worry about whether to go forwards or backwards. Thanks Caleb for your answer though.
I know this has already been answered (a long time ago!) but in case anyone else is having the same challenge. Another method for this is to create a QLineEdit, initiate it as empty and set it as a mandatory registered field. This will mean that "Next" is not enabled until it is filled with some text.
Run your connection task as normal and when it completes use setText to update the QLineEdit to "True" or "Logged in" or anything other than empty. This will then mean the built in isComplete function will be passed as this previously missing mandatory field is now complete. If you never add it to the layout then it won't be seen and the user won't be able to interact with it.
As an example ...
self.validated_field = QLineEdit("")
self.registerField('validated*', self.validated_field)
and then when your login process completes successfully
self.validated_field.setText("True")
This should do it and is very lightweight. Be sure though that you consider the scenario where a user then goes back to that page and whether you need to reset the field to blank. If that's the case then just add in the initialisePage() function to set it back to blank
self.validated_field.setText("")
Thinking about it you could also add the line edit to the display and disable it so that a user cannot update it and then give it a meaningful completion message to act as a status update...
self.validated_field = QLineEdit("")
self.validated_field.setDisabled(True)
self.validated_field.setStyleSheet("border:0;background-color:none")
self.main_layout.addWidget(self.validated_field)
self.registerField('validated*', self.validated_field)
and then when you update it..
self.validated_field.setText("Logged in")