web-dev-qa-db-fra.com

JTable Cell Renderer

Je suis certains codes que j'ai trouvés, (oui je comprends comment ça marche) C'est d'ici: Code Link

Ce que j'essaie de faire est de définir une couleur de premier plan de cellules si la valeur des cellules est définie sur "jaune"

Voici mon code:

public class Board extends JPanel{

private static final long serialVersionUID = 1L;

int boardHeight = 20;
int boardWidth = 10;

JTable table;

public Board() {
    table = new JTable(this.boardHeight, this.boardWidth);
    table.setDefaultRenderer(String.class, new BoardTableCellRenderer());
    table.setFocusable(false);
    table.setShowGrid(false);
    table.setRowMargin(0);
    table.setIntercellSpacing(new Dimension(0,0));
    table.setRowSelectionAllowed(false);
    table.setVisible(true);
    this.add(table);
    this.setPreferredSize(new Dimension(table.getPreferredSize().width, (table.getPreferredSize().height + 85)));
}

public void Paint(Graphics g) {
    table.setRowHeight(20);
    for (int x = 0; x < this.table.getColumnCount(); ++x) {
        TableColumn col = this.table.getColumnModel().getColumn(x);
        col.setPreferredWidth(20);
    }
}
}

Et le générateur de cellules

public class BoardTableCellRenderer extends DefaultTableCellRenderer {

private static final long serialVersionUID = 1L;

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);
    String s = table.getModel().getValueAt(row, col).toString();

    if (s.equalsIgnoreCase("yellow")) {
        c.setForeground(Color.YELLOW);
    }
    else {
        c.setForeground(Color.WHITE);
    }

    return c;
}
}

Le problème est que cela ne change pas, si je mets une valeur de cellule à "jaune"

Merci d'avance!

8
Diesal11

Est-ce que votre moteur de rendu est utilisé? Vous en faites le moteur de rendu par défaut pour les cellules contenant String, mais avez-vous surchargé la méthode getColumnClass de votre modèle afin qu'il sache que certaines des cellules contiennent des chaînes?

Je commencerai donc par utiliser les instructions println pour voir si le rendu est même appelé, sinon, je remplacerais la méthode de mon modèle, comme indiqué ci-dessus.

Modifier 1
Vos résultats seront également étranges. Dans la partie if, vous changez le premier plan et dans l'autre, vous changez l'arrière-plan - cela n'a aucun sens. Vous devriez probablement faire des changements d'état complémentaires dans les blocs if par rapport aux autres, et non des changements orthogonaux.

Modifier 2
Par exemple:

import Java.awt.*;
import Java.util.Random;

import javax.swing.*;
import javax.swing.table.*;

public class Board extends JPanel {

   private static final long serialVersionUID = 1L;

   int boardHeight = 20;
   int boardWidth = 10;

   JTable table;
   Random random = new Random();

   public Board() {
      setLayout(new BorderLayout()); // !!
      DefaultTableModel model = new DefaultTableModel(boardHeight, boardWidth) {
         @Override
         public Class<?> getColumnClass(int columnIndex) {
            return String.class;
         }
      };
      // !! table = new JTable(this.boardHeight, this.boardWidth);
      table = new JTable(model);
      for (int row = 0; row < model.getRowCount(); row++) {
         for (int col = 0; col < model.getColumnCount(); col++) {
            String s = random.nextBoolean() ? "red" : "yellow";
            model.setValueAt(s, row, col);
         }
      }
      table.setDefaultRenderer(String.class, new BoardTableCellRenderer());

      table.setFocusable(false);
      table.setShowGrid(false);
      table.setRowMargin(0);
      table.setIntercellSpacing(new Dimension(0, 0));
      table.setRowSelectionAllowed(false);
      table.setVisible(true);
      this.add(table);
      this.setPreferredSize(new Dimension(table.getPreferredSize().width,
               (table.getPreferredSize().height + 85)));
   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("Board");
      frame.getContentPane().add(new Board());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      Java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

class BoardTableCellRenderer extends DefaultTableCellRenderer {

   private static final long serialVersionUID = 1L;

   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);
      Object valueAt = table.getModel().getValueAt(row, col);
      String s = "";
      if (valueAt != null) {
         s = valueAt.toString();
      }

      if (s.equalsIgnoreCase("yellow")) {
         c.setForeground(Color.YELLOW);
         c.setBackground(Color.gray);
      } else {
         c.setForeground(Color.black);
         c.setBackground(Color.WHITE);
      }

      return c;
   }
}
10

Ajouter cette ligne:

c.setOpaque(true);

Le composant renvoyé par getTableCellRendererComponent doit être opaque pour que les modifications soient apportées aux couleurs d'arrière-plan et de premier plan. Le problème ici est aussi un autre: vous étendez DefaultTableCellRenderer (c'est-à-dire un JComponent) mais vous renvoyez un composant qui n'a pas de méthode setOpaque. Je voudrais refactoriser votre code comme ceci:

public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,int row,int col) {

    String s = table.getModel().getValueAt(row, col).toString();
    this.setOpaque(true);
    if (s.equalsIgnoreCase("yellow")) {
        this.setForeground(Color.YELLOW);
    }
    else {
        this.setBackground(Color.WHITE);
    }

    return this;
}
4
Heisenbug

Voici une solution simple, utilisez TabaleCellRendere en tant que classe interne.

    myTable.setDefaultRenderer(Object.class, new TableCellRenderer()
    {
        JLabel comp = new JLabel();
        String val;

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            comp.setOpaque(true);
            comp.setForeground(Color.BLACK); // text color

            if (value != null)
            {
                val = value.toString();
                comp.setText(val);

                if (val.equalsIgnoreCase("red"))
                {
                    comp.setBackground(Color.RED);
                }
                else if (val.equalsIgnoreCase("yellow"))
                {
                    comp.setBackground(Color.YELLOW);
                }
                else if (val.equalsIgnoreCase("green"))
                {
                    comp.setBackground(Color.GREEN);
                }
                else
                {
                    comp.setBackground(Color.WHITE);
                }
            }
            return comp;
        }
    });
1
Syed Maruf