Selected row in JTable is not highlighting - java

Well, this is my first post here. But I am little frustrated because I have search everywhere but nothing is working. I have JTable and code works as expected below lines right after if (value.equals("CMAU1294522")) .. however only one cell is show square box. I mouse clicked on a particular row, I want the entire row to show light gray (I think that is standard).
table = new JTable(sorter) {
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
Component comp = super.prepareRenderer(renderer, row, col);
Object value = getModel().getValueAt(row, col);
UIManager.put("Table.editRow", new javax.swing.plaf.ColorUIResource(Color.YELLOW));
if(editingRow ==1){
table.setSelectionBackground(Color.red);
}
if (getSelectedRow() == row) {
table.setSelectionBackground(Color.red);
}
if (value.equals("CMAU1294522")) {
comp.setBackground(Color.red);
} else if (value.equals("PNCT")) {
comp.setBackground(Color.green);
} else if (NewJApplet.contReady.containsKey(value)) {
comp.setBackground(Color.CYAN);
} else if (NewJApplet.badCont.containsKey(value)) {
comp.setBackground(Color.red);
} else {
comp.setBackground(Color.white);
}
return comp;
}
Is there any way to do it in prepareRenderer function I already have?

I there any way to do it in PreparRenerere function I already have?
You code to get the "value" is wrong. You always get the value of the current cell being rendered. If you want to highlight the entire row based on a specific value then you need to hardcode the column:
Object value = getModel().getValueAt(row, ???);
Also, it looks like you are sorting the data in the table so you should be using getValueAt(...) instead of getModel().getValueAt(), so you check the data in the sort table, not the data in the unsorted model.
Check out the example code in Table Row Rendering for a working example.

Related

Add JButton only to a specific JTable cell (or more)

I wanna add a button to some specific cells where i might get null characters from my database. I tried overriding 'TableCellRenderer' . But it keep adding buttons to entire column. What should i do? (example wd b better)
But it keep adding buttons to entire column.
Yes, a renderer is designed to work for the entire column.
If you want a different renderer for a different row then you can override the getCellRenderer(...) method. Something like:
public TableCellEditor getCellEditor(int row, int column)
{
Object value = getValueAt(row, column);
if (value == null)
{
return super.getCellEditor(row, column);
}
else
return getDefaultRenderer(value.getClass());
}
You would also need similar code for the getCellEditor(...) method.
You can also check out Table Button Column for an example of a button renderer/editor.

JTable cell updating issue

I got a problem I can't resolve alone and with help of other topics there. Found some 1 pretty similar but it hasn't help.
My problem is kind of tricky ones I think, I'll try to explain this as good as I can.
So, I got a JTable with couple of columns, column 2 and 3 are editable and column 4 is a product of these two (col4 = col2*col3). What I am going to do is when I edit column 2 or 3, column 4 will automaticly update it's value. I acomplished that but not fully.
The cell is updating only when I finish editing by mouseclick. I'd like to cell react with same way if editing is finished by ENTER key.
I was trying a little bit with:
if(recipeTable.getCellEditor()!=null)recipeTable.getCellEditor().stopCellEditing();
but it isn't changing anything.
Here is my code:
recipeTableModel = new DefaultTableModel(COLUMN_HEADLINE, 0) {
#Override
public boolean isCellEditable(int row, int column)
{
model.updateTotalPriceInTable(recipeTable);
return (column == 2) || (column == 3);
}
};
And:
public void updateTotalPriceInTable(JTable table)
{
double totalPrice;
DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
for(int i = 0; i < tableModel.getRowCount(); i++)
{
totalPrice = Double.parseDouble(tableModel.getValueAt(i, 2).toString()) * Double.parseDouble(tableModel.getValueAt(i, 3).toString());
tableModel.setValueAt(totalPrice, i, 4);
}
tableModel.fireTableDataChanged();
}
~~~~~~~~~~~~~~~~~~~~~~~~
Ok I figured it out, that is code the code that resolved my problem:
#Override
public void setValueAt(Object aValue, int row, int column)
{
Vector rowVector = (Vector)dataVector.elementAt(row);
rowVector.setElementAt(aValue, column);
rowVector.setElementAt(Double.parseDouble((String) rowVector.get(2))*Double.parseDouble((String) rowVector.get(3)), 4);
fireTableDataChanged();
}
Override the setValueAt(...) method of your TableModel. You invoke super.setValueAt(...) to save the data normally.
Then whenever the data in column 2 or 3 changes, you then calculate the value of column 4 and update the model.

JTable Clickable Column Sorting: Sorting sorts content of cells, but doesn't update cell formatting?

