Problems binding JTable selectedRow to JTextField (org.jdesktop.beansbinding) - java

I have a Java Swing application and want to bind the selected row of a JTable to a JTextField. My binding looks as follows:
BeanProperty<JTable, Integer> tableBeanProperty = BeanProperty.create("selectedRow");
BeanProperty<JTextField, String> textFieldProperty = BeanProperty.create("text");
Binding<JTable, Integer, JTextField, String> binding = Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, table1, tableBeanProperty, field1, textFieldProperty);
binding.bind();
The text field is filled one time at the beginning with '-1', because no row is selected. If I click on a row, there is no update of the text field.
One ugly workaround is to call the unbind() and bind() method in the mouse listener of the table. But I think there is something missing during my binding.
Maybe one of you has an idea.
Thanks!

The documentation says, that "selectedElement" can be used for this purpose. With this property, it works without the ugly unbind() and bind().
Now the code looks as follows:
BeanProperty<JTable, MyObject> tableBeanProperty = BeanProperty.create("selectedElement");
BeanProperty<JTextField, String> textFieldProperty = BeanProperty.create("text");
Binding<JTable, MyObject, JTextField, String> binding = Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, table1, tableBeanProperty, field1, textFieldProperty);
binding.bind();
To convert "MyObject" to a "String", I added a converter to the binding.

Related

Vaadin 14 grid with checkboxes as rendered components

