Each row contains three cells with RGB values. I use these RGB values to set the background of another cell in the same row. On the cells that need to have the background colored I have a callback that picks up the RGB values and sets the background perfectly. So the whole TableView looks exactly as I needed. I have a color picker and this picker needs to update the selected row containing the three RGB values. I'm able to set the new three RGB values but I also need the cell with the colored background to updated itself to the new RGB values. In the code below I have found a way to do this but I believe this is rather ugly.
#FXML void handleColorPicker(ActionEvent event)
{
int r = (int) (comColorPicker.getValue().getRed()*255);
int g = (int) (comColorPicker.getValue().getGreen()*255);
int b = (int) (comColorPicker.getValue().getBlue()*255);
ComTableView.getSelectionModel().getSelectedItem().setRCom(r);
ComTableView.getSelectionModel().getSelectedItem().setGCom(g);
ComTableView.getSelectionModel().getSelectedItem().setBCom(b);
// we need to kick the cell value so it updates also the background color so we clear and rewrite the text string
String currentName = ComTableView.getSelectionModel().getSelectedItem().getCommodityName();
ComTableView.getSelectionModel().getSelectedItem().setCommodityName(" ");
ComTableView.getSelectionModel().getSelectedItem().setCommodityName(currentName);
}
The above code's last three lines trigger the cell's updateItem but I think I'm doing this in an ugly way. I'm wondering, is there a better way to do it?
There are two ways of doing this:
Use JavaFX property value extractors
Partially rewrite your data class
If you are going down route 2:
Lets assume your data class in the table is ColorData` and has the three attributes:
int RCom
int GCom
int BCom
String CommodityName
Now if you change your CommodityName from String to StringProperty and provide this to the TableView via
commodityNameColumn.setCellValueFactory(cellData -> cellData.getValue().commodityNameProperty());
Where commodityNameColumn is the TableColumn of your TableView displaying the commodityNameProperty() a new method of ColorData giving access to the new StringProperty.
Now if you change the StringProperty via its setter, and the value actually changes, the TableCell will update accordingly.
If there is still something unclear how to link a data class to the JavaFX TableView I recommend this tutorial.
Related
Is there a way to change the background color of the 3 circled table headers of a JTable?
I also want to change the font color of all the 3 circled columns to red.
An image of my table is down below. Thanks.
The way I know of is to create a TableCellRenderer that will handle the coloring of the foreground and background color.
You could create a simple coloring scheme where the color doesn't change. You often see this in tables with alternating colored rows. You could also use it for "conditional formatting". For example, highlight a cell if a value falls under a certain value. With a cell renderer, you will have better control of this.
Here is a link to Oracle's tutorial on renderers.
Lastly, since your question specifically asks to do this on specific cells, the link documentation states that
To specify a cell-specific renderer, you need to define a JTable subclass that overrides the getCellRenderer method. For example, the following code makes the first cell in the first column of the table use a custom renderer:
TableCellRenderer weirdRenderer = new WeirdRenderer();
table = new JTable(...) {
public TableCellRenderer getCellRenderer(int row, int column) {
if ((row == 0) && (column == 0)) {
return weirdRenderer;
}
// else...
return super.getCellRenderer(row, column);
}
};
I'm working on a import module from a excel file. I have to read and check this file, if something is wrong I have to color the corrisponding cell of a color. Then I implemented the following method
public void fillCell(Workbook wb, Row row, int errorColumn){
Cell cell = row.getCell(j);
CellStyle cs = wb.createCellStyle();
cs.setFillForegroundColor((short) 10);
cs.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cell.setCellStyle(cs);
}
but i noted that this method changes the data format of the cell. For example if I'm coloring a cell with data value 29/03/2014 i get the colored cell but its value now is 39536, the same thing happen with the numeric value 1534000001629, also in this case i get the colored cell but if i try to change the value from 1534000001629 to 1534000001630 i get 1,534+E12.
How can I fix it?
The problem is that cell styles don't only control the colour of a cell, they also control the formatting applied to it. So, what's happening is that you're replacing a cell style that eg formats as #.#%, and instead applying one that's eg red but has no number/date formatting rules applied to it.
Cell styles are workbook scoped, so you shouldn't create one per cell, thus you should make your logic somewhat like:
// Lookup from number format to the coloured version
Map<String,CellStyle> styles = new Hashmap<String,CellStyle>();
// Method to make the cell a different colour
public void fillCell(Workbook wb, Row row, int errorColumn){
Cell cell = row.getCell(j);
// Try to find a coloured one for this data formatting
String formatStr = cell.getCellStyle().getDataFormatString();
CellStyle cs = styles.get(formatStr);
if (cs == null) {
// Need to create a new coloured one
cs = wb.createCellStyle();
cs.setFillForegroundColor((short) 10);
cs.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cs.setDataFormat(
wb.getCreationHelper().createDataFormat().getFormat(formatStr));
// Save this for later
styles.put(formatStr, cs);
}
// Apply the coloured form, with the format string
cell.setCellStyle(cs);
}
You could either convert it to a string if you don't need to do any date processing on it later as so:
cell.setCellType(CELL_TYPE_STRING);
therwise you may be able to do it by getting the date value from the cell into Java.Util.Date object and then saving it bacl=k:
Date date=cell.getDateCellValue();
//colour change
cell.setValue(date);
I don't have time to test this right now but let me know if it works and if not I'll look more into it.
You can get more information here
I am trying to set column width to the length of the column name. My problem is, I am not able to set it. When I use the following code the table is becoming like this,
tableA.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
for(int i = 0; i < tableA.getColumnCount(); i++) {
int columnLength = (modelA.getColumnName(i)).length();
tableA.getColumnModel().getColumn(i).setPreferredWidth(columnLength);
// tableA.getColumnModel().getColumn(i).setMinWidth(columnLength);
// tableA.getColumnModel().getColumn(i).setMaxWidth(columnLength);
}
I am getting the column length correctly from my table model.
When I use the above code the table is getting packed like this,
I am not able to understand where I am doing wrong.
As Dan has pointed out, you need to calculate the actual width of the column name based on the Font that is being used.
Something like:
String name = modelA.getColumnName(i);
Font f = tableA.getFont();
FontMetrics fm = tableA.getFontMetrics(f);
int width = fm.stringWidth(name);
tableA.getColumnModel().getColumn(i).setPreferredWidth(width);
Note that this is an extremely abbreviated example.
If you want to get it completely correct, you will need to query each column's renderer for the Font and the FontMetrics in order to get the correct values.
If all your renderers use the same font as the JTable, then this should be OK.
The setPreferredWidth expects a value in pixels while the length of the column name is the length of a String (number of characters in a String).
If you do not mind using SwingX, you can use the TableColumnExt#setPrototypeValue method which allows you to set a 'prototype' value which will be used to determine the column width.
columnLength == number or columns from ColumnModel,
standard size is 80pixels
minimum columns size is at 10pixels
see How to get/set PreferredSize
I have a JTable and any single row in it has associated a different tooltip when mouse hover a row. I have created a "filter" for this table; when it is applied it perfectly hides the rows need to be hidden but when I hover the mouse on the filtered rows, looks like the tooltip is referring to the row that occupied the same row position of the new current row.
For example:
Table
ROW 1 -> tooltip 1
ROW 2 -> tooltip 2
Apply Filter to Table:
ROW 2 -> tooltip 1
So ROW 2 is displaying the tooltip 1 instead of 2.
TableRowSorter<TableModel> sorter = (TableRowSorter<TableModel>) table.getRowSorter();
sorter.setRowFilter(RowFilter.regexFilter(text));
My table that extends JTable has:
#Override
public String getToolTipText(MouseEvent e) {
final int rowIndex = rowAtPoint(e.getPoint());
TableModel model = getModel();
// take the value from the first column of the selected row
String tip = (String) getModel().getValueAt(rowIndex, 0));
return tip;
}
So it looks like using the model is not (quite obvious) updated respect to the filter. I tried using TableModel model = getRowSorter().getModel() too but without any luck.
How can I point to a correct "filtered model" to retrieve the correct row position?
UPDATE:
I have replaced the "rowIndex" code like this:
final int rowIndex = convertRowIndexToModel(rowAtPoint(e.getPoint()));
It partially solves the problem, but when some rows are added dynamically to the table with the filter applied and I hover new rows I get the exception (with relative API description):
IndexOutOfBoundsException -> if sorting is enabled and passed an index outside the range of the JTable as determined by the method getRowCount
You need to convert the views row index to the model's row index
Have a look at JTable#convertRowIndexToModel
You should not override that JTable#getToolTipText method. Just set the tooltip-text on the component returned by your renderer. The JTable will pick it up automatically. You can see this in the implementation of the getTooltipText method of the JTable
Does anyone know how to implement the up and down arrows of a JTable column header while sorting its rows?
I have made my own way of sorting and it is triggered by listening to mouse clicks by mouseadapter and the only things that is left is the visibility of such arrows on the header...
Is there also a way to easily implement a sortable jtable?
I finished doing all the sorting and one last thing that i can't do is show the sorting arrows..
i don't want to make a new one but i failed to find if there is an setEnableArrow or something..
any ideas about this?
You can take a look in the source code of the DefaultTableCellHeaderRenderer. In the getTableCellRendererComponent you see from where those icons are retrieved (e.g. UIManager.getIcon("Table.ascendingSortIcon")) and how this icon is set (setIcon(sortIcon);)
I suggest you don't mess up with the DefaultTableCellHeaderRenderer. The problem with this one, is that it's just that, the default. Each LaF is supposed to create a subclass of this one and do its own rendering there. My suggestion is to use a LaF that provides this functionality out of the box. I think that TinyLaf can do this but I'm not sure. You can subclass DefaultTableCellHeaderRenderer but you risk alienating the header rendering from the rest of the LaF.
So how to do it? Unicode to the rescue! Refer to the geometric shapes page and use what you like. I picked the '\u25B2' and '\u25BC' triangles. But then I had to hide the dreaded Swing icon:
UIManager.put( "Table.ascendingSortIcon", new EmptyIcon() );
UIManager.put( "Table.descendingSortIcon", new EmptyIcon() );
Be very careful with the above lines! They will replace the icons for all JTables in your application which might not be what you want. Then you should be able to see something like that:
Empty Icon can be like:
class EmptyIcon implements Icon, Serializable {
int width = 0;
int height = 0;
public void paintIcon(Component c, Graphics g, int x, int y) {}
public int getIconWidth() { return width; }
public int getIconHeight() { return height; }
}
This is the easiest way to implement sorting:
MyModel model = new MyModel();
TableRowSorter<MyModel> sorter = new TableRowSorter<MyModel> (model);
jTable1 = new javax.swing.JTable();
jTable1.setRowSorter(sorter);
jTable1.setModel(model);
What if you use JXtable instead of a Jtable?
these tables have the arrows in the header to sort them and they are easy to use...
worth trying...