ActionEvent get source of button JavaFX - button

I have about 10 buttons which are going to be sent to the same method. I want the method to identify the source. So the method knows button "done" has evoked this function. Then I can add a switch case of if statement to handle them accordingly. This is what I have tried
//Call:
btnDone.setOnAction(e -> test(e));
public void test(ActionEvent e) {
System.out.println("Action 1: " + e.getTarget());
System.out.println("Action 2: " + e.getSource());
System.out.println("Action 3: " + e.getEventType());
System.out.println("Action 4: " + e.getClass());
}
Output Result:
Action 1: Button#27099741[styleClass=button]'Done'
Action 2: Button#27099741[styleClass=button]'Done'
Action 3: ACTION
Action 4: class javafx.event.ActionEvent
Done is the text on the button. As you can see I could use e.getTarget() and/or e.getSource() then I'll have to substring it, so only the "Done" appears. Is there any other way to get the string in the apostrophe instead of having to substring.
UPDATE: I have tried passing Button and it works but I still want to
know a solution using ActionEvent.
//Call:
btnDone.setOnAction(e -> test(btnDone));
public void test(Button e) {
System.out.println("Action 1: " + e.getText());
}
Output is Action 1: Done

Typically I much prefer using a different method for each button. It's generally a very bad idea to rely on the text in the button (e.g. what will happen to the logic if you want to internationalize your application?).
If you really want to get the text in the button (and again, I have to emphasize that you really don't want to do this), just use a downcast:
String text = ((Button)e.getSource()).getText();

As #James_D pointed out, relying on the button text displayed to the user is a bad idea for various reason (tho probably sufficient for your case!)
A different approach would be, to assign IDs to the buttons and then retrieving them in the callback method. That would look something like that:
// that goes to the place where you create your buttons
buttonDone.setId("done");
...
// that goes inside the callback method
String id = ((Node) event.getSource()).getId()
switch(id) {
case "done":
// your code for "buttonDone"
break;
}

Related

Xamarin Forms Prism DialogService takes some seconds to show up

My Dialog is a simple Frame with an Image, a label to display a question and two more labels (Yes / No) with TapCommand.
I've set up the container with the DialogPage.xaml and DialogPageViewModel and injected in the ViewModel I want to open the dialog.
Here is the code I'm using to call the Dialog:
public void ShowDialog()
{
_dialogService.ShowDialog("DiscardPopup", CloseDialogCallback);
}
void CloseDialogCallback(IDialogResult dialogResult)
{
var goBack = dialogResult.Parameters.GetValue<bool>("GoBack");
if (goBack)
NavigationService.GoBackAsync();
}
If the user taps over the "Yes label", I execute this command:
YesCommand = new DelegateCommand(() => YesTapped());
private void YesTapped()
{
IDialogParameters pa = new DialogParameters();
pa.Add("GoBack", true);
RequestClose(pa);
}
If the user taps over the "No label", I simply call:
NoCommand = new DelegateCommand(() => RequestClose(null));
The "problem" is when the ShowDialog is fired, the DiscardPopup is taking up to 3 seconds to show up.
Is there a way to make it faster?
The same happens with the TapCommands, 2 - 3 seconds when the RequestClose is invoked.
Without actual code telling you exactly what the issue is, is going to be best guess. Based on your feedback to my comments above I would suggest the following:
Try displaying the dialog on a test page that doesn't have a complex layout. My guess is that you won't see such a long load time. If that's the case this would point to your layout being overly complex and that the lag time is due to the device struggling to re-render the View
Try using Prism.Plugin.Popups. You'll need to initialize Rg.Plugins.Popup and register the DialogService. You can see docs on that at http://popups.prismplugins.com

Blackberry 10 SystemPrompt->inputField does not change value on user input

I need to display system input dialog: title, some text, input field, OK & Cancel buttons.
I'm new to BB development, so I carefully read docs and samples: http://developer.blackberry.com/native/documentation/cascades/ui/dialogs_toasts/prompts.html
and write the same code (let's say doc author cheated a bit in the most important part - not covering obtaining of user input with non-compiling source code - "qDebug() << "Prompt Accepted:" << text;").
void MainPage::showPrompt() {
SystemPrompt *dialog = new SystemPrompt();
dialog->inputField()->setDefaultText("TEST");
QObject::connect(dialog, SIGNAL(finished(bb::system::SystemUiResult::Type)),
this, SLOT(promptHandler(bb::system::SystemUiResult::Type)));
dialog->show();
}
void MainPage::promptHandler(bb::system::SystemUiResult::Type value) {
if (value == SystemUiResult::ConfirmButtonSelection) {
SystemPrompt *dialog = (SystemPrompt *)QObject::sender();
qDebug("text is: '%s'", qPrintable(dialog->inputField()->defaultText()));
}
}
Regardless of user input on device/simulator, inputField()->defaultText() value is always "TEST" as it was initialized.
How do I get the user input here? dialog->exec() does not change anything.
PS. Expert level question: And how do I allow empty input in SystemPrompt dialog (by default "OK" button becomes disabled on empty input).
Shame upon me. I did not read documentation carefully.
->inputFieldTextEntry() does contain the user input.
PS. First time I see such sophisticated logic of handling such simple thing as user input in text edit...

Pass records to a dialog

In a customised form I would have a create Purchase Menubutton which opens a dialog to create a purchase order.
But I need to select few records like one or two lines and then create purchase order only for those records. How do I do that?
Take a look on the "Create purchase order" button on the SalesTable form.
It works differently: you select the lines to purchase after you press the button, but it might work in your case also.
Also have a look on how to use multiple selected records in a grid.
Here is a piece of code which allows you to get the record from the previous form.
You have to put this piece of code in the INIT method of the dialog. So you have to override the init of the dialog.
DmoVehicleTable vehicleTable;
DmoVehicleId vehId;
// Get the vehicle ID from the previous form
if (element.args() && element.args().record())
{
switch (element.args().record().TableId)
{
case (tableNum(DmoVehicleTable)):
vehicleTable = element.args().record();
vehId = vehicleTable.VehicleId;
break;
default:
throw error (strFmt("#SYS477", this.name()));
}
}
I hope this will help you.
If you need more help: http://sirprogrammer.blogspot.com/

Qt: two actions in menu (with the same text)

I create a menu dynamically. I add several checkable actions into one menu. Sometimes actions may have the same text that user sees. It's up to user (actually user adds commands into menu).
The problem is in this case clicking works wrong. If I click on the first action (from 2 with the same texts) everything is good but if I click on the second one, both actions are selected. I don't understand why. The code where actions have been created is here:
for (int i = 0; i< currentList.size(); i++)
{
QString lanKey = currentList.at(i)->Language->toString();
QAction* lanAction = new QAction(this);
QString name ="action_" + currentList.at(i)->Id->toString();
lanAction->setObjectName(name);
lanAction->setText(lanKey);
lanAction->setCheckable(true);
lanAction->setData(i);
connect(lanAction, SIGNAL(triggered(bool)), this, SLOT(ShowSomething(bool)));
ui->menuMy->addAction(lanAction);
}
Here, lanKey is language that may be the same for different actions. Anyway click on the specific action should lead only to checking of this action. What's wrong?
The slot is here:
void VMainWindow::ShowSomething(bool IsTriggered)
{
QAction* senderAction = (QAction*)sender();
int listIndex = senderAction->data().toInt();
if (IsTriggered)
{
CreateEditor(subtitles, listIndex);
}
else
{
//hide this editor
QString name = "editor" + editorsList->Id->toString();
QDockWidget* editorDock = this->findChild<QDockWidget*>(name);
if (editorDock != 0)
{
this->removeDockWidget(editorDock);
this->setLayout(layout());
}
}
}
Thanks
The source of problem is found: it turned out that the slot finds the checked action wrong - by text, not by id.
I can't find a logical issue in the code you posted so far. Here are a couple of options which I would try in order to resolve this problem:
Limit the users possibilities when adding items to a menu so that he can't add two items with the same name.
Add qDebug() output to ShowSomething to see if there is a problem with signals&slots. For example, if the slot gets called once for the first item but twice for the second item there is a problem there.
Debug into CreateEditor step-by-step.
As the problem seems to appear only for actions with a similar name, you should make sure that you never make a lookup of an action (or something related) by its text() but rather by its data() or objectName() (assuming that currentList.at(i)->Id will always be unique)

listening for viewstack change event

I have a piece of software I'm working on that is using a viewstack with 3 canvases. With the change event I need to look for index 2 which is the last canvas when it changes to this canvas I need it to grab data from inputs from the previous two canvases.
Within the viewstack events I've assigned the function change() to the event childIndexChange.
Here is the method:
private function change():void
{
Alert.show(customerViewStack.selectedIndex.toString());
}
eventually this method will look something like this:
public function change():void
{
if(customerViewStack.selectedIndex == 2)
{
rCID.text = cidTxt.text;
rCNAME.text = nameTxt.text;
rCACCTN.text = acctNumTxt.text;
rCACCTR.text = acctRep.text;
rCWEB.text = website.text;
rCACTIVE.text = active.text;
rCSTREET.text = cStreet.text + " "+ cSuite.text;
rCCSZ.text = cCity.text + ", " + cState.text + " " + cZipcode.text;
rCPHN.text = cPhone.text;
rCAPHN.text = cPhone0.text;
rCFAX.text = cFax.text;
}
}
to alternate through my views im using this approach with buttons actually inside the canvases:
customerViewStack.selectedChild=cAddress
anyway the problem is the event doesn't seem to be firing my change function because no alert is coming up also the way I'm doing this is probably quite naive so if you have any suggestions please I'm open.
I've taken another approach I'm going to bypass "deferred instantiation" and turn the cereationPolicy to all. The view before the last I will set values from there then transition over.
However if anyone has any thoughts or criticism please feel free.
The change event will fire when the view is changed, so simply subscribing to this event instead of childIndexChange should solve the problem.

Resources