I have a sortable JTable set up to use a custom extension of the AbstractTableModel. However, some behavior of this table is what I expected, and I would love some advice on how to figure this out.
I have the JTable set up to be sortable using:
thisJTable.setAutoCreateRowSorter(true);
This allows me to sort the table by clicking on the column headers as expected.
However, I find that when I sort the table by clicking on the column headers, the formatting (background and foreground color) of my rows are not sorted as well.
I had set up those rows to be color-coded based on the values they contain. When I sort by column header the formatting at a given row NUMBER stays the same (although the content that was previously in that row moved).
The color of the row is set by overriding the default prepareRenderer call for the JTable:
thisTable = new JTable(thisModel){
//Set up custom rendering - Sets background color of row to correct value
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
CustTableModel thisModel = (CustTableModel) getModel();
c.setBackground(thisModel.getRowBackgroundColor(row));
c.setForeground(thisModel.getRowForeColor(row));
return c;
}
};
Is there a better/different way to approach this?
Should I be using a different method to do my rendering, a method which would update the rendering of the JTable on a sort?
Or do I want to look into writing my own sorting method?
Solution (Thanks mKorbel!)
I thought I would post my solution, since I had to play with this a bit since I wasn't sure if the new index would be passed to the prepareRenderer as well.
thisTable = new JTable(thisModel){
//Set up custom rendering - Sets background color of row to correct value
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
int viewIdx = row;
int modelIdx = convertRowIndexToModel(viewIdx);
Component c = super.prepareRenderer(renderer, row, column);
CustTableModel thisModel = (CustTableModel) getModel();
c.setBackground(thisModel.getRowBackgroundColor(modelIdx));
c.setForeground(thisModel.getRowForeColor(modelIdx));
return c;
}
};
you have to convert row index from View to the Model
int modelRow = convertRowIndexToModel(row);
You can enable table sorting by clicking on header using this
table.setAutoCreateRowSorter(true);
for more information visit this site http://www.codejava.net/java-se/swing/6-techniques-for-sorting-jtable-you-should-know

How to add tooltips to JTable's rows

