How to implement editable grid with 2 related dropdown in wicket? - java

I need to show the data from DB in table format with edit, save , cancel, delete button, its called editable grid in wicket.
In Table row after click on edit button data should be shown on 2 dropdown choices and select data from 1st dropdown then 2nd dropdown data model should be changed based on selection of first dropdown.
I have gone through the https://github.com/wicketstuff/core/tree/master/editable-grid-parent. But its showing only editable grid with 1 dropdown in wicket and i want 2 dropdown. Please help on this.
UPDATE :
I have used this
private List<AbstractEditablePropertyColumn<Person, String>> getColumns()
{
List<AbstractEditablePropertyColumn<Person, String>> columns = new ArrayList<AbstractEditablePropertyColumn<Person, String>>();
stateDropDownPropertyColumn = new AbstractEditablePropertyColumn<Person, String>(new PropertyModel<String>(this, "selectedMake"), "state")
{
private static final long serialVersionUID = 1L;
public EditableCellPanel<Person> getEditableCellPanel(String componentId)
{
return getStateDDCellpanel(componentId,this);
}
};
cityDropDownPropertyColumn = new AbstractEditablePropertyColumn<Person, String>(new Model<String>("CarModel"), "city"){
private static final long serialVersionUID = 1L;
#Override
public EditableCellPanel<Person> getEditableCellPanel(String componentId) {
// TODO Auto-generated method stub
return getCityDDCellpanel(componentId,this);
}};
columns.add(stateDropDownPropertyColumn);
columns.add(cityDropDownPropertyColumn);
return columns;
}
private EditableRequiredDropDownCellPanel<Person, String> getStateDDCellpanel(String componentId,
AbstractEditablePropertyColumn<Person, String> DropDownPropertyColumn){
this.stateComponentID = componentId;
this.stateDropDownPropertyColumn = DropDownPropertyColumn;
stateDropDownCellPanel = new EditableRequiredDropDownCellPanel<Person, String>(stateComponentID, stateDropDownPropertyColumn, stateChoices);
return stateDropDownCellPanel;
}
private EditableRequiredDropDownCellPanel<Person, String> getCityDDCellpanel(String componentId,
AbstractEditablePropertyColumn<Person, String> DropDownPropertyColumn){
this.cityComponentID = componentId;
this.cityDropDownPropertyColumn = DropDownPropertyColumn;
cityDropDownCellPanel = new EditableRequiredDropDownCellPanel<Person, String>(cityComponentID, cityDropDownPropertyColumn, cityChoices);
cityDropDownCellPanel.setOutputMarkupId(true);
cityDropDownCellPanel.setOutputMarkupPlaceholderTag(true);
return cityDropDownCellPanel;
}
I have not any idea about this where i need to put up behaviours of dropdown cell.

