DefaultTableCellRenderer

OliW

Aktives Mitglied
Hallo zusammen,

ich suche jetzt seit fast 2 Stunden wie ich ein, wie ich dachte, einfaches Prolem lösen kann und werde nicht fündig.
Ich denke, daß sich das mit den DefaultTableCellRenderer lösen lässt, aber wie bestimme ich eine einzelne Zeile.

Ich habe ein JTable das ich durch Eingaben über ein Eingabefenster fülle.
Für dieses Eingabefenster habe ich ein ein eigenes JFrame programmiert, in dem die einzelnen Werte für den JTable übergeben werden.
Letzlich wird ein neues Objekt (neue Zeile) dem JTable über einen Klick auf einen Button (Hinzufügen) übergeben.
Funktioniert alles.
U.a. habe ich in dem Engabeframe eine ComboBox aus der 2 Werte ausgewählt werden können
>> Komplettlieferung
>> Teilllieferung

Was jetzt geschehen soll, ist, daß die Zeile im JTable gelb eingefärt wird, wenn "Komplettlieferung" ausgewählt ist und rot wenn "Teillieferung" ausgeählt ist.

Anbei noch der Code Action Listener (Klick auf Hinzufügen). Bei den ??? komme ich nicht weiter.
Hat jemand einen Tipp?

Code:
 public class EingangBuchen implements ActionListener {
        
         @Override
        public void actionPerformed(ActionEvent e) {
        
             Lagernummer++;
             DefaultTableCellRenderer colorRenderer = new DefaultTableCellRenderer();
            
             String bestellnummer  = fldBestellnummer.getText(); 
             String lagernummer = ("G"+Lagernummer);
             int anzahl = 1;
             String verpackung = (String) comboVerpackung.getSelectedItem(); 
             int  gewicht = Integer.parseInt(fldGewicht.getText());
             String abmessungen = fldAbmessungen.getText();
             String projekt = fldProjekt.getText();
             String lieferant = fldLieferant.getText();
             String weDatum = fldWEDatum.getText();
             String tour = fldTour.getText();
             String versand = fldVersand.getText();
            
            
             Lagerposition lagerPos = new Lagerposition (bestellnummer,lagernummer,anzahl,verpackung,gewicht,abmessungen,projekt,lieferant,weDatum,tour,versand);
             model.add(lagerPos);
            
             if (comboVollständigkeit.getSelectedItem() ==  "Komplettlieferung") {
                
                ?????????????
                
             }
            
            

        
     }
 

mihe7

Top Contributor
Hat jemand einen Tipp?
Vorab: Strings/Objekte vergleicht man mit equals und nicht mit ==.

Du musst für den Spaß nur einen TableCellRenderer implementieren und diesen in der JTable verwenden. An anderer Stelle musst Du dann nichts machen.

Ein etwas allgemeinerer Ansatz wäre dann etwa wie:
Java:
import java.awt.Color;
import java.awt.Component;

import java.util.Optional;
import java.util.function.IntFunction;

import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import javax.swing.plaf.ColorUIResource;

public class RowColorRenderer implements TableCellRenderer {
    private final IntFunction<Optional<Color>> colorFunc;
    private final TableCellRenderer delegate;

    public RowColorRenderer(TableCellRenderer delegate, 
                            IntFunction<Optional<Color>> colorFunc) {
        this.delegate = delegate;
        this.colorFunc = colorFunc;
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, 
            Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        Component comp = delegate.getTableCellRendererComponent(table, value, 
                isSelected, hasFocus, row, column);
        if (!isSelected) {
            comp.setBackground(colorFunc.apply(row).orElse(table.getBackground()));
        }        
        return comp;
    }
}

Beispiel für die Verwendung:
Java:
import java.awt.Color;
import javax.swing.*;
import javax.swing.table.*;

import java.util.Optional;
import java.util.function.IntFunction;

public class Test {

    private String[] columnNames = {"First Name",
                            "Last Name",
                            "Sport",
                            "# of Years",
                            "Enabled"};

    private Object[][] data = {
        {"Kathy", "Smith",
         "Snowboarding", new Integer(5), new Boolean(false)},
        {"John", "Doe",
         "Rowing", new Integer(3), new Boolean(true)},
        {"Sue", "Black",
         "Knitting", new Integer(2), new Boolean(false)},
        {"Jane", "White",
         "Speed reading", new Integer(20), new Boolean(true)},
        {"Joe", "Brown",
         "Pool", new Integer(10), new Boolean(false)}
    };


    public void run() {
        JTable table = new JTable(data, columnNames);

        IntFunction<Optional<Color>> colorMapper = ix -> {
            Color result = null;
            if (table.getModel().getValueAt(ix, 0).toString().startsWith("J")) {
                result = Color.YELLOW;
            }
            return Optional.ofNullable(result);
        };
        
        TableColumnModel tcm = table.getColumnModel();
        for (int i = 0, n = tcm.getColumnCount(); i < n; i++) {
            TableColumn col = tcm.getColumn(i);
            col.setCellRenderer(new RowColorRenderer(new DefaultTableCellRenderer(), 
                                                     colorMapper));
        }
        
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(new JScrollPane(table));
        frame.setSize(600, 400);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Test().run());
    }
}
 

