I have two columns which are orderbyborder links. When i click one column i changed the color of column by adding attributeModifier in the following way
add(new AttributeModifier("style", true, new Model<String>("background-color:#80b6ed;")));
This works fine. But when i click on second column, the first column remains the changed color. But I expect only the column which i click should hold this attributeModifier!
You shouldn't change the modifier.
The trick is to have your model return the correct value. So instead of using new Model<String>("background-color:#80b6ed;"), which always returns the same constant value, you'd have something like:
new Model<String>() {
#Override
public String getObject() {
if( columnName.equals( selectedColumn ) { //or something along these lines, to check if the current column is the selected one
return "background-color:#80b6ed;";
}
return "background-color:white;";
}
}
And of course this also means you can add an attribute modifier to every column when you create them and don't have to worry about them later on.
Another way to achieve what you want is to add a css class to the selected line via Javascript (removing the class from old one).
Related
I am currently working on a tool which edits data dynamically in a JTable. I want to hide the targeted row whenever a button is clicked. Right now I am using RowFilter. Whenever the button isClicked, a new filter is created:
RowFilter<MyTableModel, Object> rowFilter = null;
try {
rowFilter = RowFilter.notFilter(RowFilter.regexFilter(((String)dataTable.getValueAt(dataTable.getSelectedRow(), 0)),0));
} catch (java.util.regex.PatternSyntaxException e) {
return;
}
sorter.setRowFilter(rowFilter);
This only works for one element each time the button is clicked. I want to stay them hidden, so you can continously hide elemtens in the table. It is important to mention that I do not want to delete the rows, just hide them.
I hope someone has an easy answer for this, looking for quite a while now.
This method sorter.setRowFilter(rowFilter); is replacing the filter every time you "add" a new filter. So, it's "forgetting" the old rules. What you have to do is edit the existing filter to include the new rules for filtering.
Check out the documentation for more details.
In any case, I extracted a part of the documentation which you should try to implement.
From RowFilter Javadoc:
Subclasses must override the include method to indicate whether the
entry should be shown in the view. The Entry argument can be used to
obtain the values in each of the columns in that entry. The following
example shows an include method that allows only entries containing
one or more values starting with the string "a":
RowFilter<Object,Object> startsWithAFilter = new RowFilter<Object,Object>() {
public boolean include(Entry<? extends Object, ? extends Object> entry) {
for (int i = entry.getValueCount() - 1; i >= 0; i--) {
if (entry.getStringValue(i).startsWith("a")) {
// The value starts with "a", include it
return true;
}
}
// None of the columns start with "a"; return false so that this
// entry is not shown
return false;
}
};
This means that the include() method is going to return true or false depending if an item should be shown.
Therefore, you should only set the RowFilter once, and reimplment the include() method to match all the rules you currently have set upon your view.
I have a class called "Product", with a double attribute "price". I'm showing it on a table column inside a table view, but i wanted to show the price formatted -- "US$ 20.00" instead of just "20.00".
Here's my code for populating the table view:
priceProductColumn.setCellValueFactory(cellData -> cellData.getValue().priceProperty());
I tried everything: convert the returned value to a string, using the method toString that priceProperty has, etc, but not seems to work.
Do i need to bind an event of something like that?
Use the cellValueFactory as you have it to determine the data that is displayed. The cell value factory is basically a function that takes a CellDataFeatures object and returns an ObservableValue wrapping up the value to be displayed in the table cell. You usually want to call getValue() on the CellDataFeatures object to get the value for the row, and then retrieve a property from it, exactly as you do in your posted code.
Use a cellFactory to determine how to display those data. The cellFactory is a function that takes a TableColumn (which you usually don't need) and returns a TableCell object. Typically you return a subclass of TableCell that override the updateItem() method to set the text (and sometimes the graphic) for the cell, based on the new value it is displaying. In your case you get the price as a Number, and just need to format it as you require and pass the formatted value to the cell's setText(...) method.
It's worth reading the relevant Javadocs: TableColumn.cellFactoryProperty(), and also Cell for a general discussion of cells and cell factories.
priceProductColumn.setCellValueFactory(cellData -> cellData.getValue().priceProperty());
priceProductColumn.setCellFactory(col ->
new TableCell<Product, Number>() {
#Override
public void updateItem(Number price, boolean empty) {
super.updateItem(price, empty);
if (empty) {
setText(null);
} else {
setText(String.format("US$%.2f", price.doubleValue()));
}
}
});
(I'm assuming priceProductColumn is a TableColumn<Product, Number> and Product.priceProperty() returns a DoubleProperty.)
If you have not, read this together with #James_D post.
https://docs.oracle.com/javafx/2/ui_controls/table-view.htm
I have a Table whose DataSource is set to a IndexedContainer. I also have multiple selection enabled on my Table. The Question is, how do I get all the selected values.. as an array perhaps?
My IndexedContainer:
private void populateAnalyteTable () {
Analyte[] analytes = Analyte.getAnalytes();
for (Analyte analyte : analytes) {
Object id = ic_analytes.addItem();
ic_analytes.getContainerProperty(id, "ID").setValue(analyte.getId());
ic_analytes.getContainerProperty(id, "Analyte Name").setValue(analyte.getAnalyteName());
}
// Bind indexed container to table
tbl_analytes.setContainerDataSource(ic_analytes);
}
What I'm eventually trying to get is an array of Analyte objects
Why do you want to use IndexContainer? Why don't you use BeanItemCotainer?
Please find the snippet of code below
table.setMultiSelect(true);
BeanItemContainer<Analyte> container = new BeanItemContainer<Analyte>(Analyte.class);
container.addAll(Arrays.asList(Analyte.getAnalytes()));
table.setContainerDatasource(container);
// Add some Properties of Analyte class that you want to be shown to user
table.setVisibleColumns(new Object[]{"ID","Analyte Name"});
//User selects Multiple Values, mind you this is an Unmodifiable Collection
Set<Analyte> selectedValues = (Set<Analyte>)table.getValue();
Please let me know in case it doesn't solve the issue
The vaadin objects supporting MultiSelect all return a set of the selected items.
https://www.vaadin.com/api/com/vaadin/ui/AbstractSelect.html#getValue%28%29
The drawback of this, if you need the selected items in "real" order (as displayed onscreen)
you will then have to find them from the Set to the Container
Just add your object as the Item-ID, like luuksen already propesed. Just change the initialisation of yout IndexedContainer to:
for (Analyte analyte : analytes) {
Object id = ic_analytes.addItem(analyte);
ic_analytes.getContainerProperty(id, "ID").setValue(analyte.getId());
ic_analytes.getContainerProperty(id, "Analyte Name").setValue(analyte.getAnalyteName());
}
table.getValue() is what you are looking for.
This method gives you an Object (if table is single select) or a Set<Object> (if multiselect) of the ID(s) of selected item(s). Runtime type depends on runtime id type, but if you do not need the value you can go around with Object .
If you are looking for Analytes as an array you can do
#SuppressWarnings("unchecked")
Set<Object> selectedIds = (Set<Object>) tbl_analytes.getValue();
List<Analyte> listAnalytes = new ArrayList<Analyte>();
for (Object id : selectedIds) {
listAnalytes.get(tbl_analytes.getItem(id));
}
listAnalytes.toArray();
Note that this approach works with every standard container you may use in Vaadin.
Regards!
EDIT: actually what .getValue() returns depends on the used container. In most of the cases it's the ID.
all is it possible to color a certain Row in smartGWT listGrid ?
i want to color just 1 row , not all the listGrid
In SmartGWT, methods that end with Style (e.g.- getStyle, getBaseStyle, getCellStyle, etc.) need to return a CSS class defined elsewhere (.css file, inline css in application load jsp, etc.).
Same applies for setStyle methods.
Unless lot of CSS customizations are done warranting the need for such, using getCellCSSText would probably be the best option.
getCellCSSText returns CSS text per cell, and will be called during every redraw.
final ListGrid resultsGrid = new ListGrid() {
#Override
protected String getCellCSSText(ListGridRecord record, int rowNum, int colNum) {
String style = super.getCellCSSText(record, rowNum, colNum);
// conditions can check values in record using rowNum, colNum as well as record attributes
if (record.getAttribute("<grid-field-name>").equals(<value>)) {
if (this.getFieldName(colNum).equals("<certain-grid-field-name>") && record.getAttribute("<grid-field-name>").equals(<specific-value>)) {
style = "font-weight:bold"; // only that cell in that row becomes bold
} else {
style = "color:red"; // all other cells in that row become red
}
} else if (record.getAttribute("<other-grid-field-name>").equals(<value>)) {
style = "color:green"; // entire row changed to green if one column in this row contain a specific value
}
return style;
}
};
Its not required to extend ListGridRecord as indicated in showcase sample linked above, unless there are other reasons to do so.
Never used SmartGWT, but looking at the JavaDoc, I'd say:
listGrid.getRecord(recordNum)
setCustomStyle(String customStyle)
setAttribute(String property, BaseClass value)
Also checkout this sample, that overrides the getBaseStyle() of the ListGrid.
The default behaviour in a JTable seems to be that if I reach the last row of a column and hit return, I am taken to the first row of the next column. Is there a way to avoid this? Please suggest a way that I could stay at the last row of the same column. I also want to avoid a situation where I am taken to the next column and then detect that and go back to the previous one, because I have some listeners associated with it.
Any help is appreciated.
to change any of the navigational behaviour, replace the default navigational actions with your own. Best by wrapping the defaults: conditionally either do the default or your custom stuff. Something like
Object key = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.get(KeyStroke.getKeyStroke("ENTER"));
final Action action = table.getActionMap().get(key);
Action custom = new AbstractAction("wrap") {
#Override
public void actionPerformed(ActionEvent e) {
int row = table.getSelectionModel().getLeadSelectionIndex();
if (row == table.getRowCount() - 1) {
// do custom stuff
// return if default shouldn't happen or call default after
return;
}
action.actionPerformed(e);
}
};
table.getActionMap().put(key, custom);