I have an object with two essential fields that must be displayed for the user together in ComboBox something kind of:
MyObject {
Long id;
Integer from;
Integer to;
...
}
My properties look like :
MyObjectProperties {
ModelKeyProvider<MyObject> id();
LabelProvider<MyObject> from();
LabelProvider<MyObject> to();
...
}
I'm trying to display **from - to** in each combobox cell, is it possible using GXT 3 ComboBox?
That's not working for me because i can't use LabelProvider for an int and can't merge two wroperties in same field!
LabelProvider is in fact the only clean way to go, but you need only one LabelProvider:
LabelProvider<MyObject> labelProvider = new LabelProvider<MyObject>(){
#Override
public String getLabel(MyObject item){
return item.getFrom() + " - " + item.getTo();
}
}
And assign it at ComboBox creation time:
ComboBox<MyObject> cb = new ComboBox<MyObject>(store, labelProvider);
Related
I have a bill table where I want to list all products which are on the bill. I saved the ProductInBill objects within an ArrayList<ProductInBill> on the bill.
When I created a TableView my common approach is to create the JavaFX fields. On the controller class, I have my fields:
#FXML public TableColumn<ProductInBill, String> finishedBillProductNameColumn;
#FXML public TableColumn<Integer, Integer> finishedBillProductNumberColumn;
#FXML public TableColumn<ProductInBill, Integer> finishedBillProductPriceBruttoLabel;
#FXML public TableColumn<Integer, Integer> finishedBillProductTotalAmountColumn;
#FXML public TableView finishedBillProductTable;
Then I am using a setUp() method with the code like:
private void setUpFinishedBillProductTable() {
finishedBillProductNameColumn.setCellValueFactory(new PropertyValueFactory<ProductInBill, String>("productName"));
finishedBillProductPriceBruttoLabel.setCellValueFactory(new PropertyValueFactory<ProductInBill, Integer>("productPrice"));
}
Also there is an updateBillTable() method to load the necessary ProductInBill objects, save them to an TableList and give it to the table.
private void updateFinishedBillProductTable(Bill bill) {
LOG.info("Start reading all Products from Bill");
for(ProductInBill product : bill.getProducts()){
finishedBillProductCurrent.add(product);
}
finishedBillProductTable.getItems().clear();
if(!finishedBillProductCurrent.isEmpty()) {
for (ProductInBill p : finishedBillProductCurrent) {
finishedBillProductTableList.add(p);
}
//here i want to calculate some other Integer values based on the ProductInBill values and insert them to the table too.
finishedBillProductTable.setItems(finishedBillProductTableList);
}
}
This is all working very good. My problem now is, that I have also a field on my TableView with calculated Integer values which I don't want to save within an object.
Take for example the finishedBillProductNumberColumn. I want iterate on my ArrayList, find all products with the same name and populate the number of the same items to the table.
How can I do this? I found only solutions where I have to use a value from my object to insert something to my TableView.
You just have to write a custom CellValueFactory for those case instead of using premade ones. Using PropertyValueFactory is just an handy short cut to fill cells with members.
For your example:
finishedBillProductNameColumn.setCellValueFactory(new PropertyValueFactory<ProductInBill, String>("productName"));
is just a shorter way to do:
finishedBillProductNameColumn.setCellValueFactory( cellData -> {
ProductInBill productInBill = cellData.getValue();
return data == null ? null : new SimpleStringProperty(productInBill.getProductName());
});
That being said, i have an 100% preference for the second syntax. Because on the first one if you rename the member, and you forgot to change it there, you won't know there is a mistake until you get there in the application. Plus it allow to display different value than just the members.
As a concrete example for your finishedBillProductNumberColumn you could do:
First change the definition(the first Generic type is the one received with cellData.getValue():
#FXML public TableColumn<ProductInBill, Integer> finishedBillProductNumberColumn;
and then define the CellValueFactory you want like:
finishedBillProductNumberColumn.setCellValueFactory( cellData -> {
ProductInBill productInBill = cellData.getValue();
if(productionInBill != null){
Long nbProduct = finishedBillProductTable.getItems().stream().filter(product -> product.getProductName().equals(productInBill.getProductName())).count();
return new SimpleIntegerProperty(nbProduct.intValue()).asObject();
}
return null;
});
Hope it helped!
I create multiple CustomNodes with Buttons on an AnchorPane.
My Nodes are created on Button click,e.g. when I click on the Button 'task1' a new Node with a Label 'task1' and a ID will be created.
These CustomNodes have multiple tasks(e.g. task1, task2), and they will be created on different Button events.
I have a ArrayList where I store these ID's (but I store all ID's in the same List).
Can I store two items in one List index (id + function)? Like when I press on the task1 Button I want to store the id and function task1 in the same index. And when I press task2 Button, I want to store the id + task2 function right behind but in the same List.
And another point of my question is can I get the order of ID's? I connect my Nodes via CubicCurves, in this Link class I have my function:
public void bindEnds (DragNode source, DragNode target) {
//Code above
source.registerLink (getId());
target.registerLink (getId());
}
public void registerLink(String linkId) {
mLinkIds.add(linkId);
}
Where I register my source and target CustomNodes.
On my Nodes are two Circles (on the left and right). The left Circle is supposed to be the input, the right output. I want to check if my left/right Circle is connected . If the left is not connected but the right, it should be the first Item in my list. If both are connected, I need the order and store it.
Just create a class that will store id and task like this :
public class Stocker {
private Task task;
private int id;
public Stocker(Task task, int id) {
this.task = task;
this.id = id;
}
public Task getTask() {
return task;
}
public int getId() {
return id;
}
}
and then change your list like this :
List<Stocker> stockers = new ArrayList<Stocker>();
you can now create a stocker with :
Stocker stocker = new Stocker(task,id);
store it with :
stockers.add(stocker);
and access your values using :
stockers.get(index).getId();
//or
stockers.get(index).getTask();
The library http://www.javaslang.io/ has already defined the type Touple, that is exactly what you want, but if you do not want to add a new library, just build the object yourself. A simple pojo with two attributes (id and function) should do the trick.
just a question about Vaadin's Table component. I have a table created with a TableFieldFactory, and I have noticed that if I count the number of times the TableFieldFactory is called for a Table with e.g. 8 rows and 4 columns, I get 40 as the result (instead of the expected 8 * 4 = 32).
So does Vaadin uses an hidden extra column when creating the table? Does this column contain the itemId given to the Table.addItem() method? Anyway here is the code I used for the field factory:
// UI's static field
public static int counter = 1;
// ... UI's init() method
tbl.setTableFieldFactory(new TableFieldFactory() {
#Override
public Field<?> createField(Container container, Object itemId,
Object propertyId, Component uiContext) {
TextField field = new TextField((String) propertyId);
counter++;
// User can only edit the "Numeric field"
if ("Numeric field".equals(propertyId)) {
field.setData(itemId);
// Remeber the field
valueFields.put((Integer) itemId, field);
// Focus if it is the first editable value
if ((Integer) itemId == 0) {
field.focus();
}
}
else {
field.setReadOnly(true);
}
return field;
}
});
// here counter is 40 for a 8x4 table
I guess the reason is the lazy loading of the vaadin table. I experienced that on the first load the table is initialized with one row (for better response to the user I suppose), after this it is re-initialized with the lazy-loading amount (in your case the whole table) this would explain the extra 8 calls.
Is there a way to have the DropDownChoice in Wicket assign tooltips (e.g. title attributes) to individual option elements?
I have selectbox items in the following form:
public class SelectBoxItem
{
private Long id;
private String label;
private String description;
}
All items are loaded from the database.
I configure the DropDownChoice component using a ChoiceRenderer to use the ids as keys and the labels as values.
Now I would need to configure it to use the descriptions as tooltip messages as well.
I have only found this related thread on the Internet. Browsing the relevant Wicket classes let me to the same conclusions as the author, e.g. that this was probably not possible with the current versions of the DropDownChoice/ChoiceRenderer classes. Is that right? And in that case, is there a similar component which would allow that?
(For a more comprehensive description of my code base see my other question where I asked about a different problem within the same context.)
Here is my solution for this problem. Many thanks to Andrea Del Bene for the advice.
public class TitledDropDownChoice<T> extends DropDownChoice<T> {
// ... constructors from superclass ...
#Override
protected void appendOptionHtml(AppendingStringBuffer buffer,
T choice, int index, String selected) {
super.appendOptionHtml(buffer, choice, index, selected);
// converts <option value="foo">bar</option> to
// <option value="foo" title="bar">bar</option>
String replString = "value=\"" + getChoiceRenderer()
.getIdValue(choice, index) + "\"";
int pos = buffer.indexOf(replString);
buffer.insert(pos + replString.length(),
" title=\"" + getChoiceRenderer().getDisplayValue(choice) + "\"");
}
}
Have you tried overriding method appendOptionHtml? You could use it to append the desired html (i.e. title="toolTipText").
I have a JComboBox filled with some random items, that can change at run time. I have set them as JLabels using getListCellRendererComponent(...). I have also set some of those Jlabels as setEnabled( false ).
When user selects an item from that JComboBox, is there a way i can detect if it is enabled or disabled ?
The renederer just paints them so there will not be an isEnabled value to check. Instead use the same logic that the cellRenderer uses to determine if a value is allowed, when you are looking at the selection. Or possibly remove those values from the list instead of making the disabled.
The items in the list/combo (or any of the collections components) are supposed to be representations of business objects with some state. Then implement renderers which are aware of the different state and make them (the renderer) map the state into appropriate visual representation.
// the item
public class Valve {
private boolean open;
private boolean canOperate;
private Point location;
// getters and methods as appropriate
public boolean isOpen() { ...
...
}
// custom renderer
Component getListCellRendererComponent(....) {
// normal config, assuming you subclass DefaultListCellRender
super.getListCellRendererComponent(...)
if (value instanceof Valve) {
configFromValve((Valve) value)
}
return this;
}
private void configFromValve(Valve valve) {
setText("P: (" + valve.location().x + "," + valve.getLocation().y + ")");
setIcon(valve.isOpen() ? openIcon : closedIcon);
setEnabled(valve.canOperate());
}