OliW

Aktives Mitglied
Hm, ja Danke für den Tipp mit dem Vergleich von Strings.
Aber ich habe immer noch keine Idee, wie ich das lösen kann. Einen eigenen Renderer zu schreiben ist nicht das Problem. Aber wie bekomme ich Zugriff auf eine einzelne ganze Zeile. Es gibt sowas wie get.ColumnModell.getColumn, aber es gibt kein getRow.
Ich will ja eine Zeile färben und keine Spalte.

Jetzt habe ich das erstmal aus der Methode "EingangBuchen" herausgenommen, da ich die Fabe später nochmals ändern möchte, wenn sich der Status ändert (Es handels sich um Lagereingänge und Ausgänge mit den 4 Stadien "Teillieferung" "Komplettlieferung" "Teilausgang" und "Komplettausgang".
Je nach Status soll die Zeile unterschiedliche Farben haben.

Meine Idee ist den Renderer wie folgt zu implementieren. Aber wie definiere ich die Reihe
row.setColor geht ja so nicht. (was jetzt sehr anfängerfreundlich und nett wäre :)) )

Code:
public class ColorRenderer  implements TableCellRenderer {
        
         @Override
            public Component getTableCellRendererComponent(JTable arg0, Object arg1, boolean arg2, boolean arg3, int row,
                    int column) {
            
                
                    String s= LagerPosList.liste.get(row).Status;
                    
                    switch (s) {
                    case  "Komplettlieferung" : // Reihe gelb einfärben
                    case  "Teillieferung"     : // Reihe rot einfärben     
                    }
                
                
                return null  // ?? ;
            }

     }
 

OliW

Aktives Mitglied
Hätt mal noch kurz warten sollen vor dem Posten. Habs hinbekommen.

Code:
  public class ColorRenderer  implements TableCellRenderer {
        
         @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean arg2, boolean arg3, int row,
                    int column) {
            
             JTextField editor = new JTextField ();
                
                    String s= LagerPosList.liste.get(row).Status;
                    
                    switch (s) {
                    case  "Komplettlieferung" : editor.setBackground(Color.YELLOW);
                    break;
                    case  "Teillieferung"     : editor.setBackground(Color.blue);   
                    }
                    
                       editor.setText(value.toString());
                
                
                return editor;
            }

     }

und der Aufruf:

Code:
 for (int i=0; i<=model.getColumnCount()-1; i++) {
         table.getColumnModel().getColumn(i).setCellRenderer(centerRenderer);
         table.getColumnModel().getColumn(i).setCellRenderer(colorRenderer);
      }
 

mihe7

Top Contributor
Aber ich habe immer noch keine Idee, wie ich das lösen kann.
Ich habe Dir doch ein Beispiel geschrieben, das zeilenweise einfärbt, wenn der Anfangsbuchstabe der ersten Zelle der aktuellen Zeile mit J beginnt.

Aber wie bekomme ich Zugriff auf eine einzelne ganze Zeile.
Das kannst Du machen, wie Du willst, z. B. kannst Du dem Konstruktor Deines Renderers Dein Modell (z. B. eine Liste) mitgeben oder in einer inneren Klasse einfach auf die Daten zugreifen oder über das TableModel der JTable gehen oder ...
Ich will ja eine Zeile färben und keine Spalte.
Du musst den CellRenderer für alle Spalten setzen, wie hier:
Java:
        TableColumnModel tcm = table.getColumnModel();
        for (int i = 0, n = tcm.getColumnCount(); i < n; i++) {
            TableColumn col = tcm.getColumn(i);
            col.setCellRenderer(new RowColorRenderer(new DefaultTableCellRenderer(), 
                                                     colorMapper));
        }

Aber wie definiere ich die Reihe
row.setColor geht ja so nicht. (was jetzt sehr anfängerfreundlich und nett wäre :)) )
Das könntest Du auch haben - ebenfalls mit dem RowColorRenderer von oben. Dazu musst Du nur einen entsprechenden Mapper schreiben.
 

Ähnliche Java Themen

Neue Themen


Oben