so i want my JTable to render everytime a value in a variable is changed however this is not taking place, the table is only getting rendered either when I click on it, or move it out of view then back in. Any suggestions? I am using a custom TableCellRender as posted below.
import java.awt.Color; import java.awt.Component; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.table.TableCellRenderer; public class myRenderer extends JLabel implements TableCellRenderer { private static final long serialVersionUID = 1L; public myRenderer() { super.setOpaque(true); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setHorizontalAlignment(SwingConstants.CENTER); setText(value.toString()); Color myColor = new Color(255, 253, 117); setBackground(myColor); if(value == Integer.valueOf(-1)) { value = null; setText(""); return this; } for(int i = 0; i < 90; i++) { if(value == Integer.valueOf(finalClass.done[i])) //this value changes during the program. { setBackground(Color.cyan); } } return this; } }
I want my table to render everytime that the value in finalClass.done
is changed in any other part of the program. any ideas? i tried the revalidate option, but got no results.
EDIT: Here is a minimal version of finalClass, which when run together with the above mentioned renderer code, can reproduce the same error I’m facing.
import javax.swing.JFrame; import javax.swing.JTable; import javax.swing.table.DefaultTableModel; public class finalClass { JFrame frame = new JFrame(); static int[] done = new int[90]; Integer[][] slip = new Integer[9][5]; String colHeader[] = {"1","2","3","4","5"}; JTable table; finalClass() { for(int i = 0; i<90; i++) done[i] = -1; int cnt = 0; for(int x = 0; x<9; x++ ) { for(int y = 0; y <5; y++) { slip[x][y] = cnt++; } } DefaultTableModel tableModel = new DefaultTableModel(slip, colHeader) { private static final long serialVersionUID = 1L; @Override public boolean isCellEditable(int row, int column) { //all cells false return false; } }; table = new JTable(slip, colHeader); table.setDefaultRenderer(Object.class, new myRenderer()); table.setModel(tableModel); frame.add(table); frame.setVisible(true); frame.pack(); } public static void main(String[] args) { new finalClass(); try { Thread.sleep(5000); done[5] = 10; } catch(Exception e) { e.printStackTrace(); } } }
Thank you all in advance for bearing with me. I’m new here so it might take a little time for me to understand how things are done around here. sorry to waste your time and thanks for the help in advance.
Advertisement
Answer
The reason why the value shows only after you move the table or click on it, is that by doing so you force a repaint.
You can verify it by invoking frame.repaint()
after done[5] = 10;
The following is a one-file MRE (copy paste the entire code into FinalClass.java
and run):
import java.awt.Color; import java.awt.Component; import java.util.Arrays; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; public class FinalClass { private final JFrame frame = new JFrame(); private final int[] done = new int[90]; //better avoid static private final Integer[][] slip = new Integer[9][5]; private final String colHeader[] = {"1","2","3","4","5"}; private JTable table; FinalClass() { Arrays.fill(done, -1); int cnt = 0; for(int x = 0; x<9; x++ ) { for(int y = 0; y <5; y++) { slip[x][y] = cnt++; } } DefaultTableModel tableModel = new DefaultTableModel(slip, colHeader) { private static final long serialVersionUID = 1L; @Override public boolean isCellEditable(int row, int column) { //all cells false return false; } }; table = new JTable(slip, colHeader); table.setDefaultRenderer(Object.class, new MyRenderer()); table.setModel(tableModel); frame.add(table); frame.pack(); frame.setVisible(true); } private void refresh(){ frame.repaint(); } void done(int index, int value){ done[index] = value; refresh(); } public static void main(String[] args) { FinalClass f = new FinalClass(); try { Thread.sleep(3000); f.done(5, 10); } catch(Exception e) { e.printStackTrace(); } } //follow java naming conventions class MyRenderer extends JLabel implements TableCellRenderer { private static final long serialVersionUID = 1L; public MyRenderer() { super.setOpaque(true); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setHorizontalAlignment(SwingConstants.CENTER); setText(value.toString()); Color myColor = new Color(255, 253, 117); setBackground(myColor); if((int)value == -1) { value = null; setText(""); return this; } for(int i = 0; i < 90; i++) { if((int)value == done[i]) //this value changes during the program. { setBackground(Color.cyan); } } return this; } } }
Side notes:
1. If you want the table to respond automatically to change in the undelying data, you need to apply the change to its model as demonstrated in this answer to your previous question.
2.Modifying done
from more than one thread needs to be synchronized.
3.It is recommended to follow Java Naming Conventions