I have created a table using ObservableMap instead of ObservableList. You can see the code (not written by me) here. Now I need to add context menu to every row. So I wrote the code as below:
public MapTableView<String, LineItem> initialize(MapTableView<String, LineItem> tableView) {
tableView.setRowFactory((TableView<Entry<String, LineItem>> tableView1) -> {
final TableRow<Entry<String, LineItem>> row = new TableRow<>();
final ContextMenu contextMenu = new ContextMenu();
final MenuItem cancelMenuItem = new MenuItem("Cancel");
cancelMenuItem.setOnAction((ActionEvent event) -> {
LineItem item = tableView1.getSelectionModel().getSelectedItem().getValue();
System.out.println(item.getLineNo()); // gives me null
});
});
contextMenu.getItems().add(cancelMenuItem);
// Set context menu on row, but use a binding to make it only show for non-empty rows:
row.contextMenuProperty().bind(Bindings.when(row.emptyProperty()).then((ContextMenu) null)
.otherwise(contextMenu)
); tableView1.setContextMenu(contextMenu);
return row;
});
return tableView;
}
Actually it is retrieving the order from the table but when I am accessing the variables of the object it is giving me "null". I couldn't find out what wrong I am doing. Please help me with this. More-over I am initializing the table with:
tableView.setEditable(false);
tableView.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
Should I have to use anything like:
tableView.getSelectionModel().setCellSelectionEnabled(true);
Everything is working fine, but when I am trying to access the variables of the "item" I am getting the "Null Pointer Exception" as the values are null, but the object is not null. Thanks in advance.
As #James_D said, using
LineItem item = row.getItem().getValue() solved the issue.
Related
I'm writing a seating chart program using JavaFX. I have a table that keeps a list of students together that holds their name, grade, and whether they are present or absent (using a checkbox). I have a delete button that allows me to delete the students from the list. This works fine, however, whenever I delete the student object, the checkbox does not go along with it. I'm not sure what I would need to add to get that to work. Here is a snippet of the delete code. There are also two images below that show my problem. This is my first post so please let me know if I missed something. Please help! Thanks!
ObservableList<Student> items, sel;
items = currentTable.getItems();
sel = currentTable.getSelectionModel().getSelectedItems();
Student s = new Student("", "", 0, "");
for (Student p : sel) {
items.remove(p);
s = p;
}
Before Delete
After Delete
This has nothing to do with the delete or remove method. It has to do with what you did in TableColumn.setCellFactory().
To get the checkbox you shown, you should have used (in general) one of the two methods:
Overriding updateItem() in TableCell while setting Cell Factory
There is this empty parameter in updateItem() which indicates whether the row is empty or not. You need to use that to determine when not to show the checkbox.
column.setCellFactory(col -> {
return new TableCell<Foo, Boolean>() {
final CheckBox checkBox = new CheckBox();
#Override
public void updateItem(final Boolean selected, final boolean empty) {
super.updateItem(selected, empty);
if (!this.isEmpty()) {
setGraphic(checkBox);
setText("");
}
else {
setGraphic(null); // Remove checkbox if row is empty
setText("");
}
}
}
}
Using CheckBoxTableCell
JavaFX API has this convenient class CheckBoxTableCell that would do all these for you. Most people find this class hard to use because there are 2 things that you need to ensure to use it correctly:
The TableView that the column belongs to must be editable.
The TableColumn itself must be editable.
Example:
tableView.setEditable(true);
tableColumnSelected.setCellFactory(CheckBoxTableCell.forTableColumn(tableColumnSelected));
tableColumnSelected.setEditable(true);
As for whether which entry you want to be removed with the delete button, you just need to remove the correct items from the TableView.
I'm noob in javafx and scene builder. I want to populate tableview by selecting one item from combobox. It is possible?
i try with String val = combobox.getValue() and i put the string in SQL query in preparedStatement for directly sort but app stops at the null string value and tableview is not updated.
Thank you guys!
It is possible that the String is being initialized with the ComboBox value even before the ComboBox gets an input. In that case, the ComboBox will return a null value.
You should add an onAction event for the ComboBox which will update the string.
You can use the following code segment to do that
comboBox.setOnAction((event) -> {
val = comboBox.getValue();
//Any other action you want to carry out when an item of the combo box is selected
});
Or if you are using an FXML file and want to add the onAction event in the controller, you can use this.
public void comboBoxEvent(ActionEvent event){
val = comboBox.getValue();
} // Use this code when working with FXML files
Both these examples assume that the String var was defined globally. Just to be on the safer side, when you are comparing var to another value or storing it somewhere else, you should put it under an if condition
if(var != null)
//Code segment here
I am using this link for creating a ContextMenu for each table row. Right now I'm running into problems because I'm not sure how to attach a ContextMenu after the 'type' has been inserted into a row.
Lets say I'm using a .zip editor program, and it lists the contents. I have an Image, and a text file, and some other stuff, all of them are under a class called Entry. My table's generic type is 'Entry', and I'd like to be able to create a context menu for each entry based on it's underlying subclass type (like an ImageEntry might return a menu item to open it up in an image editor...etc).
Right now I have a generic context menu for everything, but it's not great displaying a menu item about opening a text file with an image editor...
Is this possible to do? If so, what is the proper way to go about doing it?
Add a listener to the row's itemProperty (which represents the item displayed in the row) and update the context menu when it changes:
table.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {
#Override
public TableRow<Person> call(TableView<Person> tableView) {
final TableRow<Person> row = new TableRow<>();
final ContextMenu contextMenu = new ContextMenu();
row.itemProperty().addListener((obs, oldPerson, newPerson) -> {
contextMenu.getItems().clear();
// add items to context menu depending on value of newPerson
// ...
});
// Set context menu on row, but use a binding to make it only show for non-empty rows:
row.contextMenuProperty().bind(
Bindings.when(row.emptyProperty())
.then((ContextMenu)null)
.otherwise(contextMenu)
);
return row ;
}
});
This is my zul code:
<combobox id="digitalPublisherCombobox" value="#load(ivm.inventory.digitalPublisherName)"
onOK="#command('setDigitalPublisher', digitalPublisherBox = self)"
onSelect="#command('setDigitalPublisher', digitalPublisherBox = self)"
onChanging="#command('setupQuicksearchByEvent', searchlayout = event, prefix = 'PUB', tags = 'PublisherName, PublisherNameTranslit')"
mold="rounded" hflex="1" buttonVisible="false" autodrop="true">
<comboitem self="#{each=entry}" value="#{entry.key}" label="#{entry.value}"/>
</combobox>
And this is QuickSearch implementations:
#Command
public void setupQuicksearchByEvent(#BindingParam("searchlayout")Event event, #BindingParam("prefix") String prefix, #BindingParam("tags") String tags) throws WrongValueException, SearchException, IOException
{
if(event instanceof InputEvent)
{
InputEvent inputEvent = (InputEvent) event;
String inputText = inputEvent.getValue();
List<String> searchFields = Arrays.asList(tags.split(","));
ListModel model = new ListModelMap(ZKLogic.findDocsStartingWith(prefix, searchFields, "proxy", inputText), true);
ListModel subModel = ListModels.toListSubModel(model, Autocompleter.MAP_VALUE_CONTAINS_COMPARATOR, 10);
Combobox searchBox = (Combobox) event.getTarget();
searchBox.setModel(subModel);
searchBox.setItemRenderer(new ComboitemRenderer()
{
#Override
public void render( Comboitem item, Object data, int pos ) throws Exception
{
String publisherString = data.toString();
UID key = getUidFromPublisherString(publisherString);
int startIndex = publisherString.indexOf('=') + 1;
String publisher = publisherString.substring(startIndex);
item.setLabel(publisher);
item.setValue(key);
}
});
}
}
ZKLogic.findDocsStartingWith return map with UID-key and String-value.
With code above I achieved to get dropdown list when I switch to another window. I need to type something, then select another browser or notepad window - and comboitems will be displayed immediately.
So, my question still need answer, is there are any techniques to reproduce this windows switching in code? Or maybe I should do something with autocomplete, because I've got some ac working with preloaded lists, but this thing should return only 10 records from db, instead of all 70000 entries, every time when user type something in the field.
Edit 20/09/2013: Problem still exist. Rename question a bit, because thing that I need is to call render option by force in code. Is there is any way to do it? Code hasn't changed a lot, but print option in render method said, that method can miss two or more onChange events and suddenly render text for one variant.
Maybe you know another autocomplete options in zk framework where database participating? I'm ready to change implementation, if there is a guide with working implementation of it.
Ok I see two problems, you should solve first.
Setting the Renderer in every call of setupQuicksearchByEvent(...).
that is not logical, cos it is the same every time.
Add to the zul combobox tag something like
itemRenderer="#load(ivm.myRenderer)" ....
If you want just 10 items, do not let the db-request return more then 10.
If you use JPA klick here or for sql here or just google a bit.
After you fixed this two issues, we can exclude these as a reason of the unexpected behavior and fix it, if it is still present.
Edit
Ok, I have two possible ways to fix it.
Call Combobox#invalidate()
This schould force zk to rerender the Combobox, but could
lead to low performance and I would not prefer this.
Use Listbox with the select mold instead of Combobox.
To force the rerender, use Listbox#renderAll()
Try setting the selected item on your combobox or throw its related event
Solution is simple. Really. Nothing is better then brute-force, but I think I tried to avoid it and use it in despair.
#Command
public void setupQuicksearchByEvent(#BindingParam("searchlayout")Event event, #BindingParam("prefix") String prefix, #BindingParam("tags") String tags) throws WrongValueException, SearchException, IOException
{
if(event instanceof InputEvent)
{
InputEvent inputEvent = (InputEvent) event;
String inputText = inputEvent.getValue();
List<String> searchFields = Arrays.asList(tags.split(","));
Map<UID, String> publishers = ZKLogic.findDocsStartingWith(prefix, searchFields, "proxy", inputText);
Combobox searchBox = (Combobox) event.getTarget();
searchBox.getChildren().clear();
for (Map.Entry<UID, String > entry : publishers.entrySet())
{
Comboitem item = new Comboitem();
item.setLabel(entry.getValue());
item.setValue(entry.getKey());
searchBox.appendChild(item);
}
}
}
Im trying to create a scrollPanel that holds a list of checkbox item. My main problem is constructing a CellList with CheckboxCell. Here is a snippet of whats causing the compile time error.
CheckboxCell testCheckBox = new CheckboxCell();
CellList<String> cellList = new CellList<String>(testCheckBox);
Error Message: The constructor CellList(CheckboxCell) is undefined.
If this is the wrong constructor, what is the correct way?
Try changing the type of CellList to Boolean.
CheckboxCell testCheckBox = new CheckboxCell();
CellList<Boolean> cellList = new CellList<Boolean>(testCheckBox);
update:
More examples on various cells (this is combined checkbox + picture, but you might want to replace picture with text):
http://gwt.google.com/samples/Showcase/Showcase.html#!CwCellTree
It's little trickier, but this showcase contains also sources so might want to dive into them.
PS: Lazier solution is not to use Cell Widgets and make own (extends Composite) combo/label and place it in say FlexTable :)
You can try something like that. You are going to need some extra native code to handle the "check" event.
public class StyleCell extends AbstractCell<Style> {
#Override
public void render(Context context, Style row, SafeHtmlBuilder sb) {
if (row == null) {
return;
}
sb.appendHtmlConstant("<INPUT TYPE=CHECKBOX NAME='property'>" + row.getProperty() + "</INPUT>");
}
}
StyleCell styleCell = new StyleCell();
CellList<Style> styleList = new CellList<Style>(styleCell);