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.
Related
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();
I may have worked myself into a corner but this sounded to me like a good idea at the time.
I have been developing an interface that permits a user to modify settings of a robotic device, i.e. speed, directions, force, etc. with a very large series of options in the form of ComboBoxes. The problem is that there are about a thousand of these things, in sub categories. e.g. Speed category x1, x2, x3, Y1, y2, etc. So rather than create a thousand comboboxes in QT, I thought the good idea was to create one set of 50 (ish) and then provide a few button to switch between categories. So when the user selects speed QT, populates the comboboxes with the appropriate options, sets the style sheets and text for the labels etc. So it appears as though a dedicated page exists. Then if the user selects Direction, QT Writes the current index of each box to a dedicated array and then repopulates the boxes, labels etc with the appropriate content. I then do this over and over for the various needs of the system.
All of that seems to work fine. However I am now in a bind where the options provided to navigate to each page have grown. For instance I have forward / backward buttons (like you woudl expect in a set-up wizard), as well as action menus at the top to jump to a page. So now the code is becoming very repetitious. If you select the next button, I write the current values to array, then repopulate. If you jump to the page from anywhere, I look to see where I am, write it to array, and populate the boxes. Thus if I need to change anything I have to make the change in numerous places in the code.
I know that this is not optimal. What I woudl like to do is run a continuous loop as I woudl normally do with Micros in C. So the program can look at a variable in each pass and if it is then it does. I am not however skilled enough to figure this loop out in QT. So my new thought was...
Is it possible to trigger an action or slot with a variable. For example, if the user presses the Next button it triggers a slot for a button that does not exist, so that QT will execute a particular line of Code? Then I can have 1 dedicated section focused on reading and writing boxes, with a bunch of actions that will take me there.
You can make a signal that is triggered with an emit call in your code, so you'd hook up the next button signal of clicked to a slot that does some work and moves on, or directly calls another signal that you've created that triggers a slot elsewhere, or do some work in a lambda triggered by the button press.
I would first load all the ComboBoxes options in a QStringList array (or maybe an array of QList<QLatin1String> lists - for memory saving and code efficiency).
Then I would keep an array of a 1000 integers for current ComboBox indexes.
When the user changes a value in some ComboBox, the currentIndexChanged signal will trigger the corresponding slot (a single slot for all the ComboBoxes would be enough - sender()->objectName() to get the name of the ComboBox which had sent the signal):
void WindowWidget::on_ComboBox_currentIndexChanged(int index)
{
name = sender()->objectName();
/* here change the corresponding integer in the current
indexes array */
}
On Next/Back button push repopulate the ComboBoxes. Also, provide some 'Save' button for saving the ComboBoxes indexes (or trigger the Save slot on some action, i.e. on window close either even on a timer signal).
I have written a GUI in R with RGTK2 and Tcltk that does a lot of fairly heavy calculations and aggregations on big data sets.
I would like to find a way to stop the user interface from accepting user inputs while it is processing a large data set, and ideally, change the interface color, popup a dialogue, or change the mouse pointer to an hourglass/spinner to indicate to users that the application is active.
The implementation that I want would look something like:
gSignalConnect(bigRedButton,"clicked",
f=function(widget)
{
something$start() # object with method that blocks further user input
# and pops up loading bar or "Processing" dialogue
# (or possibly spins the mouse)
# Code that does a very big set of calculations
something$stop() # unblocks user inputs and removes visual impedance
}
)
I have tried using gtkDialogue to solve the problem, but this seems to stop execution of the whole program until one closes the dialogue, which rather defeats the purpose.
Any help would be greatly appreciated.
So the magic method is gtkWidgetSetSensitive:
gSignalConnect(bigRedButton,"clicked",
f=function(widget)
{
gtkWidgetSetSensitive(Window,FALSE)
# Code that does a very big set of calculations
gtkWidgetSetSensitive(Window,TRUE)
}
)
This method turns the targeted widget (which can be an individual button, textEntry, comboBox, etc...) gray and blocks input.
I am using PyQt4, but this is general enough that it could just apply to QT.
I have a series of QComboBoxes that I fill from left to right (i.e. selecting an item in the leftmost will populate the next one. Selecting an item in that one will populate the next, and so on)
I am having difficulty getting my signals to fire under all situations (i.e. regardless of whether the current index changes or not AND regardless of whether the item is set by the user or set programatically).
More detail:
I rely on the signals of the first QCombox to fire whenever an item is selected so that I can populate the next QCombobox in the gui. I then rely on THAT QCombobox to emit a signal so that I can populate the next one. And so on.
I want to pre-select an item in each QCombobox based on the user's last interaction with the gui.
I have a unique function per QCombobox that is responsible for populating and pre-selecting just that QCombobox. The code looks something like this:
comboBox1.blockSignals(True)
comboBox1.clear()
comboBox1.addItems(sorted(itemList))
comboBox1.blockSignals(False)
comboBox1.setCurrentIndex(intLastSavedState1)
where intLastSavedState1 is an integer that is derived from the text that was last selected by the user the last time they had used the app. I had hoped that the last line of this function would fire a signal that would cause the next combo box's function to load and pre-select an item (comboBox2). And that action would then cause the next comboBox's function to activate and it would cascade to the next and the next. But it is not working across all cases.
I have tried two versions of the signals:
self.connect(comboBox1, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.load_comboBox2)
and
self.connect(comboBox1, QtCore.SIGNAL("activated(const QString&)"), self.load_comboBox2)
In the first case, the signal will fire only if the intLastSavedState1 is different than whatever is currently selected in the combo box. This causes an issue if the user had last selected item 0 from that list. In this case QT does not recognize my script setting the the current index to 0 as being a change (since after loading the box it appears to think it is already on index 0), and so the signal does not fire.
In the second case, the signal will fire regardless of what is currently selected in the combo box... but only if activated by the user. It will not fire when my script tries to set the current index programatically.
These appear to be my only two options regarding the signals. So... is there another way of pre-selecting items in a QCombobox that will trigger a signal each and every time?
Well... sometimes just the act of asking a question can lead you to a (partial) answer.
I have a work-around but I am still interested in hearing if someone has a better idea.
I am now programatically setting the index of the QCombobox to -1 immediately after loading it up. Then, when I programatically set the actual index based on the user's history, it will always be considered a change (i.e. it will never be -1) and the signal will fire
using: currentIndexChanged(const QString&)
So my code looks like this now:
comboBox1.blockSignals(True)
comboBox1.clear()
comboBox1.addItems(sorted(itemList))
comboBox1.setCurrentIndex(-1)
comboBox1.blockSignals(False)
comboBox1.setCurrentIndex(intLastSavedState1)
and my signal looks like this:
self.connect(comboBox1, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.load_comboBox2)
This functions... does anyone have a better idea?
Thanks agian.
You can check current Index of your ComboBox and then either call your slot or do call setCurrentIndex().
Example:
if comboBox1.currentIndex() == index:
self.load_comboBox2(index)
else
comboBox1.setCurrentIndex(index)
This way you will not end up calling slot twice.
I have a label inside an update panel which I would like to use as a status bar.
Basically the user clicks a button which executes a main function that performs a series of tasks. I'd like to inform the user as to the state of the function as it progresses e.g.:
Stage 1: Retrieving data...
Stage 2: Calculating values...
Stage 3: Printing values...
Stage 4: Done!
I've tried updating the updatepanel directly from the function but it only updates the panel at the end of function (stage 4) and shows "Done!" (which I understand is how it should work).
I've been looking into timers and threads to try and update the panel separate to the main function but I thought I'd post here in case anyone has any better ideas?
Have you put an Update Panel around the label as well? Set UpdateMode to conditional, then when executing your stages, set the label's text then updatePanelProgress.Update() should do it