I'm trying to retrieve the "name" (or any type of unique identifier) of the ToggleGroup of a given ToggleButton, and have been having no success. It is important, if possible, that the different buttons share the event handler. Any help?
//create toggleGroups
final ToggleGroup toggleGroup1 = new ToggleGroup();
final ToggleGroup toggleGroup2 = new ToggleGroup();
//create toggleButtons
final ToggleButton toggleButton1 = new ToggleButton("b1");
final ToggleButton toggleButton2 = new ToggleButton("b2");
//assign toggleButtons to toggleGroups
toggleButton1.setToggleGroup(toggleGroup1);
toggleButton2.setToggleGroup(toggleGroup2);
//assign custom handler to toggleButtons
toggleButton1.setOnAction(new handleEvent());
toggleButton2.setOnAction(new handleEvent());
//handler
class handleEvent implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent e) {
// enable ability to get toggleButton name later
ToggleButton b = (ToggleButton)e.getSource();
//get name of group toggleButton belongs too?
String toggleGroup = b.getToggleGroup().toString();
// do stuff based on name and group
if (toggleGroup == "toggleGroup1") {
//do stuff
} else if (toggleGroup == "toggleGroup2") {
//d other stuff
}
}
}
You can set the name as userData: toggleGroup.setUserData("toggleGroupName")
To retrieve it back you call: String name = (String) toggleGroup.getUserData()
Related
I would like to have this functionality in my program:
I will have a user input field. When the user pressed the button, it will be added to the list, and input will be shown to the user.
The problem is, I would like to deselect/remove those input if the user wants. I could not achieve this.
Here is the code I have written so far, I have removed some functionality unnecessary for the question's scope:
public class AddUserInput extends VerticalLayout{
// The user input will be added to the this list
// later, this list will be sent to the server for some verification
private List<String> emails;
private HorizontalLayout content;
private VerticalLayout rows;
// user input field
private TextField emailField = new TextField("Enter email address");
public AddUserInput() {
content = new HorizontalLayout();
rows = new VerticalLayout();
content.setMargin(true);
Button addToListButton= new Button("Add to list");
addToListButton.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(Button.ClickEvent event) {
// When the user clicks add to list button
// The raw input will be added to the emails list
// The UI component is added to 'rows' component
rows.addComponent(addNewRow(emailField.getValue()));
}
});
content.addComponents(emailField, addToListButton, rows);
addComponent(content);
}
public Component addNewRow(String email){
HorizontalLayout newRow = new HorizontalLayout();
Button deleteRowButton = new Button("-");
deleteRowButton.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(Button.ClickEvent event) {
// I can delete from the UI by using the code below
newRow.removeAllComponents();
rows.removeComponent(newRow);
// How to remove from the email list???
}
});
emails.add(emailField.getValue());
Label lastEmail = new Label(emailField.getValue());
emailField.clear();
newRow.addComponents(lastEmail,deleteRowButton);
return newRow;
}
}
Is there any component/library that does this functionality?
I only need a text field, and adding the input to the list, and removing the list item if a user wants to.
The visualization of the code above:
You could use the NativeSelect component for managing the entered Strings.
I modified your AddUserInput-Component to use a NativeSelect and a corresponding DataProvider:
public class AddUserInput extends VerticalLayout {
private HorizontalLayout content = new HorizontalLayout();;
private NativeSelect<String> select = new NativeSelect<>("The List");
private ListDataProvider<String> dataProvider = DataProvider.ofCollection(new ArrayList<>());
private Button addToListButton= new Button("Add to list");
private Button deleteFromListButton = new Button("-");
private TextField emailField = new TextField("Enter email address");
public AddUserInput() {
select.setVisibleItemCount(5);
select.setWidth("100px");
select.setDataProvider(dataProvider);
select.setEmptySelectionAllowed(false);
deleteFromListButton.setEnabled(false);
content.setMargin(true);
addToListButton.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(Button.ClickEvent event) {
addEmailToList(emailField.getValue());
}
});
deleteFromListButton.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(Button.ClickEvent clickEvent) {
select.getSelectedItem().ifPresent(selectedItem -> removeSelectedEmailFromList());
}
});
select.addValueChangeListener(new HasValue.ValueChangeListener<String>() {
#Override
public void valueChange(HasValue.ValueChangeEvent<String> valueChangeEvent) {
deleteFromListButton.setEnabled(select.getSelectedItem().isPresent());
}
});
content.addComponents(emailField, addToListButton, select, deleteFromListButton);
addComponent(content);
}
private void addEmailToList(String email){
dataProvider.getItems().add(email);
select.getDataProvider().refreshAll();
emailField.clear();
}
private void removeSelectedEmailFromList(){
select.getSelectedItem().ifPresent(selectedItem -> dataProvider.getItems().remove(selectedItem));
select.setSelectedItem(dataProvider.getItems().isEmpty() ? null : dataProvider.getItems().iterator().next());
select.getDataProvider().refreshAll();
}
}
It looks like the following:
Would that be a possible option for you?
Am still new to javafx and i would like to perform a directional binding to radio buttons
in my fxml i have
<fx:define>
<ToggleGroup fx:id="version_selection" />
</fx:define>
<RadioButton toggleGroup="$version_selection" ............>
<RadioButton toggleGroup="$version_selection" ............>
In my controller i want to bind the value of the selected togglegroup. With textfields its easy as its just
#FXML
TextField name;
#FXML
private ToggleGroup version_selection;
name.textProperty().bindBidirectional(model.field5Property());
where the model is my class with the SimpleStringValue property
How do i bind the togglegroup as it doesnt have a textproperty as a textfield
Even if you had a ObjectProperty<Toggle> in your model, it you couldn't establish a bidirectional binding, since ToggleGroup.selectedToggle is readonly. You need to work around this by adding a listener to both the ToggleGroup.selectedToggle property and the model property and update the property other than the source of the change on a change.
Use a Map<String, Toggle> to convert the text to the toggle to be selected. The following example uses a TextField to determine the property instead of a model property to demonstrate the behaviour: input the text of the RadioButton to select and it'll be selected.
#Override
public void start(Stage primaryStage) throws IOException {
ToggleGroup group = new ToggleGroup();
VBox vbox = new VBox();
for (char c = 'a'; c <= 'f'; c++) {
RadioButton radio = new RadioButton(Character.toString(c));
radio.setToggleGroup(group);
vbox.getChildren().add(radio);
}
TextField input = new TextField();
vbox.getChildren().add(input);
// create map mapping from text to corresponding toggle
Map<String, Toggle> map = new HashMap<>();
for (Toggle t : group.getToggles()) {
map.put(((RadioButton) t).getText(), t);
}
StringProperty property = input.textProperty();
InvalidationListener listener = new InvalidationListener() {
// flag preventing circular updating
boolean updating = false;
#Override
public void invalidated(Observable observable) {
if (!updating) {
updating = true;
if (observable == group.selectedToggleProperty()) {
// change as result of user interaction with RadioButton
// update property
RadioButton selectedToggle = (RadioButton) group.getSelectedToggle();
property.set(selectedToggle == null ? "" : selectedToggle.getText());
} else {
// change as result of updating the property
// select corresponding toggle
Toggle toggleToSelect = map.get(property.get());
group.selectToggle(toggleToSelect);
}
updating = false;
}
}
};
property.addListener(listener);
group.selectedToggleProperty().addListener(listener);
Scene scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}
I'm trying to get the name of a MenuItem and then set a Label text to the name of this clicked MenuItem in a MenuButton. How can i do this? The MenuItems getting the id's from a String in a DB.
Variables:
#FXML
private MenuButton projektAuswahl;
MenuItem item;
Creating new MenuItem:
ResultSet rs = stmt.executeQuery(sqlQuery);
while (rs.next()) {
item = new MenuItem(rs.getString(1));
item.setId(rs.getString(1));
projektAuswahl.getItems().add(item);
}
set the Label text:
private void setProjectLabel() {
//projectnameLabel.setText(item.getText()); //not working..
}
How can i recognize which MenuItem is clicked?
You also need to register a handler for the onAction event. This could be a new one for each MenuItem saving the data about the text each, or you could access the event source to get a reference to the MenuItem:
static MenuItem createMenuItem(String text, EventHandler<ActionEvent> handler) {
MenuItem result = new MenuItem(text);
result.setOnAction(handler);
return result;
}
private Label projectnameLabel;
private void setProjectLabel(ActionEvent event) {
MenuItem source = (MenuItem) event.getSource();
projectnameLabel.setText(source.getText());
}
#Override
public void start(Stage primaryStage) {
EventHandler<ActionEvent> handler = this::setProjectLabel;
MenuButton btn = new MenuButton("menu");
btn.getItems().addAll(createMenuItem("a", handler),
createMenuItem("b", handler),
createMenuItem("c", handler));
projectnameLabel = new Label();
VBox root = new VBox(10, btn, projectnameLabel);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
You can add action listener directly in code like :
menuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
setProjectLabel(); // in your case
}
});
Or I propose you to add a controller to your fxml, then replace all code you displayed in it and bind the setProjectLabel() with the menuitem in SceneBuilder here :
I have created a text field:
TextField tfPost = new TextField("140 character word count...");
I also have a button with a ActionEvent Handler class:
Button btTweet = new Button("Tweet");
TweetHandlerClass btTweetHandler = new TweetHandlerClass();
btTweet.setOnAction(btTweetHandler);
Here is the body of the handler class:
class TweetHandlerClass implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent ae) {
System.out.println("Tweet button was clicked");
String newTweet = tfPost.getText();
}
}
What I need is for the string inside the TextField to be saved to a string variable when the Tweet button is clicked. How do I do this?
Variable scoping is a design question. The OP's question does not provide sufficient information to understand the full use case. One approach is to store the variable in the TweetHandlerClass. There are various rationales for and against such an approach. Nonetheless, for the specific question posed, it should suffice.
class TweetHandlerClass implements EventHandler<ActionEvent> {
private final TextField tfPost;
public TweetHandlerClass(TextField srcTxtFld)
{
this.tfPost = srcTxtFld;
}
#Override
public void handle(ActionEvent ae) {
System.out.println("Tweet button was clicked");
String newTweet = tfPost.getText();
}
}
Then, in the instantiating the Button:
TextField tfPost = new TextField("140 character word count...");
Button btTweet = new Button("Tweet");
TweetHandlerClass btTweetHandler = new TweetHandlerClass(tfPost);
btTweet.setOnAction(btTweetHandler);
If you really want the event handler to be a top-level class like that, you could give it a reference to a TextField as in #KevinO's answer. A slight variant on that would just be to have a reference to a Supplier<String>, which is more semantically what you really need:
class TweetHandlerClass implements EventHandler<ActionEvent> {
private final Supplier<String> tweetSupplier ;
TweetHandlerClass(Supplier<String> tweetSupplier) {
this.tweetSupplier = tweetSupplier ;
}
#Override
public void handle(ActionEvent ae) {
System.out.println("Tweet button was clicked");
String newTweet = tweetSupplier.get();
}
}
and then
Button btTweet = new Button("Tweet");
TweetHandlerClass btTweetHandler = new TweetHandlerClass(tfPost::getText);
btTweet.setOnAction(btTweetHandler);
This is pretty much overkill though. Normally you would just define the event handler with a lambda expression, instead of an explicit class:
Button btTweet = new Button("Tweet");
btTweet.setOnAction(e -> {
System.out.println("Tweet button was clicked");
String newTweet = tfPost.getText();
// ..
});
I want to write test in SWTBot.
The test should press on table add new row and then press on button of DateCombo and insert value to the cell.( value from the calender )
This is my code :
public SWTBotTable AppExp_getGridTable(SWTBotView appExpView) {
return appExpView.bot().tableWithId("GridViewer.Table"); //$NON-NLS-1$
}
public List<Widget> getWidgetListOfType(java.lang.Class type) {
Matcher matcher = allOf(widgetOfType(type));
List<Widget> widgets = bot.getFinder().findControls(matcher);
return widgets;
}
SWTBotTable swtbotTable = utilsList.AppExp_getGridTable(view);
//Put the foucs on the cell
swtbotTable.doubleClick(0, 1);
Display.getDefault().syncExec(new Runnable() {
#Override
public void run() {
List<Widget> widgetListOfType = utilsList.getWidgetListOfType(DateCombo.class);
DateCombo dateCombo = (DateCombo) widgetListOfType.get(0);
List<Widget> widgetListOfType = utilsList.getWidgetListOfType(Button.class);
Button bt = (Button) widgetListOfType.get(0);
}
});
How I can trigger the click on the button or on the dateCombo?
And then How I can select value from the calendar ?
I have no idea what DateCombo is, since it's not part of the default API, but you can simulate the Button click like this:
Event event = new Event();
event.widget = button;
event.type = SWT.Selection;
button.notifyListeners(SWT.Selection, event);