Probably almost direct answer to question according to dynamic list (first is fixed, second id depended, dynamically computed):
http://examples7x.wicket.apache.org/ajax/choice
To be with SO rules not to include pure links, excerpt from official example Apache licensed
(prepared to be shorter - not compile)
Model allows You prepare changed data, and AJAX event forces refresh - this is core of idea. Event (ajax behaviour) connected to first 'makers', and behaviour forces to refresh 'models' . This is typical wicket+ajax pattern.
/**
* Linked select boxes example
*
* #author Igor Vaynberg (ivaynberg)
*/
public class ChoicePage extends BasePage
{
private String selectedMake;
private final Map<String, List<String>> modelsMap = new HashMap<>(); // map:company->model
/**
* #return Currently selected make
*/
public String getSelectedMake()
{
return selectedMake;
}
/**
* #param selectedMake
* The make that is currently selected
*/
public void setSelectedMake(String selectedMake)
{
this.selectedMake = selectedMake;
}
/**
* Constructor.
*/
public ChoicePage()
{
modelsMap.put("AUDI", Arrays.asList("A4", "A6", "TT"));
modelsMap.put("CADILLAC", Arrays.asList("CTS", "DTS", "ESCALADE", "SRX", "DEVILLE"));
modelsMap.put("FORD", Arrays.asList("CROWN", "ESCAPE", "EXPEDITION", "EXPLORER", "F-150"));
IModel<List<String>> makeChoices = new AbstractReadOnlyModel<List<String>>()
{
#Override
public List<String> getObject()
{
return new ArrayList<>(modelsMap.keySet());
}
};
IModel<List<String>> modelChoices = new AbstractReadOnlyModel<List<String>>()
{
#Override
public List<String> getObject()
{
List<String> models = modelsMap.get(selectedMake);
if (models == null)
{
models = Collections.emptyList();
}
return models;
}
};
Form<?> form = new Form("form");
add(form);
final DropDownChoice<String> makes = new DropDownChoice<>("makes",
new PropertyModel<String>(this, "selectedMake"), makeChoices);
final DropDownChoice<String> models = new DropDownChoice<>("models",
new Model<String>(), modelChoices);
models.setOutputMarkupId(true);
form.add(makes);
form.add(models);
...
makes.add(new AjaxFormComponentUpdatingBehavior("change")
{
#Override
protected void onUpdate(AjaxRequestTarget target)
{
target.add(models);
}
});
}
}
UPDATE after comment. Lets back to previous github code, must replace fixed list by model. How??? Derive or copy, add contructor with IModel ... Wicket has very good object design.
In similar way we add column types not known to (not planned) grid author.
BTW Your comment 'its not working' is very broad. Sorry, I can help if I can, but dont make full project for You. Hope You will enjoy with coding.
package org.wicketstuff.egrid.column;
import java.util.List;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.FormComponent;
/**
*
* #author Nadeem Mohammad
*
*/
public class EditableRequiredDropDownCellPanel<T, S> extends EditableCellPanel
{
private static final long serialVersionUID = 1L;
public EditableRequiredDropDownCellPanel(final String id, final PropertyColumn<T, S> column, #SuppressWarnings("rawtypes") final List choices)
{
super(id);
#SuppressWarnings("unchecked")
DropDownChoice<T> field = new DropDownChoice<T>("dropdown", choices); <--- **** Here should be model ****
field.setLabel(column.getDisplayModel());
add(field);
}
#Override
public FormComponent<?> getEditableComponent()
{
return (FormComponent<?>) get("dropdown");
}
}
then with changed class return here:
columns.add(new AbstractEditablePropertyColumn<Person, String>(new Model<String>("Age"), "age")
{
private static final long serialVersionUID = 1L;
public EditableCellPanel getEditableCellPanel(String componentId)
{
return new ***** EditableRequiredDropDownCellPanel ***** <Person, String>(componentId, this, Arrays.asList("10","11","12","13","14","15"));
}
});
add Beahviours too

Related

JTable with RowSorter changes selection upon filter change

This is a complicated problem, and unfortunately a small SSCCE would not be possible. Therefore I have a long SCCE that demonstrates the problem. The simplified sample program uses a simplified data source - Time Zones. To use it, select a Time Zone in the table, then change the filter with the buttons at the top. Notice the text at the bottom changing to show the application selection. The undesired behavior is that when shifting to a filter that does not include the selected value, the selected value in the model is cleared. Surprisingly, when the selection is filtered out, the value is updated to being not set; but when filtered back in, the application selection is returned.
The Swing-based application's design is a Model-ViewModel-View, the Model is supposed to be the authoritative source for the application's data, including what the current selection is. The Model can have multiple ViewModel-Views displaying the data in the Model. This current selection may be reflected in multiple views. The user should be able to change the selection from any View. The selection may or may not be visible in all Views if it doesn't apply to some Views (a real-world example might be a View that shows vehicle maintenance may not show trips being taken by the vehicle).
The sample program has a JLabel as a simplified View-only of the application's selection, which displays at the bottom of the app the selection in the model.
The other more relevant View is a JTable that shows one Time Zone (as a String) per row. It has a custom ListSelectionModel as the ViewModel that forwards change requests to the application Model, and listens to changes from the application Model and applies them to the selection by calling methods on super. This works as expected, at least until filtering is applied.
The process of filtering is done mostly within the JTable and its inner classes, such as JTable$SortManager. It seems to remember and clear the selection, perform the sort and filter, and then restore the selection or nothing if the selected value is not in the newly filtered set.
Unfortunately, in the ListSelectionModel, these clearing and selecting operations are changing the underlying selection in the application Model. In my actual application, the selection loads a lot more information to display about the selection, and is a relatively expensive operation, so spurious changes to this value should be avoided.
So the question is this: Is there a way to prevent the application Model's selection from being changed when changing the table filter? I imagine the solution would fall under one of these categories:
There may be some way of detecting within the ListSelectionModel when the filter/sort is in progress, and not update the application model while that is happening
There may be something that can be overridden somewhere to change the undesired behavior
Here is the sample code:
import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
import javax.swing.Box;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.RowFilter;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
public class TableProblem
extends JFrame
{
public static final class ApplicationModel
{
String[] data = TimeZone.getAvailableIDs();
public String[] getData() { return data; }
private String modelSelection;
public String getModelSelection() { return modelSelection; }
public void setModelSelection(String value) { modelSelection = value; fireModelSelectionChange(); }
private void fireModelSelectionChange()
{ selectionListeners.forEach(l -> l.modelSelectionChanged(modelSelection, findModelIndex(modelSelection))); }
private int findModelIndex(String value)
{
if (value != null)
for (int i = 0; i < data.length; i++)
if (value.equals(data[i]))
return i;
return -1;
}
private List<ApplicationModelSelectionListener> selectionListeners = new ArrayList<>();
public void addSelectionListener(ApplicationModelSelectionListener l) { selectionListeners.add(l); }
}
public interface ApplicationModelSelectionListener
{
void modelSelectionChanged(String selection, int selectedModelIndex);
}
/** This class acts as the selection ViewModel. The actual model is the
* passed-in ApplicationModel.
*/
public final class TimeZoneListSelectionModel
extends DefaultListSelectionModel
implements ApplicationModelSelectionListener
{
private final ApplicationModel appMdl;
private static final long serialVersionUID = 1L;
private TimeZoneListSelectionModel(ApplicationModel appMdl)
{
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
this.appMdl = appMdl;
appMdl.addSelectionListener(this);
}
// Requests to ListSelectionModel to modify the selection are passed
// to the appMdl
#Override
public void clearSelection()
{
appMdl.setModelSelection(null);
}
#Override
public void setSelectionInterval(int index0, int index1)
{
int modelIdx = tbl.convertRowIndexToModel(index0);
String value = appMdl.getData()[modelIdx];
appMdl.setModelSelection(value);
}
#Override
public void addSelectionInterval(int index0, int index1)
{
int modelIdx = tbl.convertRowIndexToModel(index0);
String value = appMdl.getData()[modelIdx];
appMdl.setModelSelection(value);
}
// Notification from the app model about selection change gets
// percolated back to the user interface
#Override
public void modelSelectionChanged(String selection, int selectedModelIndex)
{
if (selectedModelIndex == -1)
{
super.clearSelection();
return;
}
int viewIndex = tbl.convertRowIndexToView(selectedModelIndex);
if (viewIndex == -1)
super.clearSelection();
else
super.setSelectionInterval(viewIndex, viewIndex);
}
}
public static final class TimeZoneTableModel
extends AbstractTableModel
{
private static final long serialVersionUID = 1L;
private final String[] data;
public TimeZoneTableModel(String[] data)
{
this.data = data;
}
#Override public int getRowCount() { return data.length; }
#Override public int getColumnCount() { return 1; }
#Override
public Object getValueAt(int rowIndex, int columnIndex)
{
if (columnIndex == 0)
return data[rowIndex];
throw new IllegalArgumentException("columnIndex="+columnIndex+" should be < 1");
}
#Override public String getColumnName(int column)
{ return "Time Zone"; }
}
private static final class StringRowFilter
extends RowFilter<TableModel, Integer>
{
private String prefix;
public void setPrefix(String value) { prefix = value; rowSorter.sort(); }
private final TableRowSorter<TableModel> rowSorter;
public StringRowFilter(TableRowSorter<TableModel> rowSorter)
{
this.rowSorter = rowSorter;
}
#Override
public boolean include(
Entry<? extends TableModel, ? extends Integer> entry)
{
if (prefix == null)
return true;
String lowerCase = entry.getStringValue(0).toLowerCase();
return lowerCase.startsWith(prefix);
}
}
private static final long serialVersionUID = 1L;
public static void main(String[] args)
{
ApplicationModel appMdl = new ApplicationModel();
SwingUtilities.invokeLater(() -> new TableProblem(appMdl).setVisible(true));
}
private final JTable tbl;
public TableProblem(ApplicationModel appMdl)
{
super("View-ModelView-Model Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TimeZoneTableModel mdl = new TimeZoneTableModel(appMdl.getData());
tbl = new JTable(mdl);
tbl.setAutoCreateRowSorter(true);
TimeZoneListSelectionModel tzListSelectionModel = new TimeZoneListSelectionModel(appMdl);
tbl.setSelectionModel(tzListSelectionModel);
#SuppressWarnings("unchecked")
TableRowSorter<TableModel> rowSorter = (TableRowSorter<TableModel>)tbl.getRowSorter();
StringRowFilter filter = new StringRowFilter(rowSorter);
rowSorter.setRowFilter(filter);
Box filterButtons = createFilterButtons(filter);
Box vbox = Box.createVerticalBox();
vbox.add(filterButtons);
vbox.add(new JScrollPane(tbl));
JLabel mdlSelect = new JLabel("App Model selection: ");
appMdl.addSelectionListener((selection, selectedModelIndex) ->
mdlSelect.setText("App Model selection: " + selection + " (" +
selectedModelIndex + ")"));
vbox.add(mdlSelect);
add(vbox, BorderLayout.CENTER);
pack();
}
private static Box createFilterButtons(StringRowFilter filter)
{
Box filterButtons = Box.createHorizontalBox();
filterButtons.add(new JLabel("Filter: "));
for (String filterStr : "All,Africa,America,Antarctica,Asia,Australia,Canada,Europe,Pacific,Us".split(","))
addFilterButton(filter, filterButtons, filterStr);
return filterButtons;
}
private static void addFilterButton(StringRowFilter filter,
Box filterButtons, String buttonName)
{
String filterPrefix = "All".equals(buttonName) ? null : buttonName.toLowerCase();
JButton asiaButton = new JButton(buttonName);
asiaButton.addActionListener(ae -> filter.setPrefix(filterPrefix));
filterButtons.add(asiaButton);
}
}
A disappointing and unsatisfying solution to this problem is upon requesting a change of the filter value, before telling the JTable's RowSorter, clear out the currently selected item in the model.
This is a change in the behavior, where the selection gets cleared, but prevents spurious clearing and resetting of the value when clicking through the filter values.
The change to the example code would involve passing the selection model to the action of the filter button. The three methods that would change are below.
public TableProblem(ApplicationModel appMdl)
{
super("View-ModelView-Model Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TimeZoneTableModel mdl = new TimeZoneTableModel(appMdl.getData());
tbl = new JTable(mdl);
tbl.setAutoCreateRowSorter(true);
TimeZoneListSelectionModel tzListSelectionModel = new TimeZoneListSelectionModel(appMdl);
tbl.setSelectionModel(tzListSelectionModel);
#SuppressWarnings("unchecked")
TableRowSorter<TableModel> rowSorter = (TableRowSorter<TableModel>)tbl.getRowSorter();
StringRowFilter filter = new StringRowFilter(rowSorter);
rowSorter.setRowFilter(filter);
Box filterButtons = createFilterButtons(filter, tzListSelectionModel);
Box vbox = Box.createVerticalBox();
vbox.add(filterButtons);
vbox.add(new JScrollPane(tbl));
JLabel mdlSelect = new JLabel("App Model selection: ");
appMdl.addSelectionListener((selection, selectedModelIndex) ->
mdlSelect.setText("App Model selection: " + selection + " (" +
selectedModelIndex + ")"));
vbox.add(mdlSelect);
add(vbox, BorderLayout.CENTER);
pack();
}
private static Box createFilterButtons(StringRowFilter filter,
TimeZoneListSelectionModel tzListSelectionModel)
{
Box filterButtons = Box.createHorizontalBox();
filterButtons.add(new JLabel("Filter: "));
for (String filterStr : "All,Africa,America,Antarctica,Asia,Australia,Canada,Europe,Pacific,Us".split(","))
addFilterButton(filter, filterButtons, filterStr, tzListSelectionModel);
return filterButtons;
}
private static void addFilterButton(StringRowFilter filter,
Box filterButtons, String buttonName,
TableProblem.TimeZoneListSelectionModel tzListSelectionModel)
{
String filterPrefix = "All".equals(buttonName) ? null : buttonName.toLowerCase();
JButton asiaButton = new JButton(buttonName);
asiaButton.addActionListener(ae -> {
tzListSelectionModel.clearSelection();
filter.setPrefix(filterPrefix);
});
filterButtons.add(asiaButton);
}
Notice I will not be marking this Answer as the solution because it is more of a workaround, and an actual solution to the problem is preferred.

Setting and Getting parameters in a JavaFX application

I have this method in my application which is constructing RadioButtons using an helper class: Mode. I would like to call out of the createModesRadios method .getText() for the user's selected RadioButton. Also I would like to save the user's choices in order to remember them in a following use. Is there an easy way to call them and set the choices into the CheckBoxes, into the RadioButtons and into the PrefixSelectionComboBoxs?
I am using a Model Class Configuration.java in order to store the information, because I will need to process some calculations with the user inputs. I would like to store in it also the choices made from the controllers mentioned above.
Part of my Class
public class ConfigurationEditDialogController {
// General Tab
#FXML
private TextField configurationNameField;
#FXML
private TextField commentField;
#FXML
private TextField creationTimeField;
#FXML
private TextField startAddress;
#FXML
private ToggleSwitch triggerEnable;
#FXML
private ToggleSwitch softwareTrigger;
#FXML
private ToggleSwitch ctsEnable;
// Data Acquisition Tab
#FXML
private Pane dataAcquisitionTab;
#FXML
private Button okButton;
private Mode[] modes = new Mode[]{
new Mode("Vertical", 4),
new Mode("Hybrid", 2),
new Mode("Horizontal", 1)
};
private int count = Stream.of(modes).mapToInt(Mode::getCount).max().orElse(0);
private ToggleGroup group = new ToggleGroup();
private IntegerProperty elementCount = new SimpleIntegerProperty();
private ObservableMap<Integer, String> elements = FXCollections.observableHashMap();
CheckBox[] checkBoxes = new CheckBox[count];
private ObservableList<String> options = FXCollections.observableArrayList(
"ciao",
"hello",
"halo");
private Stage dialogStage;
private Configuration configuration;
private boolean okClicked = false;
/**
* Initializes the controller class. This method is automatically called
* after the fxml file has been loaded.
*/
#FXML
private void initialize() {
HBox radioBox = createModesRadios(elementCount, modes);
GridPane grid = new GridPane();
VBox root = new VBox(20, radioBox);
root.setPrefSize(680, 377);
grid.setHgap(40);
grid.setVgap(30);
grid.setAlignment(Pos.CENTER);
elementCount.addListener((o, oldValue, newValue) -> {
// uncheck checkboxes, if too many are checked
updateCheckBoxes(checkBoxes, newValue.intValue(), -1);
});
for (int i = 0; i < count; i++) {
final Integer index = i;
CheckBox checkBox = new CheckBox();
checkBoxes[i] = checkBox;
PrefixSelectionComboBox<String> comboBox = new PrefixSelectionComboBox<>();
comboBox.setItems(options);
comboBox.setPromptText("Select Test Bus " + i);
comboBox.setPrefWidth(400);
comboBox.setVisibleRowCount(options.size() -1);
comboBox.valueProperty().addListener((o, oldValue, newValue) -> {
// modify value in map on value change
elements.put(index, newValue);
});
comboBox.setDisable(true);
checkBox.selectedProperty().addListener((o, oldValue, newValue) -> {
comboBox.setDisable(!newValue);
if (newValue) {
// put the current element in the map
elements.put(index, comboBox.getValue());
// uncheck checkboxes that exceed the required count keeping the current one unmodified
updateCheckBoxes(checkBoxes, elementCount.get(), index);
} else {
elements.remove(index);
}
});
grid.addRow(i, comboBox, checkBox);
}
// enable Ok button iff the number of elements is correct
okButton.disableProperty().bind(elementCount.isNotEqualTo(Bindings.size(elements)));
root.getChildren().add(grid);
dataAcquisitionTab.getChildren().add(root);
}
/**
* Create Radio Buttons with Mode class helper
*
* #param count
* #param modes
* #return
*/
private HBox createModesRadios(IntegerProperty count, Mode... modes) {
ToggleGroup group = new ToggleGroup();
HBox result = new HBox(50);
result.setPadding(new Insets(20, 0, 0, 0));
result.setAlignment(Pos.CENTER);
for (Mode mode : modes) {
RadioButton radio = new RadioButton(mode.getText());
radio.setToggleGroup(group);
radio.setUserData(mode);
result.getChildren().add(radio);
radio =
}
if (modes.length > 0) {
group.selectToggle((Toggle) result.getChildren().get(0));
count.bind(Bindings.createIntegerBinding(() -> ((Mode) group.getSelectedToggle().getUserData()).getCount(), group.selectedToggleProperty()));
} else {
count.set(0);
}
return result;
}
/**
* Method for updating CheckBoxes depending on the selected modek
*
* #param checkBoxes
* #param requiredCount
* #param unmodifiedIndex
*/
private static void updateCheckBoxes(CheckBox[] checkBoxes, int requiredCount, int unmodifiedIndex) {
if (unmodifiedIndex >= 0 && checkBoxes[unmodifiedIndex].isSelected()) {
requiredCount--;
}
int i;
for (i = 0; i < checkBoxes.length && requiredCount > 0; i++) {
if (i != unmodifiedIndex && checkBoxes[i].isSelected()) {
requiredCount--;
}
}
for (; i < checkBoxes.length; i++) {
if (i != unmodifiedIndex) {
checkBoxes[i].setSelected(false);
}
}
}
/**
* Sets the stage of this dialog.
*
* #param dialogStage
*/
public void setDialogStage(Stage dialogStage) {
this.dialogStage = dialogStage;
}
/**
* Sets the configuration to be edited in the dialog.
*
* #param configuration
*/
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
configurationNameField.setText(configuration.getConfigurationName());
commentField.setText(configuration.getComment());
//Set the comboboxes and the checkboxes and the radiobutton
creationTimeField.setText(LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm")));
}
/**
* Returns true if the user clicked OK, false otherwise.
*
* #return
*/
public boolean isOkClicked() {
return okClicked;
}
/**
* Called when the user clicks ok.
*/
#FXML
private void handleOk() {
if (isInputValid()) {
configuration.setConfigurationName(configurationNameField.getText());
configuration.setComment(commentField.getText());
configuration.setTestBus1(elements.get(0));
configuration.setTestBus2(elements.get(1));
configuration.setTestBus3(elements.get(2));
configuration.setTestBus4(elements.get(3));
configuration.setCreationTime(DateTimeUtil.parse(creationTimeField.getText()));
// Store the information of the sample mode (vertical, hybrid or horizontal).
okClicked = true;
dialogStage.close();
}
}
Mode Helper Class
public class Mode {
private final String text;
private final int count;
public Mode(String text, int count) {
this.text = text;
this.count = count;
}
public String getText() {
return text;
}
public int getCount() {
return count;
}
}
Configuration.java
public class Configuration {
private final StringProperty configurationName;
private final StringProperty comment;
private final StringProperty testBus1;
private final StringProperty testBus2;
private final StringProperty testBus3;
private final StringProperty testBus4;
private final StringProperty triggerSource;
private final StringProperty sampleMode;
private final StringProperty icDesign;
private final StringProperty triggerMode;
private final DoubleProperty acquisitionTime;
private final ObjectProperty<LocalDateTime> creationTime;
/**
* Default constructor.
*/
public Configuration() {
this(null, null);
}
/**
* Constructor with some initial data.
*
* #param configurationName
* #param comment
*/
public Configuration(String configurationName, String comment) { //todo initialize null values
this.configurationName = new SimpleStringProperty(configurationName);
this.comment = new SimpleStringProperty(comment);
// Some initial sample data, just for testing.
this.testBus1 = new SimpleStringProperty("");
this.testBus2 = new SimpleStringProperty("");
this.testBus3 = new SimpleStringProperty("");
this.testBus4 = new SimpleStringProperty("");
this.triggerSource = new SimpleStringProperty("");
this.sampleMode = new SimpleStringProperty("");
this.icDesign = new SimpleStringProperty("Ceres");
this.triggerMode = new SimpleStringProperty("Internal");
this.acquisitionTime = new SimpleDoubleProperty(2346.45);
this.creationTime = new SimpleObjectProperty<>(LocalDateTime.of(2010, 10, 20,
15, 12));
}
/**
* Getters and Setters for the variables of the model class. '-Property' methods for the lambdas
* expressions to populate the table's columns (just a few used at the moment, but everything
* was created with scalability in mind, so more table columns can be added easily)
*/
// If more details in the table are needed just add a column in
// the ConfigurationOverview.fxml and use these methods.
// Configuration Name
public String getConfigurationName() {
return configurationName.get();
}
public void setConfigurationName(String configurationName) {
this.configurationName.set(configurationName);
}
public StringProperty configurationNameProperty() {
return configurationName;
}
// Comment
public String getComment() {
return comment.get();
}
public void setComment (String comment) {
this.comment.set(comment);
}
public StringProperty commentProperty() {
return comment;
}
// Test Bus 1
public String getTestBus1() {
return testBus1.get();
}
public void setTestBus1(String testBus1) {
this.testBus1.set(testBus1);
}
public StringProperty testBus1Property() {
return testBus1;
}
// Test Bus 2
public String getTestBus2() {
return testBus2.get();
}
public void setTestBus2(String testBus2) {
this.testBus2.set(testBus2);
}
public StringProperty testBus2Property() {
return testBus2;
}
// Test Bus 3
public String getTestBus3() {
return testBus3.get();
}
public void setTestBus3(String testBus3) {
this.testBus3.set(testBus3);
}
public StringProperty testBus3Property() {
return testBus3;
}
// Test Bus 4
public String getTestBus4() {
return testBus4.get();
}
public void setTestBus4(String testBus4) {
this.testBus4.set(testBus4);
}
public StringProperty testBus4Property() {
return testBus4;
}
// Trigger Source
public String getTriggerSource(){
return triggerSource.get();
}
public void setTriggerSource (String triggerSource){
this.triggerSource.set(triggerSource);
}
public StringProperty triggerSourceProperty() {
return triggerSource;
}
// Sample Mode
public String getSampleMode() {
return sampleMode.get();
}
public void setSampleMode (String sampleMode){
this.sampleMode.set(sampleMode);
}
public StringProperty sampleModeProperty() {return sampleMode;}
// IC Design
public String getIcDesign() {
return icDesign.get();
}
public void setIcDesign (String icDesign){
this.icDesign.set(icDesign);
}
public StringProperty icDesignProperty() {
return icDesign;
}
// Trigger Mode
public String getTriggerMode() {
return triggerMode.get();
}
public void setTriggerMode (String triggerMode){
this.triggerMode.set(triggerMode);
}
public StringProperty triggerModeProperty() {return triggerMode;}
// Acquisition Time
public double getAcquisitionTime() {
return acquisitionTime.get();
}
public void setAcquisitionTime(double acquisitionTime){
this.acquisitionTime.set(acquisitionTime);
}
public DoubleProperty acquisitionTimeProperty() {
return acquisitionTime;
}
// Last modified - Creation Time
#XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
public LocalDateTime getCreationTime() {
return creationTime.get();
}
public void setCreationTime(LocalDateTime creationTime){
this.creationTime.set(creationTime);
}
public ObjectProperty<LocalDateTime> creationTimeProperty() {
return creationTime;
}
}
You can use the java.util.Properties class to easily read/write settings like this to/from an XML file.
Save To Properties
Properties props = new Properties();
// Set the properties to be saved
props.setProperty("triggerMode", triggerMode.get());
props.setProperty("acquisitionTime", String.valueOf(acquisitionTime.get()));
// Write the file
try {
File configFile = new File("config.xml");
FileOutputStream out = new FileOutputStream(configFile);
props.storeToXML(out,"Configuration");
} catch (IOException e) {
e.printStackTrace();
}
This creates the config.xml file and populates it with all the properties you set using the props.setProperty() method.
Within the props.setProperty() method, you have two parameters. The first is the name of the property, the second is the actual value. The name is important as you will use it to read the appropriate value later.
The above code outputs the following XML file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Configuration</comment>
<entry key="acquisitionTime">12.0</entry>
<entry key="triggerMode">My Trigger Mode</entry>
</properties>
Read from Properties
Reading from the XML file is just as simple. Use the loadFromXML() method:
FileInputStream in;
// Load the settings file
in = new FileInputStream(DataFiles.LOCAL_SETTINGS_FILE);
properties.loadFromXML(in);
From there, you can set your Configuration model object by getting each property:
configuration.setAcquisitionTime(props.getProperty("acquisitionTime", "0.0"));
configuration.setTriggerMode(props.getProperty("triggerMode", "Manual"));
The getProperty() method also takes two parameters. The first is obviously the name of the property we saved earlier. The second is the default value to use if the requested property name does not exist in the XML file.
Pretty simple!
I do recommend updating all the values in your Configuration.java model and saving properties from there (instead of trying to save the properties directly from your textfields, comboboxes, etc).
EDIT
In order to retrieve the values from your controls within the for loop, you need to add them to a list that is accessible from outside that loop.
Create appropriate lists to hold the controls as their created:
List<PrefixSelectionComboBox<String>> comboBoxes = new ArrayList<PrefixSelectionComboBox<String>>();
List<CheckBox> checkBoxes = new ArrayList<>();
At the bottom of your loop, add the new controls to these lists:
comboBoxes.add(comboBox);
checkBoxes.add(checkBox);
grid.addRow(i, comboBox, checkBox);
Now, when you need their values, you can iterate over those lists to extract them:
for (PrefixSelectionComboBox cb : comboBoxes) {
cb.getValue(); // Do with this what you must
}
for (CheckBox cb : checkBoxes) {
cb.isSelected();
}

Q: How to print a specific field of a specific row from my TableView?

i have the following problem: I read out database items in an observable list. Now I want to display some items from the selected line in a few textfields on the right side of my tableview.
I got the observable-line-index with the following code, but I want to select an other column of the line.
AnalysemethodenTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
public void changed(ObservableValue<?> observable, Object oldvalue, Object newValue) {
index.set(analysemethodendata.indexOf(newValue));
databaseIndex = (analysemethodendata.indexOf(newValue) + 1);
System.out.println("Index:\t" + databaseIndex);
}
});
I found the following code: Click
But i don't understand this. It's something like to write a new list and place a copy of the items of the observable list in this new list.
I think, if I have the index of the line with my code, I can select the other items in the line of the observable list, too (I thought like "x,y" like an array)
If i cast it to String, the output is only machine code.
Hope I can understand the solution with your help!
EDIT: I inserted the following code:
System.out.println(analysemethodendata.get(databaseIndex).toString());
But I only get machine code in my Output:
table.analysemethoden_table#63c0d5b7
EDIT 2:
Table-Controller-Code:
package table;
import javafx.beans.property.SimpleFloatProperty;
import javafx.beans.property.SimpleStringProperty;
public class analysemethoden_table {
private final SimpleStringProperty rAmnorm;
private final SimpleStringProperty rMethverantw;
private final SimpleFloatProperty rBestimmungsgrenze;
private final SimpleFloatProperty rNachweisgrenze;
public analysemethoden_table (String sAmnorm, String sMethoverantw, Float sBestimmungsgrenze, Float sNachweisgrenze) {
this.rAmnorm = new SimpleStringProperty(sAmnorm);
this.rMethverantw = new SimpleStringProperty(sMethoverantw);
this.rBestimmungsgrenze = new SimpleFloatProperty(sBestimmungsgrenze);
this.rNachweisgrenze = new SimpleFloatProperty(sNachweisgrenze);
}
// Getter- und Setter-Methoden
/** rAmnorm **/
public String getRAmnorm() {
return rAmnorm.get();
}
public void setRAmnorm(String set) {
rAmnorm.set(set);
}
/** rMethverantw **/
public String getRMethverantw() {
return rMethverantw.get();
}
public void setRMethverantw(String set) {
rMethverantw.set(set);
}
/** rBestimmungsgrenze **/
public Float getRBestimmungsgrenze() {
return rBestimmungsgrenze.get();
}
public void setRBestimmungsgrenze(Float set) {
rBestimmungsgrenze.set(set);
}
/** rNachweisgrenze **/
public Float getRNachweisgrenze() {
return rNachweisgrenze.get();
}
public void setRNachweisgrenze(Float set) {
rNachweisgrenze.set(set);
}
}
You need to use
analysemethodendata.get(databaseIndex).getRAmnorm();
or any other getter method in place of getRAmnorm() to get the required output.
databaseIndex -> row number

how I can put a dynamic filtered xpage view / repeat control into a hashmap?

Can I easily put the entry values of a filtered view into a hashmap?
I have a repeat control, bound to a view, with a dynamic filter.
The user can change the filter by several djFilteringSelect controls, corresponding to the view columns.
Depending on the selection in the 1st djFilteringSelect, the selection in the next djFilteringSelects should be limited to the possible entries ("similar to the data filter in excel"). At the moment I do this with separate #dbcolumn/#dblookup methods for the djFilteringSelects, but I think it is much better and easier to just fill the view entries values into a hashmap and show the hashmap values in the djFilteringSelect.
I found few threads here with repeat controls and hashmaps, but these examples also build the doc collection separatly, which I wish to avoid.
Thanks for any help,
Uwe
There's a reason why all these examples build their document collections separately. Instead of "the view is in the UI", so I must use it, you might have an easier time to build a bean that serves as the source for your repeat control. A bean data source or a managed bean. This will allow for a use case, where you show 2 filter results (e.g England/London and France/Lyon) in one display, something a filtered view can't do.
Update
If you have a lot of reader/author fields, you want to have a view categorized by them, to populate your "backing bean" - there is lot of performance to gain. Holding a few hundred items in memory isn't a big deal.
There are 2 trains of though: make it generic, so every line in the view ends up as a Collection item (Array, List, Map etc.) or to build dedicated line items with clear names. This trains collide quite often, let me take you to the dedicated train for a moment. :-) So your classes (you need 2) would look like this:
package test;
import java.io.Serializable;
import java.util.Vector;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;
import lotus.domino.ViewEntry;
public class Fruit implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String color;
private String shape;
private String taste;
private String unid = null;
public Fruit() {
// default constructor, might not be needed
}
// To make it easy from a view
public Fruit(final ViewEntry ve) {
try {
#SuppressWarnings("rawtypes")
Vector v = ve.getColumnValues();
// 0 would be the user/group/role
this.setName(v.get(1).toString());
this.setColor(v.get(2).toString());
this.setShape(v.get(3).toString());
this.setTaste(v.get(4).toString());
this.unid = ve.getUniversalID();
} catch (NotesException e) {
e.printStackTrace();
}
}
public void save(Database db) throws NotesException {
Document doc;
if (this.unid == null) {
doc = db.createDocument();
} else {
doc = db.getDocumentByUNID(this.unid);
}
doc.replaceItemValue("Color", this.getColor());
// more here
doc.save();
}
public final String getName() {
return this.name;
}
public final void setName(String name) {
this.name = name;
}
public final String getColor() {
return this.color;
}
public final void setColor(String color) {
this.color = color;
}
public final String getShape() {
return this.shape;
}
public final void setShape(String shape) {
this.shape = shape;
}
public final String getTaste() {
return this.taste;
}
public final void setTaste(String taste) {
this.taste = taste;
}
}
That's to hold a line item (using my favourite fruits example). In your code the repeat control variable (or the data table variable) - instead of the view control, would hold one Fruit instance coming from fruitController.getSelectedFruits() (which you can use in EL as fruitController.selectedFruits), so you can bind your columns using varName.color, varname.shape
The class around it looks roughly like:
package test;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import lotus.domino.Database;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.View;
import lotus.domino.ViewEntry;
import lotus.domino.ViewEntryCollection;
public class FruitController implements Serializable {
private static final long serialVersionUID = 1L;
private static final String FRUIT_VIEW = "(FruitsByUser)";
private final Collection<Fruit> allFruits = new ArrayList<Fruit>();
private final Set<String> colors = new TreeSet<String>();
private final Set<String> shape = new TreeSet<String>();
private final Set<String> taste = new TreeSet<String>();
private String colorFilter = null;
private String tasteFilter = null;
private String shapeFilter = null;
// if you use this controller, you only can use an object data source!
// for a bean you would need an empty controller
public FruitController(final Session s, final Database db) {
this.populateData(s, db);
}
public final String getColorFilter() {
return this.colorFilter;
}
public final String[] getColors() {
return (String[]) this.colors.toArray();
}
public Collection<Fruit> getSelectedFruits() {
Collection<Fruit> result = new ArrayList<Fruit>();
for (Fruit f : this.allFruits) {
if (this.matchesFilter(f)) {
result.add(f);
}
}
return result;
}
public final String[] getShape() {
return (String[]) this.shape.toArray();
}
public final String getShapeFilter() {
return this.shapeFilter;
}
public final String[] getTaste() {
return (String[]) this.taste.toArray();
}
public final String getTasteFilter() {
return this.tasteFilter;
}
public void resetFilters() {
this.setColorFilter(null);
this.setShapeFilter(null);
this.setTasteFilter(null);
}
public final void setColorFilter(String colorFilter) {
this.colorFilter = colorFilter;
}
public final void setShapeFilter(String shapeFilter) {
this.shapeFilter = shapeFilter;
}
public final void setTasteFilter(String tasteFilter) {
this.tasteFilter = tasteFilter;
}
private boolean matchesFilter(Fruit f) {
boolean result = true;
result = ((result == false) ? false : ((this.colorFilter == null || "".equals(this.colorFilter.trim())) ? true
: (this.colorFilter.equals(f.getColor()))));
result = ((result == false) ? false : ((this.tasteFilter == null || "".equals(this.tasteFilter.trim())) ? true
: (this.tasteFilter.equals(f.getTaste()))));
result = ((result == false) ? false : ((this.shapeFilter == null || "".equals(this.shapeFilter.trim())) ? true
: (this.shapeFilter.equals(f.getShape()))));
return result;
}
private void populateData(final Session s, final Database db) {
try {
final View v = db.getView(FRUIT_VIEW);
// You might need to loop a little here to get all the values
final ViewEntryCollection vec = v.getAllEntriesByKey(s.getUserName());
ViewEntry ve = vec.getFirstEntry();
while (ve != null) {
ViewEntry nextVe = vec.getNextEntry(ve);
Fruit f = new Fruit(ve);
this.updateSelectors(f);
this.allFruits.add(f);
ve = nextVe;
nextVe.recycle();
}
vec.recycle();
v.recycle();
} catch (NotesException e) {
// TODO Stacktrace is no error handling
e.printStackTrace();
}
}
private void updateSelectors(Fruit f) {
this.colors.add(f.getColor());
this.shape.add(f.getShape());
this.taste.add(f.getTaste());
}
}
Of course you can make that more sophisticated by filtering the selection values based on the other selections (e.g. after picking a color only offer the shapes that are available in that color). Using the class as object datasource (e.g. fruitController) should be easy. You can bind your dropdowns to fruitController.colorFilter etc. in EL and define the selections in EL as fruitController.Colors.
Update 2
The data source should be an object data source, like this one:
<xp:this.data>
<xe:objectData var="fruitController" ignoreRequestParams="true"
readonly="false" scope="view"
createObject="#{javascript:return new test.FruitController(session, database);}">
</xe:objectData>
</xp:this.data>
For a bean approach you would need to edit the faces-config.xml and change the class to have a parameterless constructor. For the select values you could stick with the toArray() call in your page or better change the class to return an array in the first place. I updated the class above accordingly (so you can still use EL, no need for SSJS).
Now you only need to add a refresh to the repeat in the onChange event of your selects. Since the new values will be send to the object data source (you bound them to colorFilter, shapeFilter, tasteFilter) the refresh will execute #{fruitController.selectedFruits} which delivers the subset back to the panel.
So the concept here is: You fetch all the user data once into the object data source and once that is loaded filter inside that class, no renewed retrieval or lookup required.
Let us know hoe it goes