I created a grid that has four columns. The first column shows a name, the other three columns represent different roles. Each of those three columns is filled with check boxes in order to assign a specific role to a specific name. That's as far as i have come so far.
In each column and in each row there should only be one selected checkbox allowed. So in total i do have exactly one selection per checkbox column. How do i implement this?
Edit: I realize I might have misunderstood the question entirely. If you want to have 3 columns, with each having multiple CheckBoxes where only 1 can be selected per column, then you should use a RadioButtonGroup in each column and bind each to a different Enum field of your griditem class.
Instead of showing how to do three columns with a CheckBox in each, while only one CheckBox can be selected, I will show a different way to achieve the same information about the item.
The reason for this is the solution that what you want to achieve is not easily doable, since each CheckBox is defined in a scope that does not know the other Checkboxes of the same item. Therefore you would need to implement your only-one-selected rule inside the itemclass' setters, which is not optimal. I mean, it is possible, but I'd rather change the structure to something more apt. Usually you don't want to put this kind of business logic into your bean classes.
How would I solve the problem at hand?
Create a new Enum, which will replace all 3 boolean fields in your item class. Now in your grid you will only need one column for a ComboBox to select the enum.
I chose an Enum because this matches your needs here perfectly. With an Enum, you may have several options, but you can select only one (or none).
To better show what I mean, let's use an example Class for the Grid items, Foo. Your version has 3 booleans which your three grid-CheckBoxes are bound to. Let's call them isA, isB, isC.
// your version of the griditem class
public class Foo {
private boolean isA, isB, isC = false;
// constructor, getters, setters
}
// how the columns are added in the grid (approximately) (without editor):
Grid<Foo> grid = new Grid<>();
grid.addComponentColumn((item) -> {
CheckBox checkBox = new CheckBox();
checkBox.setValue(item.isA());
checkBox.addValueChangeListener(event -> item.setA(event.getValue()); // inside setA() method you need to set isB and isC to false if the new value is true. No good!
return checkBox;
});
grid.addComponentColumn((item) -> {
CheckBox checkBox = new CheckBox();
checkBox.setValue(item.isB());
checkBox.addValueChangeListener(event -> item.setB(event.getValue()); // inside setB() method you need to set isB and isC to false if the new value is true. No good!
return checkBox;
});
grid.addComponentColumn((item) -> {
CheckBox checkBox = new CheckBox();
checkBox.setValue(item.isC());
checkBox.addValueChangeListener(event -> item.setC(event.getValue()); // inside setC() method you need to set isB and isA to false if the new value is true. No good!
return checkBox;
});
And here is how it would look after my changes
public class Foo {
private AbcEnum abcEnum = null;
// constructor, getters, setters
}
public Enum AbcEnum {
A,
B,
C;
}
// how the columns are added (without editor):
Grid<Foo> grid = new Grid<>();
grid.addComponentColumn((item) -> {
ComboBox<AbcEnum> comboBox = new ComboBox<>();
comboBox.setValue(item.getAbcEnum());
comboBox.addValueChangeListener(event -> item.setAbcEnum(item.getValue()));
return comboBox;
});
I wrote "without editor" in the comments about adding the column, because this code will add the ComboBox/CheckBox as clickable and functional components for each grid item, without needing to open the editor for an item to change the values. If you are indeed using an editor, you can add these functional inputs as editorComponents (and bind them to the editor-binder instead of using setValue and addValueChangeListener), and show only the current value in the normal columns (not editable - therefore no inputs like CheckBox or ComboBox are required)

Updating Label with HashMap value

I have an issue, with binding a Label someLabel with a value.
So there is a class with a HashMap field used as an inventory:
public HashMap<Animals, Integer> inventory = new HashMap<>();
I need to display this Integer value live, like a timer of some sort.
The thing is, I tried to use bind property on the label, but it wil show only the initial value, and there are some issues with binding, as it wants a SimpleStringProperty class instance as a property. While my get(Object key) method is called, it returns a String after my modification, and won't let me do it...
Please point me in the right direction, should I monitor every time the method put() is called, to keep the label on the live by setText()?
HashMap does not implement Observable.
However JavaFX has ObservableMap which does implement Observable:
ObservableMap<Animals, Integer> inventory = FXCollections.observableHashMap();
Label label = ...
Animals key = ...
label.textProperty().bind(Bindings.valueAt(inventory, key).asString());
or for more control
label.textProperty().bind(Bindings.createStringBinding(() -> Objects.toString(inventory.get(key), "n/a"), inventory);

DynamicReports remove row if column is null

I am a little bit stuck with such an easy problem. I am using DynamicReports and I want to hide whole row if column value is null. As I know, DynamicReports is based on JasperReports and it's possible there to do that by checking TextField's option "Remove line when blank". How can I do that in Dynamic?
Components, which I use:
TextColumnBuilder, ColumnGroupBuilder, JasperReportBuilder
I want to hide whole row if any of my TextColumns would be null.
OK, after some thoughts, I found that this problem could be resolved in other way.
We gonna use column, group etc property setPrintWhenExpression(DRIExpression expression)
1. Create class, which will handle, print or not to print the row. Dynamic has the abstract class for doing this:
public class ShowExpressionDynamicReports extends AbstractSimpleExpression<Boolean> {
private String fieldName;
public ShowExpressionDynamicReports(String fieldName) {
this.fieldName = fieldName;
}
#Override
public Boolean evaluate(net.sf.dynamicreports.report.definition.ReportParameters reportParameters) {
return reportParameters.getValue(fieldName) != null;
}
}
You should extend AbstractSimpleExpression in order to pass it as parameter to methods which are listed below.
So, the column value is printed if evaluate(ReportParameters rp) returns true.
I've also added field fieldName which allows me to print (or not) column due to other's column state.
2. Add property to your
column:
setPrintWhenExpression(DRIExpression expression)
group:
.setPrintSubtotalsWhenExpression(DRIExpression expression)
or
setFooterPrintWhenExpression(DRIExpression expression)
or
setHeaderPrintWhenExpression(DRIExpression expression)
Depends on what you want to hide.
Example:
We have 2 columns in our report: Product and ProductCount columns. I would like to hide Product column if ProductCount is null (we have no information for this Product).
So, to do that i will add property PrintWhenExpression to Product column
TextColumnBuilder<String> productColumn = col.column("Product", "Product", type.stringType())
.setPrintWhenExpression(new ShowExpressionDynamicReports("ProductCount"));

Getting name of JComponent and assigning as parameter in PreparedStatement

Okay, so this is what I have so far and it works. However, I'm not able to specify to which ? (or parameter) the int 1 or 0 (boolean converted to int) is set (through setInt()). I tried using the getName() to see the component variable name but it returns null when I print it.
How can I assign a checkbox's value as parameter to my PreparedStatement if I'm not able to specify correctly on which textbox the value of 1 or 0 is from?
ps.setInt(1,valueOfUnknownCheckbox); //need to put the correct checkbox as 2nd argument.
I saw some information about using Java Reflection which I'm totally unfamiliar with. Is there any way without using Java Reflection?
Some of the checkbox values are not going to the correct database table's column.
I hope you can help with me guys. I wanted to be able to use List to collect components from containers to lessen the lines of codes.
Here's my code.
private void saveAdminPermissions(){
List<Component> adminPermissionsChbxs = fm.getComponentsAsList(administrationPermissionsCheckBoxPanel);
Boolean bool = null;
String updateSQL =
"UPDATE allusers_admin_permissions SET CURC_BTN=?, DISCOUNTS_BTN=?, SECTIONS_BTN=?,"
+ " USERS_BTN=?, SCHEDULING_BTN=?, YRLEVELS_BTN=?, ACCTG_BTN=? WHERE USERID=? ";
try(Connection con = DBUtil.getConnection(DBType.MYSQL);
PreparedStatement ps = con.prepareStatement(updateSQL);)
{
int x=1;
for(Component c : adminPermissionsChbxs){
if(c instanceof JCheckBox){
bool = ( (JCheckBox)c ).isSelected();
JOptionPane.showMessageDialog(null,"Name: "+ ((JCheckBox)c).getName() );
JOptionPane.showMessageDialog(null,bool);
} //--end of if
int boolToInt = (bool)?1:0 ;
ps.setInt(x, boolToInt);
x++;
}//--end of forloop
ps.setInt(8, um.getIdOfSelected(usersList));
ps.executeUpdate(); JOptionPane.showMessageDialog(null,"Update successful");
}catch(SQLException e){
JOptionPane.showMessageDialog(null,"Error#saveAdminPermissions\n"+ e.getMessage());
}
}//--end of method
Thanks.
Several approaches are possible:
Instead of looping though view components, create a permission model having a collection of states such as List<Boolean>. As shown in How to Use Check Boxes, let each JCheckBox have an ItemListener that updates its Boolean value in the List; an example is seen here. Use the list in constructing your PreparedStatement.
Alternatively, store the permission description and state in a suitable TableModel, and use a JTable as the view. As described in How to Use Tables: Concepts: Editors and Renderers, the default renderer/editor for a model value of type Boolean is a check box. Neither the renderer nor editor remember the value between calls to render or edit a cell's value, but the table underlying TableModel must do so. Some guidelines and a typical example are cited here. You should be able to invoke the table's getValueAt() method to find the current setting of the desired cell in a particular row and column, as shown here.

Table Field Factory for a Transient variable

I'd like to create a custom column for my vaadin table. All items should have a column with a checkbox. In order to have this column, I created a transient variable, which name is "selected". When the table makes its columns, the table.setTableFieldFactory() runs, but "selected" is not presented in the propertyIds' list.
table.setTableFieldFactory((container, itemId, propertyId, uiContext) -> {
if("selected".equals(propertyId)) {
CheckBox checkBox = new CheckBox();
checkBox.addValueChangeListener(event -> selectListener((Boolean)event.getProperty().getValue()));
return checkBox;
}
return null;
});
The questions are, how to create a custom field for transient variable? How should I add my transient variable to propertyIds' list? What Am I doing wrong?
Found out what was wrong. This table was a CustomTable, which was made by my mate. It has a column generator on Boolean.class. So when it was making the columns, its overwrote my definition.

Categories

Resources