how can I add tooltips to JTable's rows (Java Swing)?
These tooltips should contain same values of the relative row.
This is the code I used in my class that extends JTable. It overrides the method "prepareRenderer", but I got empty cells, and it adds a tooltip for each single cell within row, not one tooltip for the whole row (that is what I'm looking for):
public Component prepareRenderer(TableCellRenderer renderer,int row, int col) {
Component comp = super.prepareRenderer(renderer, row, col);
JComponent jcomp = (JComponent)comp;
if (comp == jcomp) {
jcomp.setToolTipText((String)getValueAt(row, col));
}
return comp;
}
it adds a tooltip for each single cell within row, not one tooltip for the whole row
You are changing the tooltip depending on the row and column. If you only want the tooltip to change by row, then I would only check the row value and forget about the column value.
Another way to set the tooltip is to override the getToolTipText(MouseEvent) method of JTable. Then you can use the rowAtPoint(...) method of the table to get the row and then return the appropriate tool tip for the row.
Just use below code while creation of JTable object.
JTable auditTable = new JTable(){
//Implement table cell tool tips.
public String getToolTipText(MouseEvent e) {
String tip = null;
java.awt.Point p = e.getPoint();
int rowIndex = rowAtPoint(p);
int colIndex = columnAtPoint(p);
try {
//comment row, exclude heading
if(rowIndex != 0){
tip = getValueAt(rowIndex, colIndex).toString();
}
} catch (RuntimeException e1) {
//catch null pointer exception if mouse is over an empty line
}
return tip;
}
};
see JComponent.setToolTipText() -- the JComponent you want on per-row data is not the table, but rather the cell renderer of the data, which has access to configuring a JComponent for each rendered cell.
rowIndex can be ZERO.
change:
if(rowIndex != 0){
tip = getValueAt(rowIndex, colIndex).toString();
}
by:
if(rowIndex >= 0){
tip = getValueAt(rowIndex, colIndex).toString();
}

JTable with multi-line cell renderer prints very weird

I have a JTable with a custom Cell Renderer for multi-line cells. Everything is ok, the JTable is painted ok in the screen and I am very happy with it, but ast night when I tried to simply print it, I came up with a very strange issue. Using:
table.print(PrintMode.FIT_WIDTH, new MessageFormat("..."), new MessageFormat("..."));
I saw that the table did not print entirely. Then using another class made from a colleague for printing JTables I had the same result:
The table (with multi-line cells) needed 22 pages to print. The printed document (which I only viewed in xps format since I do not own a printer) had also 22 pages. But up to page 16 everything was printed as expected and after that only the borders and the column headers of the table were printed.
Strangely (to me) enough, when I tried to print the table using another cell renderer that does not allow for multi line cells, the table needed exactly 16 pages and was printed entirely, albeit the cropping in the lengthy cell values.
I searched all over the net but I had no luck. Does anybody know why could this be happening? Is there a solution?
Update:
My cell renderer is the following:
public class MultiLineTableCellRenderer extends JTextPane implements TableCellRenderer {
private List<List<Integer>> rowColHeight = new ArrayList<List<Integer>>();
public MultiLineTableCellRenderer() {
setOpaque(true);
}
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
String s = (String)value;
if (s.equals("<περιοδάριθμος>")) {
setForeground(Color.blue);
}
else if(s.equals("<παραγραφάριθμος>")) {
setForeground(Color.red);
}
else {
setForeground(Color.black);
}
setBackground(new Color(224, 255, 255));
if (isSelected) {
setBackground(Color.GREEN);
}
setFont(table.getFont());
setFont(new Font("Tahoma", Font.PLAIN, 10));
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
setForeground(UIManager.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
setBorder(new EmptyBorder(1, 2, 1, 2));
}
if (value != null) {
setText(value.toString());
} else {
setText("");
}
adjustRowHeight(table, row, column);
SimpleAttributeSet bSet = new SimpleAttributeSet();
StyleConstants.setAlignment(bSet, StyleConstants.ALIGN_CENTER);
StyleConstants.setFontFamily(bSet, "Tahoma");
StyleConstants.setFontSize(bSet, 11);
StyledDocument doc = getStyledDocument();
doc.setParagraphAttributes(0, 100, bSet, true);
return this;
}
private void adjustRowHeight(JTable table, int row, int column) {
int cWidth = table.getTableHeader().getColumnModel().getColumn(column).getWidth();
setSize(new Dimension(cWidth, 1000));
int prefH = getPreferredSize().height;
while (rowColHeight.size() <= row) {
rowColHeight.add(new ArrayList<Integer>(column));
}
List<Integer> colHeights = rowColHeight.get(row);
while (colHeights.size() <= column) {
colHeights.add(0);
}
colHeights.set(column, prefH);
int maxH = prefH;
for (Integer colHeight : colHeights) {
if (colHeight > maxH) {
maxH = colHeight;
}
}
if (table.getRowHeight(row) != maxH) {
table.setRowHeight(row, maxH);
}
}
}
Furthermore, if you test the following very simple example you will notice that something is terribly wrong with the printing, but I really can't find what!
public static void main(String[] args) throws PrinterException {
DefaultTableModel model = new DefaultTableModel();
model.addColumn("col1");
model.addColumn("col2");
model.addColumn("col3");
int i = 0;
for (i = 1; i <= 400; i++) {
String a = "" + i;
model.addRow(new Object[]{a, "2", "3"});
}
JTable tab = new JTable(model);
tab.print();
}
I believe you are having the same problem that I had when I asked this question:
Truncated JTable print output
I found a solution to my problem, and I believe it may help you as well.
The answer is here:
Truncated JTable print output
To summarize my answer:
If your TableCellRenderer is the only place in your code where you are setting rows to their correct height, then you are going to run into trouble caused by an optimization inside JTable: JTable only invokes TableCellRenderers for cells that have been (or are about to be) displayed.
If not all of your cells have been displayed on-screen, then not all of your renderers have been invoked, and so not all of your rows have been set to the desired height. With your rows not being their correct height, your JTable overall height is incorrect. After all, part of determining the overall JTable height is accounting for the height of each of that table's rows. If the JTable overall height isn't correct, this causes the print to truncate, since the JTable overall height is a parameter that is considered in the print layout logic.
An easy (but perhaps not squeaky clean) way to fix this is to visit all of your cell renderers manually before printing. See my linked answer for an example of doing this. I actually chose to do the renderer visitation immediately after populating my table with data, because this fixes some buggy behavior with the JTable's scrollbar extents (in addition to fixing the printing.)
The reason the table looks and works OK on-screen even when printing is broken, is because as you scroll around in the table, the various renderers are invoked as new cells come on screen, and the renderers set the appropriate row height for the newly visible rows, and various dimensions are then are recalculated on the fly, and everything works out OK in the end as you interact with the table. (Although you may notice that the scrollbar "extent" changes as you scroll around, which it really shouldn't normally do.)
Strange thing is that behavior is not deterministic.
Such behavior always makes me suspect incorrect synchronization.
It's not clear how your TableCellRenderer works, but you might try HTML, which is supported in many Swing components.
Another useful exercise is to prepare an sscce that reproduces the problem in minature. A small, complete example might expose the problem. It would also allow others to test your approach on different platforms.
This answer is probably too late for the one who asked this question, but for everybody with a similar problem, here is my solution;
I had exactly the same problem, I have my own TableCellRenderer to handle multi-line Strings which works flawless for showing the table but makes the printing of the table unreliable.
My solutions consists of 2 parts;
Part 1: I have created my own TableModel, in the getValueAt() I 'copied' a part of the StringCellRenderer logic, I make it recalculate and set the height of the table row in case af a multi-line String AND return the String as HTML with 'breaks' instead of line-separators.
Part 2: Before invoking the table.print() I call the getValueAt() for all cells (a for-loop over the columns with an inner for loop over the rows invoking the getValueAt()), this has to be done 'manually' because the print functionality doesn't invoke all getValueAt's (I have found reasons on different fora regarding this issue regarding the execution of the TableCellRenderers).
This way the clipping of the table is done like it is supposed to, only complete rows are printed per page and it devides the rows over severall pages if required with a table header at each page.

Categories

Resources