Java: Filling a JComboBox with objects

I'm trying to fill a jComboBox with objects. I have it working in one class, but in this class it's giving a NullPointerException but the code is almost the same. What am I missing here?
The code I'm using to fill the comboboxes:
I have translated every variable to English and removed some unnescessary stuff. I hope it's more clear for you guys now:
package unive.billing.boundary.clientmanager.frames;
import unive.billing.control.ClientsManager;
import unive.billing.control.InsuranceManager;
/**
*
* #author Forza
*/
public class ClientFrame extends javax.swing.JFrame {
/**
* Creates new form AddClientGUI
*/
private ClientsManager clientmanager;
private InsuranceManager insurancemanager;
public ClientFrame() {
initComponents();
clientmanager = new ClientsManager();
clientmanager.printList();
updateComboBoxCompany();
updateComboBoxInsurance();
}
private ClientsManager clientmanager;
private InsuranceManager insurancemanager;
public ClientFrame() {
initComponents();
clientmanager = new ClientsManager();
clientmanager.printList();
updateComboBoxCompany();
updateComboBoxInsurance();
}
public void updateComboBoxCompany()
{
for (Object object : insurancemanager.getCompanyNames())
{
companyComboBox.addItem(object);
}
}
public void updateComboBoxInsurance()
{
for (Object object : insurancemanager.getPolicyNames())
{
insuranceComboBox.addItem(object);
}
}
Here are the methods used:
public Object[] getCompanyNames()
{
ArrayList<String> cnames = new ArrayList<String>();
for (InsurancesCompany company : insurancecompanyList)
{
cnames.add(company.getCompanyName());
}
return cnames.toArray();
}
public Object[] getPolicyNames()
{
ArrayList<String> vnames = new ArrayList<String>();
for (Insurance insurance : insuranceList)
{
vnames.add(insurance.getPolicyName());
}
return vnames.toArray();
}
This is how my lists are initialized:
public class InsuranceManager {
private String insurancePath;
private String insurancecompanyenPath;
private static List<InsurancesCompany> insurancecompanyList;
private static List<Insurance> insuranceList;
private Insurance currentInsurance;
public InsuranceManager() {
insurancecompanyenPath = "Files/company.txt";
insurancePath = "Files/insurance.txt";
insuranceList = new List<>();
}
public void createNewList()
{
insurancecompanyList = new List<>();
System.out.println("Creates list");
}
public Object[] getCompanyNames()
{
ArrayList<String> cnames = new ArrayList<String>();
for (InsurancesCompany company : insurancecompanyList)
{
cnames.add(company.getCompanyName());
}
return cnames.toArray();
}
public Object[] getPolicyNames()
{
ArrayList<String> vnames = new ArrayList<String>();
for (Insurance insurance : insuranceList)
{
vnames.add(insurance.getPolicyName());
}
return vnames.toArray();
}
Edit: Here's the MainGUI which calls createNewList (maakLijstAan)
private ClientsManager clientsmanager;
private BillingManager billingmanager;
private InsuranceManager insurancemanager;
public MainGUI() {
clientsmanager = new ClientsManager();
clientsmanager.CreateNewList();
insurancemanager = new InsuranceManager();
insurancemanager.CreateNewList();
insurancemanager.loadInsuranceCompanyList();
initComponents();
jMenuItem1.setText("Save clients");
jMenuItem2.setText("Load clients");
jMenuItem3.setText("Exit");
}
You never initialize verzekeringBeheer, therefore you get a NullPointerException when you try to invoke methods on that variable.
You should have somewhere in your constructor, something like this:
verzekeringbeheer = new VerzekeringBeheer();
Also, try to avoid making your code coupled with other parts of your code. For example:
public VerzekeringBeheer() {
...
//verzekeringmaatschappijLijst is never initialized!!!
}
public void maakLijstAan()
{
verzekeringmaatschappijLijst = new Lijst<>();
System.out.println("Maak lijst aan");
}
public Object[] getMaatschappijNamen()
{
ArrayList<String> mnamen = new ArrayList<String>();
// Here you use verzekeringmaatschappijLijst without checking that is not null!!!
for (VerzekeringsMaatschappij maatschappij : verzekeringmaatschappijLijst)
{
mnamen.add(maatschappij.getMaatschappijNaam());
}
return mnamen.toArray();
}
If nobody calls maakLijstAan, you will get a NullPointerException in getMaatschappijNamen. Try to avoid code that is so dependent of external code, in order to run without problems.
all data for JComboBox are stored in ComboBoxModel
set ComboBoxModel for proper Objects type (String, Integer, Icon or simple Object), Java7 implements Generics, there are significant differiences in compare with Java6
all updates (to the JComboBox or its Model) must be done on Event Dispatch Thread
I only see you useing variables but for me they are nit initialized. So they are null and you get a NPE.
So how are verzekeringmaatschappijLijst and verzekeringLijst initialized?

Categories