1

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.

Yash Mathur
  • 243
  • 2
  • 7
  • You need to tell the `TableModel` that something has changed (and in general which cell) – MadProgrammer May 12 '20 at 23:58
  • But is this object in fact part of the table model? – DontKnowMuchBut Getting Better May 12 '20 at 23:59
  • You could have a look at [this example](https://stackoverflow.com/questions/13753562/adding-progress-bar-to-each-table-cell-for-file-progress-java/13755155#13755155) which demonstrates updating the progress bar of a number of cells – MadProgrammer May 13 '20 at 00:00
  • `value == Integer.valueOf(-1)` << that's playing with fire, use `Object.equals` to compare objects. – TT. May 13 '20 at 05:08
  • @DontKnowMuchButGettingBetter , the value in the array done is not included in the table. it is just a randomly generated by a different part of the code, and I want the changes to reflect. – Yash Mathur May 13 '20 at 10:31
  • @MadProgrammer, im sorry but i didnt quite understand how are you telling the table that something has changed in the example u listed. i believe the file inputs and such have confused me there. could u please dumb it down for me a little. Thanks in advance. – Yash Mathur May 13 '20 at 10:41
  • @TT. thank you for ur suggestion. I'll see to implement the same in my code. – Yash Mathur May 13 '20 at 10:44
  • 1
    Please make your code [mre]. We should be ablr to copy-paste and run it. – c0der May 13 '20 at 10:56
  • @c0der, done. my apologies that i did not know how to do that until now. i hope that might be enough to help. as in the code, the cell background of 10 only changes when I click on it, and not on its own. – Yash Mathur May 13 '20 at 23:16
  • 1
    Well done. It is certainly more of an MRE now. – c0der May 14 '20 at 05:12

1 Answers1

1

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

c0der
  • 18,467
  • 6
  • 33
  • 65