I will need create custom widget for search products from our database product table. I can create and use ComboBox widget but there is products table many rows so as then way do not right. I will need same ComboBox itself first only show 50 rows and after LookUp search gets some data from product tables. Give me some ideas or library made for LookUp widget!
You should use JFXAutoCompletePopup.
Here is a simple example of JFXAutoCompletePopup:
JFXTextField field = new JFXTextField();
field.setLabelFloat(true);
field.setPromptText("Type Something");
JFXAutoCompletePopup<String> autoCompletePopup = new JFXAutoCompletePopup<>();
autoCompletePopup.setSelectionHandler(event -> field.setText(event.getObject()));
autoCompletePopup.getSuggestions().addAll("Film", "Book", "Paper");
field.textProperty().addListener(observable ->{
autoCompletePopup.filter(s -> s.contains(field.getText()));
if(!autoCompletePopup.getFilteredSuggestions().isEmpty()){
autoCompletePopup.show(field);
}else{
autoCompletePopup.hide();
}
});
Regards,
Related
I am working with vaadin 8.1.0 grid. I need to insert checkbox as a column and also as column header. when I click checkbox in column header, all column checkbox should be checked. That is working fine. But the problem is if I have 100 rows, when I Check header checkbox only some column checkboxes are checked i.e, only the rows that are displayed. When I scrolldown the remaining rows checkboxes are not checked. Here is my code:
List<Person> people = new ArrayList();
for (int i = 0; i < 1000; i++) {
people.add(i, new Person("Galileo Galilei", 1564));
}
CheckBox CheckBox1 = new CheckBox("All");
CheckBox1.setValue(false);
Grid<Person> grid = new Grid<>();
grid.setItems( people);
grid.addColumn(Person::getName).setCaption("Name");
grid.addColumn(Person::getYear).setCaption("Year of birth").setId("1");
grid.addComponentColumn(Person -> {
CheckBox chk=new CheckBox("Chk 2");
CheckBox1.addValueChangeListener(e->
chk.setValue(CheckBox1.getValue())
);
return chk;
}).setCaption("ch2").setId("CH2");
grid.getHeaderRow(0).getCell("CH2").setComponent( CheckBox1);
Well, for performance reasons, not all of the checkboxes are rendered from the start, as you'll see in the GIF below (right side, items flashing in violet), just the ones currently visible. And when you scroll, new items will be replacing the old ones, and checkboxes will be drawn for them. However their initial state will be uncheked, so the simplest solution is to set its initial state to the one of the master checkbox: CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());.
Result:
Furthermore, looking at the code you might have a minor leak. Since the checkboxes are drawn each time you scroll a larger section, the code in grid.addComponentColumn will be called each time, and value change listeners will be added to the list on and on and on... because they're never unregistered. Take a look at the image below, after a few scrolls, I ended up with over 9000 of them:
To overcome this, you can un-register the listeners when the checkboxes are detached:
grid.addComponentColumn(Person -> {
CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());
// save the registration info to unregister at a later time
Registration listenerRegistration = CheckBox1.addValueChangeListener(e -> chk.setValue(CheckBox1.getValue()));
// when the checkbox is detached, remove the listener
chk.addDetachListener(event -> listenerRegistration.remove());
return chk;
}).setCaption("ch2").setId("CH2");
Now the list contains just those who were not yet detached:
You could also extend data model by a boolean field "selected" or wrap it into a new class and there add the "selected" field. Then set/unset that field in the ValueChangeListener added to the CheckBox.
This will also take care of selecting all grid entries and not just the one rendered. You will just have to change "selected" in all you data model instances.
Another approach would be to use the ImageRenderer. Then you wouldn't have to deal with any listeners.
This assumes that your model has an attribute to hold the value of checked/selected.
ThemeResource resourceChecked = new ThemeResource("selected.gif");
ThemeResource resourceUnchecked = new ThemeResource("deselected.gif");
grid.addColumn(person -> person.getSelected() ? resourceChecked : resourceUnchecked,
new ImageRenderer<>(event -> {
Person person = event.getItem();
person.setSelected(!person.getSelected());
grid.getDataProvider().refreshItem(person);
grid.markAsDirty();
}));
I want to put the data from a TableView into a Collection of Maps. Each Map represents a row in the table and contains the columnName-entry-pairs of all visible columns.
Now the tricky part for me is to get the data from the visible columns only.
On the TableView, I could call getItems(), but how could I then check which column is visible?
With getColumns(), I can check which column is visible, but how could I then get the corresponding data?
The easiest thing would be a way to iterate through all visible columns - but I can't find a way to do this.
Can anyone give me a hint or a pointer in the right direction?
You can try this, though I did not test this:
final ObservableList<Map<String, Object>> collection = FXCollections.observableArrayList();
tableView.getItems().forEach(item -> {
final Map<String, Object> itemMap = new HashMap<>();
tableView.getVisibleLeafColumns().forEach(column -> {
itemMap.put(column.getText(), column.getCellObservableValue(item).getValue());
}
collection.add(itemMap);
});
I'm learning JavaFX 8 and working on Tableview.
I know we can add data to table view by using following steps.
ObservableList<PersonCode> data =
FXCollections.observableArrayList(
new PersonCode("Jacob", "Smith"),
new PersonCode("Isabella", "Johnson"),
new PersonCode("Ethan", "Williams"),
new PersonCode("Emma", "Jones"),
new PersonCode("Michael", "Brown")
);
Then set Column cellValueFactory
TableColumn<PersonCode, String> firstName = new TableColumn<PersonCode, String>("First Name");
firstName.setCellValueFactory(new PropertyValueFactory<PersonCode, String>("aName"));
TableColumn<PersonCode, String> lastName = new TableColumn<PersonCode, String>("Last Name");
lastName.setCellValueFactory(new PropertyValueFactory<PersonCode, String>("aNameLast"));
and then table.setItems(data);
But my question is, can we add data to table's column without creating another class? As in my previous example I have created PersonCode class. But I want to add following data to tableview.
ObservableList<String> data = FXCollections.observableArrayList("Good","Luck","Bad");
As I was reading Tableview Doc there I found this line.
When you create a table in a JavaFX application, it is a best practice
to implement a class that defines the data model and provides methods
and fields to further work with the table. Example 13-3 creates the
Person class to define data in an address book.
So I'm expecting we can add data without creating a separate class. How? any idea?
These are my table columns Course and Description. If one clicks on a row (the row becomes 'active'/highlighted), and they press the Delete button it should remove that row, how do I do this?
The code for my Course column: (and what event listener do I add to my delete button?)
#SuppressWarnings("rawtypes")
TableColumn courseCol = new TableColumn("Course");
courseCol.setMinWidth(300);
courseCol.setCellValueFactory(new PropertyValueFactory<Courses, String>("firstName"));
final Button deleteButton = new Button("Delete");
deleteButton.setOnAction(.....
Just remove the selected item from the table view's items list. If you have
TableView<MyDataType> table = new TableView<>();
then you do
deleteButton.setOnAction(e -> {
MyDataType selectedItem = table.getSelectionModel().getSelectedItem();
table.getItems().remove(selectedItem);
});
If someone want to remove multiple rows at once, there is similar solution to accepted:
First we need to change SelectionMethod in our table to allow multiple selection:
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
After this, we need to set action with such code for button:
ObservableList<SomeField> selectedRows = table.getSelectionModel().getSelectedItems();
// we don't want to iterate on same collection on with we remove items
ArrayList<SomeField> rows = new ArrayList<>(selectedRows);
rows.forEach(row -> table.getItems().remove(row));
We could call removeAll method instead of remove(also without creating new collection), but such solution will remove not only selected items, but also their duplicates if they exists and were not selected. If you don't allow duplicates in table, you can simply call removeAll with selectedRows as parameter.
I have a small app that generates statistic charts from a MySQL DB via JPA. To select which DB components to include in the statistic I have installed 2 JComboBoxes. First JComboBox is populated with the elements of Category1, second JComboBox with elements from Category2, which is a subcategory of Category1. What i want to do is populate JComboBox2 only with the elements of Category2 that are linked to the selection in JComboBox1.
Example: Category1 is car brands, Category2 is models; I want JComboBox2 to show only the models for the selected brand, right now it shows every available model of every brand.
First, add a listener on the Combobox1 :
private void comboBox1ItemStateChanged(java.awt.event.ItemEvent evt) {
if (java.awt.event.ItemEvent.DESELECTED == evt.getStateChange()) {
String valueBeforeDeselection = evt.getItem().toString();
// Do something if needed
} else if (java.awt.event.ItemEvent.SELECTED == evt.getStateChange()) {
String valueAfterSelection = evt.getItem().toString();
// Set the values of the ComboBox2
}
}
In order to fill the ComboBox2, you should empty it first
comboBox2.removeAllItems();
comboBox2.addItem("Value 1");
comboBox2.addItem("Value 2");