1 Reply Latest reply on Jun 5, 2013 6:42 AM by gimbal2

    JTable and Renderer Class

    1012772
      Hello,

      After many and many tries, I was unable to get what I wanted.
      I'm trying to develop a very popular game in France (Morpion : a kind of Tic-TacToe ). I have created a 9x9 grid with a JTable.
      By clicking in a cell I fill it either with a X or a O alternatively. This works pretty well.

      When there are at least 3 X or 3 O (for the moment not necessarily contiguous) I would like characters to be coloured either in red or green depending on which they are.
      To do this, I have defined 2 vectors (rouge et bleu) into which I put the cells coordinates under a very simple hash format key ( 10*row + column) for performance reasons. This works because the number of cells per row or per column is <10).

      In addition I have created a renderer class :
      jt.setDefaultRenderer(Object.class, new MyRenderer());

      Here is the problem I got : I cannot set the right colour for characters. Depending cases, they are coloured anarchically in any colour : red or green.

      I guess it is because I haven't understand very well how all these things work. For this reason I need your help to explain me how to do.
      Many thanks in advance.


      Gégé_

      BTW: For the moment I'm know that my code is neither optimized nor very clean because it's just a test.
      I hope you have understood my bad English.
       
      package test;
      import java.awt.Color;
      import java.awt.Component;
      import java.awt.event.ActionEvent;
      import java.util.Vector;
       
      import javax.swing.BorderFactory;
      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JLabel;
      import javax.swing.JPanel;
      import javax.swing.JTable;
      import javax.swing.ListSelectionModel;
      import javax.swing.border.Border;
      import javax.swing.event.ListSelectionEvent;
      import javax.swing.event.ListSelectionListener;
      import javax.swing.table.DefaultTableModel;
       
           public class TestMorpion  extends JFrame implements java.awt.event.ActionListener, ListSelectionListener
           {
                   int currentLigne =0;
                   int currentColonne =0;
                   int cells      = 9 ;    // nombre de cases par ligne  ou colonnes 
                   protected String[][] valeur      = new String[cells][cells];
       
                   protected String c = "";
                   protected JPanel JFrameContentPane = new JPanel();
                   protected JPanel panel = null;
                   protected JLabel monLabel, message;
                   protected DefaultTableModel dtm ;
                   protected JButton Terminer ; 
                   private JTable jt = null;
                   protected ListSelectionModel lsm = null;
                   Vector rouge = null;
                   Vector bleu = null;
                   int jeu = 0;
       
                   boolean  toggle=true,
                            inProcess=false;
       
                   public TestMorpion() 
                   {
                       super("Jeux de pions");
                       panel = new JPanel();
                       JFrameContentPane.setLayout(null);
                       setSize(309, 344);
                         setContentPane(JFrameContentPane);
                       this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                       definirGrille();
                       definirBoutons();
                       this.setLocationRelativeTo(null);
                       this.setVisible(true);
                   }
       
                   void definirBoutons()
                   {
       
                        Terminer = new JButton();
                        Terminer.setBounds(170, 230, 86, 25);
                        Terminer.setText("Quitter");
                        JFrameContentPane.add(Terminer);
                        Terminer.addActionListener(this);
                   }
       
                   void definirGrille()
                   {
                        panel = new javax.swing.JPanel();
                         panel.setName("monPaneau");
                         panel.setLayout(new java.awt.GridLayout());
                         panel.setBounds(10, 44, 272, 151);
                         panel.setBackground(Color.white);
                         // Defining the grid 
                         dtm = new DefaultTableModel(cells,cells);
       
                        jt = new JTable(dtm);
                        jt.setDefaultRenderer(Object.class, new MyRenderer()); 
                         panel.add(jt);
                         jt.setCellSelectionEnabled(true);
                         jt.setGridColor( Color.BLACK) ;  
                         JFrameContentPane.add(panel);
       
                         Border raisedbevel, loweredbevel, compound;
                         raisedbevel = BorderFactory.createRaisedBevelBorder();
                         loweredbevel = BorderFactory.createLoweredBevelBorder();
                         compound = BorderFactory.createCompoundBorder(raisedbevel, loweredbevel);
                       panel.setBorder(compound);
       
                       lsm = jt.getSelectionModel(); 
                       lsm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                       clearGrille();
                       lsm.addListSelectionListener(this); 
       
                   }
       
                   @Override
                   public void actionPerformed(ActionEvent e) 
                   {
                     if (e.getSource() == Terminer)      { System.exit(0);}
                   }
       
                   void clearGrille()
                   {
                        lsm.removeListSelectionListener(this);
                        rouge = new Vector();
                           bleu = new Vector();
                        for (int i=0; i<cells;i++)
                             for (int j=0;j<cells;j++) jt.setValueAt(" ", i, j);
                        lsm.addListSelectionListener(this);
                   }
       
                   public void valueChanged(ListSelectionEvent listSelectionEvent)
                   {
                           int ligne =  jt.getSelectedRow();
                           if (ligne<0)return; // ligne invalide
                           int colonne = jt.getSelectedColumn();
                           if (colonne<0) return; // ligne invalide
                               executerMorpion(ligne, colonne); 
                   }
       
                   private void executerMorpion(int i,int j) 
                   {
                        String wk = "",   old;
                        old = ((String) jt.getValueAt(i, j));
                        if (old==null) old="";
                        old=old.trim();
                       if (!old.equals("")) 
                            return;  // cell not free
                       if (rouge.size()>=3) rouge.clear(); 
                        if (bleu.size()>=3)  bleu.clear(); 
                        if (toggle) 
                        {     
                             wk ="X";
                             toggle=false;
                             rouge.add(rouge.size(),""+(10*i +j));
                        }
                        else   
                        {
                             wk ="O";
                             toggle=true;
                             bleu.add(bleu.size(),""+(10*i +j));
                        }
                        currentLigne=i;
                        currentColonne=j;
                        valeur[i][j] = wk;
                        jt.setValueAt("  "+ wk, i, j);
                   }
       
       
                     public static void main(String args[]) 
                     {
                        new TestMorpion();
                   }
       
                     public class MyRenderer extends  javax.swing.table.DefaultTableCellRenderer 
                     {
                          private static final long serialVersionUID = 1L;
       
                          @Override
                          public  Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)  
                          {
                                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
                              // immediate return if some conditions are not fulfilled  
                                if ( row < 0 || col < 0) return c;
                                String old = valeur[row][col];
                                if (old==null ) return c;
                                if ( old.trim().equals("")) return c;
                                if (rouge == null) return c ;
                                 if (bleu == null) return c;
                                Vector vb = bleu;  // copying vector for test purpose
                                Vector vr = rouge;
                                if (vr.size()<3 && vb.size()< 3 ) return c;   // not 3 entries yet
                              // end of conditions for returning
       
                                String clef =  String.valueOf(10*row+col); // on calcule la clef de cette case  pour raison de performance
                                if (vr.indexOf(clef)< 0 & vr.indexOf(clef)< 0) return c; // These coordinates are not found in any vector.  So no colour to apply
       
                                String car="";
                                if (vr.size()>=3)
                                {       
                                     for (int i=0; i< vr.size(); i++)
                                     {       
                                         car = (String) vr.elementAt(i);
                                          if (car.equals(clef) && old.equals("X")) 
                                          {       
                                               c.setForeground(Color.RED);
                                               return c;
                                          }       
                                     } 
                                }       
                                if (vb.size()>=3)
                                 {       
                                     for (int i=0; i< vb.size(); i++)
                                     {       
                                          car = (String) vr.elementAt(i);
                                          if (car.equals(clef) &&  old.equals("O"))  
                                          {       
                                               c.setForeground(Color.GREEN);  
                                               return c;
                                          }       
                                     } 
                                 }
       
                                c.setForeground(Color.BLACK);
                             return c;    
                             }
                          }
                          private static final long serialVersionUID = 1L;
       
                          static String afficherMenu(String morpion) {
                            throw new UnsupportedOperationException("Not yet implemented");
                        }     
               }
      
       
        • 1. Re: JTable and Renderer Class
          gimbal2
          I spot one major problem: I already see two references to performance in your problem description and at least one of them is a premature optimization. Stop that immediately. Java is far better at optimization than you will ever be; just write dumb, readable code and don't get in its way.

          The first thing you should do is to in fact clean up your code: I see you omitting curly braces ( { } ) everywhere - put them back in. This not only makes your code more readable for yourself but also to people that will attempt to help you here, it also prevents you making mistakes.

          After you've done that, try peppering your code with System.out statements to see what is going on. I know it is difficult to debug a Swing application due to it being multithreaded, but the good old System.out usually gives me a clear enough picture about what happens in which order. You know where your problem is so you don't have to put them EVERYWHERE, just the bits of code that have to do with the red/green logic.

          A final note: your question really isn't about game development (its a useless forum that will probably disappear in a few days anyway). You would have been far better off posting this in the Swing forum. I will request to have it moved for you.

          EDIT:

          oh, and welcome to the forum ;)