I am using Vaadin 7.1.7.
I have a Table which has a few TextFields and a Button called "delete".
On click of the delete button, that particular row is to be deleted.
As i understand, I could remove table item as follows:
table.removeItem(itemID);
Unfortunately, I am unable to fetch the itemID of the row to remove it from the table.
Since, I used table.addItem(o, null); to addItems to it, how could I get the rowID/itemID on the click of the button inside buttonClickListener?
My trys so far have been:
#Override
public void buttonClick(ClickEvent event) {
Table t = (Table) event.getButton().getParent();
}
This has got me to the parent table but not to that particular item.
Thanks in advance
.
You could for example use setData(rowID) when you create the buttons.
The onClick you retrieve the associated data of the button and have the correct row id.
Provide a row id, override Button.ClickListener, and use the id in the click listener.
Object rowId = new Object();
Button button = new Button("Delete");
button.addClickListener(new RowDeleteListener(rowId));
//populate cells in the row, add the button & whatever
table.addItem(row, rowId);
public class RowDeleteListener implements Button.ClickListener {
Object rowId;
public RowDeleteListener(Object rowId) {
this.rowId = rowId;
}
public void buttonClick(ClickEvent event) {
table.removeItem(rowId);
}
}
Or André Schild’s solution, which is to use setData(rowId) on the button.
Button button = new Button("Delete");
button.addClickListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
table.removeItem(getData());
}
});
//Populate row stuff.
button.setData(table.addItem(row, null));
I like the first solution slightly better because it's more obvious what's going on, and also because the button has the correct row id before it gets added to the table instead of after.
Or, if you feel like creating something obnoxious: you could use the Button object as the id for the row.
Button button = new Button("Delete");
button.addClickListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
table.removeItem(this);
}
});
//populate row stuff, including adding the button to the row.
table.addItem(row, button);
I didn't test or compile any of these so... you know...
Related
I'm currently made an Form with JavaFX.
Always i press a Button, i call the "addAnswer()"-Method.
In that I create a RadioButton, a Label and a delete-Button, which i bundle in a HBox. All that HBoxes i pack in a vBox.
The Problem now is the delete-Button. I want to delte just THAT HBox in which the clicked Button is.
Here is my code:
public void addAnswer() {
this.rB = new RadioButton();
checkAnswer.getToggles().add(rB);
hBox = new HBox();
tF = new TextField();
delAnswer = new Button("Löschen");
delAnswer.setId(Integer.toString(counter));
hBox.getChildren().addAll(rB, tF, delAnswer);
hBox.setId(Integer.toString(counter));
delAnswer.setOnAction(e -> delAnswer(Integer.parseInt(hBox.getId())));
System.out.println(delAnswer.getId());
vBox.getChildren().addAll(hBox);
counter++;
}
public void delAnswer(int e){
vBox.getChildren().remove(delAnswer.getId());
}
i tried this one above but i realized, that all the delAnswers-Buttons have the same ID: the number of how often i pressed the add-Button.
Is there any solution where i can just select that one i pressed with that dynamic way? Cause i don't kow how often somebody will press or delete something.
Thanks
hbox is a field and this is why always the HBox last added is used. (hBox is evaluated, when lambda body is executed, not at the time of the lambda creation). This would be different, if you used a (effectively) final local variable:
final HBox hBoxLocal = hBox;
delAnswer.setOnAction(e -> delAnswer(Integer.parseInt(hBoxLocal.getId())));
However I'd like to present a different solution which would allow you to use the same EventHandler<ActionEvent> for all delete Buttons:
You can get the Node that triggered the event using getSource. From this Node you can get the parent, which is the HBox. You can remove this from the VBox using the remove(Object) method
delAnswer.setOnAction(e -> {
// get button
Node source = (Node) e.getSource();
// remove parent of button from VBox
vBox.getChildren().remove(source.getParent());
});
I think your problem is that you give the same event to all your button,Begin by creating a list that stores your buttons and then increments the value of the ID after affecting it to an item :
List<Button> buttons = new ArrayList<>();
/*
Create Button and call IDEvt method to create new event
for each button
*/
private void IDEvt(Button btn){
btn.setId(String.valueOf(IDRank));
btn.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println(btn.getId());
}
});
IDRank++;
}
I have a ComboBox (JavaFX) that displays info from a database according to the selected String.
For eg: the values in the ComboBox are as follows:
Table 1
Table 2
When I have Table 1 selected, and I then select Table 2, the value change is detected and the code is run.
But when I have Table 1 selected, and I re-select Table 1, no value change is detected. Instead I want code to reload Table 1 from the source database.
The current code:
myComboBox.valueProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue ov, String t, String t1) {
myComboBoxValue = t1;
if (t1 != null) {
displayTable(t1)
}
}
});
The listener will not be triggered if the old selected value is equal to the new value. However, if this is what you want, you can clear the selected value once the comboBox is clicked.
myComboBox.valueProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue ov, String t, String t1) {
myComboBoxValue = t1;
if (t1 != null) {
displayTable(t1)
}
}
});
myComboBox.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
myComboBox.getSelectionModel().clearSelection();
}
});
A working approach to react to item selection in ComboBox irrespective if a new item was selected or not can be found here: https://stackoverflow.com/a/25704438/4749209
Basing on this solution, your sample code would stay like this:
myComboBox.showingProperty().addListener((ov, old_show_state, new_show_state) ->
{
// checks if the combobox popup menu was closed
if (new_show_state == false)
{
myComboBoxValue = myComboBox.getValue();
if (myComboBoxValue != null)
{
displayTable(myComboBoxValue)
}
}
});
The only problem to mention is that the reload operation you mentioned will happen if the user clicks outside the combobox popup menu area, as it will close too.
You don't change a value when it remains the same, so no event gets fired. Depending on what you are trying to do you could e. g. add a listener to onHidden. It's ugly and doesn't cover e. g. when you set the same value programmatically, but would work for changes via mouse click.
I have a cell table showing some data. For each row, I want to have two columns which contain edit / delete buttons. When each button is clicked, it should be able to notify a listener which button was clicked (and preferably also be able to pass in the object that row is associated with).
How can I do this? Specifically, I know how to render a button, but how can I process the on-click event and pass in the object which the user clicked to edit or delete?
This is the standard approach:
myTable.addCellPreviewHandler(new Handler<MyObject>() {
#Override
public void onCellPreview(CellPreviewEvent<MyObject> event) {
if ("click".equals(event.getNativeEvent().getType())) {
if (event.getColumn() == 0 || event.getColumn() == 1) {
MyObject object = event.getValue();
Window.alert("Column clicked: " + event.getColumn());
}
}
}
});
This is a more efficient solution, because you only have one handler attached to a table, instead of trying to attach a handler to each button in each row.
I think you can make a foreach through all the rows in the celltable (I never worked with celltables)
And then you can add your own ClickHandler to the Button.
Something like that (not tested):
final int row = myrow; // add the row value or a object identifier or similar
Button delete_button = new Button("delete");
delete_button.addClickHandler(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
// Insert your delete funciton
delete(row);
}
});
You mentioned a Listener, Listener are depreciated, use Handler instead.
When a user clicks a 'Add Node' button above a tree and the program adds a tree item below the selected node, I would like to insert the new tree item with the text highlight and ready for editing by the user... like labels in GMail. Any ideas?
--Kirt
Are you using the GWT default TreeItem? If so, when you add the node, you could add the TreeItem with a Widget which you write which contains a TextBox and a Button to save.
When the save button is clicked, it calls setText() on the tree item with the text box's text, thus removing the widgets from the tree item.
It may be an even better idea to subclass TreeItem to encapsulate this logic and provide more functionality.
edit: Here, just because I'm feeling generous...
public class EditableTreeItem extends TreeItem {
public EditableTreeItem() {
super();
TextBox textBox = new TextBox();
Button saveButton = new Button("Save");
saveButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent e) {
if (!textBox.getText().isEmpty()) {
EditableTreeItem.this.setText(textBox.getText());
}
}
});
}
}
I use the TableViewer to show informations in a table. The user can select one of the shown options by selecting one line of the table.
I want to create a table in matrix form, in which the user can not only select the line. It should be possible to select every item of the table, like row 2 column 3. For every item selection an action is called to handle this item as it is in the TableViewer.
As far as i now, i can add CellModifier and CellEditors to the line of Columns of the table, but the reference for the action is always the line object and not the selected TableItem.
Does somebody have an example how to create such a matrix inside a Composite?
I can create it by setting a GridLayout and adding the components in a for-loop, but than i get issues, when i want to redraw the Composite with new childrens. The TableViewer does already have this handling, so i dont want to implement it again.
I had the same problem a while ago and the only way I found to solve it was to register a mouse listener on the SWT table widget associated to the table viewer.
MouseListener columnSelectionMouseListener = new ColumnSelectionMouseListener();
getViewer().getTable().addMouseListener(columnSelectionMouseListener);
public class ColumnSelectionMouseListener implements MouseListener {
private TableColumn selectedColumn;
#Override
public void mouseDoubleClick(MouseEvent e) {
// Nothing to do here
}
#Override
public void mouseDown(MouseEvent e) {
table = (Table) e.widget;
TableItem item = table.getItem(new Point(e.x, e.y));
for (int i = 0; i < table.getColumnCount(); i++) {
TableColumn column = table.getColumn(i);
Rectangle bounds = item.getBounds(i);
if (bounds.contains(e.x, e.y)) {
selectedColumn = column;
}
}
}
#Override
public void mouseUp(MouseEvent e) {
// Nothing to do here
}
public TableColumn getSelectedField() {
return selectedColumn;
}
}
Then, for example in the viewer's selection listener, you can ask to the mouse listener which column was selected when the mouse has been pressed and combine that with the selected line coming from the viewer's selection to perform the appropriate action.
Hope this can help.
Manu
Maybe the following JFace snippet will help:
Snippet058CellNavigationIn34
Ingo