# JTable: Alle selektierten Zellen abfangen



## Crasher (26. Mai 2010)

Hi @ all,

ich habe einen ColorRenderer geschrieben, der mit die markierte Zelle mit Benutzerdefinierten farben füllt.
Jetzt stehe ich vor dem Problem, dass aber alle selektierten Zellen mit den Farben gefüllt werden sollen.
Mein jetztiger Code färbt aber immer nur eine Zelle. Könnt ihr mir helfen!?


```
public Component getTableCellRendererComponent(
                  JTable table, Object value,
                  boolean isSelected, boolean hasFocus, int row, int column) {
              super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
              if(isSelected){
              selectedRow = row;
              selectedClm = column;
                    if(jTable1.getModel().getValueAt(row, column) != null){
                      String[] selectedCellContent =  jTable1.getModel().getValueAt(row, column).toString().split("-");
                      colors1.clear();
                      for (int i=0; i<selectedCellContent.length; i++) {
                        String[] rgb = selectedCellContent[i].split(",");
                        Color rgbColor = new Color(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]));
                        colors1.add(rgbColor);
                      }
                      //currentColorLabel1.setBorder(BorderFactory.createLineBorder(Color.black));
                      return currentColorLabel1;
                    }
                    //currentColorLabel1.setText(getText());
                    return this;

              } else {
                if(jTable1.getModel().getValueAt(row, column) != null){
                  colorsOther1.clear();
                  String[] selectedCellContent =  jTable1.getModel().getValueAt(row, column).toString().split("-");
                  for (int i=0; i<selectedCellContent.length; i++) {
                    String[] rgb = selectedCellContent[i].split(",");
                    Color rgbColor = new Color(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]));
                    colorsOther1.add(rgbColor);
                  }

                  //otherColorLabel1.setText(getText());
                  return otherColorLabel1;
                }
                return this;
              }

          }
      });
```


Danke schonmal.
Greetz
Crasher


----------



## Foermchen82 (26. Mai 2010)

scheinbar bedeutet "isSelected" nicht markiert sondern nur die Zelle, die du zuletzt angeklickt hast. Da du jedoch die JTable zur Verfügung hast kannst du darüber die selektierten Zellen ermitteln und dann händisch einfärben. Habs selbst nicht ausprobiert. Aber es ist mal ne Idee! *g*


----------



## Michael... (26. Mai 2010)

Der Code enthält viele Unbekannte
Ausserdem ist sowas (sofern es überhaupt das gewünschte liefert) überflüssig:


Crasher hat gesagt.:


> ```
> jTable1.getModel().getValueAt(row, column)
> ```


weil es schon Durch die Variable value geliefert wird.

Was genau hast Du vor?
Irgendwo in der Tabelle stehen Farbinformationen die vorgeben wie die selektieren Zellen eingefärbt werden sollen. Stehen die in der Zelle selbst? Oder z.B. nur in der ersten Zelle jeder Zeile?

Ausserdem schaut das ganze ziemlich merkwürdig aus.


----------



## Michael... (26. Mai 2010)

Foermchen82 hat gesagt.:


> scheinbar bedeutet "isSelected" nicht markiert sondern nur die Zelle, die du zuletzt angeklickt hast.


 isSelected sagt aus (wie der Name schon vermuten lässt), ob die Zelle selektiert ist. Die aktuell "angeklickte" Zelle ist mit hasFocus markiert.


----------



## Foermchen82 (26. Mai 2010)

Michael... hat gesagt.:


> isSelected sagt aus (wie der Name schon vermuten lässt), ob die Zelle selektiert ist. Die aktuell "angeklickte" Zelle ist mit hasFocus markiert.



ah primea. Wieder was gelernt.


----------



## Crasher (26. Mai 2010)

Hi Jungs,

danke für die schnelle Antwort.
Also ich versuch es euch mal zu beschreiben.

In meiner Tabelle werden Monate und Tage dargestellt. Für jeden Tag kann eine Farbe (oder Mehrere) hinzugefügt werden.
Die Farben werden über ein JPopUp ausgewählt und zu "colors" hinzugefügt. Die Farben werden dann (für den Benutzer nicht sichtbar, da das Label über der Zelle liegt) in die Zelle geschrieben um für jeden Tag die Farben zu speichern.
Wenn man jetzt aber mehrere Tage gleichzeitig markieren möchte, um zu jedem ausgewählten Tag via PopUp eine Farbe hinzuzufügen
möchte, klappt das nicht. Ich müsste also irgendwie alle markierten Tage abfragen statt nur isSelected.

Mein currentColorLabel1 ist das Label, welches die aktuell geänderte zelle darstellt. otherColorLabel stellt die andren Zellen dar, indem vorher die Faben aus der entsprechenden Zelle ausgelesen werden.

Gruß
Kevin


----------



## Michael... (26. Mai 2010)

Crasher hat gesagt.:


> Wenn man jetzt aber mehrere Tage gleichzeitig markieren möchte, um zu jedem ausgewählten Tag via PopUp eine Farbe hinzuzufügen


Du möchtest also den selektierten auf einmal ein Farbe zuordnen?

Die Zuordnung erfolgt doch unabhängig vom CellRenderer und sollte doch mehr oder weniger wie folgt ablaufen:
- Zellen werden selektiert
- Popup öffnet sich und Farbe wird ausgewählt
- die ausgewählte Farbe wird im Model bzw. in den Objekten der Zellen gespeichert.
- Renderer wertet die gespeicherte Farbe aus und weist sie der Zelle als Hintergrundfarbe zu


----------



## Michael... (26. Mai 2010)

Crasher hat gesagt.:


> In meiner Tabelle werden Monate und Tage dargestellt. Für jeden Tag kann eine Farbe (oder Mehrere) hinzugefügt werden.


Was hat es mit dem "mehrere" auf sich und wie wirkt sich das auf die Zelle oder den Tag aus?


----------



## Crasher (26. Mai 2010)

Hi,

genau. Ich möchte alle selektierten Zellen einfärben.

Wenn mehrere Farben hinzugefügt werden, werden die Farben, der größe des Labels entsprechend, aufgeteilt:


```
JLabel currentColorLabel1 = new JLabel() {
              @Override
              protected void paintComponent(Graphics g) {
                  int w = getWidth() / colors1.size();
                  for (int i = 0; i < colors1.size(); i++) {
                      g.setColor(colors1.get(i));
                      g.fillRect(w * i, 0, w, getHeight());
                  }
                  super.paintComponent(g);
              }
          };
```



> Die Zuordnung erfolgt doch unabhängig vom CellRenderer und sollte doch mehr oder weniger wie folgt ablaufen:
> - Zellen werden selektiert
> - Popup öffnet sich und Farbe wird ausgewählt
> - die ausgewählte Farbe wird im Model bzw. in den Objekten der Zellen gespeichert.
> - Renderer wertet die gespeicherte Farbe aus und weist sie der Zelle als Hintergrundfarbe zu




```
ActionListener menuListener1 = new ActionListener() {
    public void actionPerformed(ActionEvent event) {

      String assistantsName = event.getActionCommand();
      //Die gewählte Farbe auswählen und zu Colors hinzufügen
      for(int i=0; i<cast.length; i++){
        if(assistantsName.equals(train[i][0] + " " + train[i][1])){
          String[] rgb = train[i][3].split(",");
          assistantsColor = new Color(Integer.parseInt(rgb[0]),Integer.parseInt(rgb[1]),Integer.parseInt(rgb[2]));
        }
      }

      colors1.clear();
      colors1.add(assistantsColor);

      //Wenn schon Farben in der Zelle ingetragen wurden, diese auch zu Colors hinzufügen
      if(jTable1.getModel().getValueAt(selectedRow, selectedClm) != null){
        String[] selectedCellContent =  jTable1.getModel().getValueAt(selectedRow, selectedClm).toString().split("-");
        for (int i=0; i<selectedCellContent.length; i++) {
          String[] rgb = selectedCellContent[i].split(",");
          Color rgbColor = new Color(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]));
          colorsOther1.add(rgbColor);
          colors1.add(rgbColor);
        }
      }
      
      //Farben in Zelle schreiben.
      jTable1.getModel().setValueAt("", selectedRow, selectedClm);
      for(int i=0; i<colors1.size();i++){
        int r = colors1.get(i).getRed();
        int g = colors1.get(i).getGreen();
        int b = colors1.get(i).getBlue();
        System.out.println(r + "," + g + "," + b);

        if(jTable1.getModel().getValueAt(selectedRow, selectedClm).equals("")){
          Object newStringData = r + "," + g + "," + b;
          jTable1.getModel().setValueAt(newStringData, selectedRow, selectedClm);
        }else{
          lastIn = jTable1.getModel().getValueAt(selectedRow, selectedClm).toString();
          Object newStringData = lastIn + "-" + r + "," + g + "," + b;
          jTable1.getModel().setValueAt(newStringData, selectedRow, selectedClm);
        }
      }
    }
  };
```


----------



## Crasher (26. Mai 2010)

Der CellRenderer setzt dann ja nur noch das Label der entsprechenden Zelle (momentant isSelected) und füllt dieses mit den entsprechenden Farben.

Jetzt müsste der CellRenderer statt nur isSelected (ich dachte das filt für alle selektierten Zellen) für alle Selektierten Zellen die änderung vornehmen.


----------



## Michael... (26. Mai 2010)

Die Farben sollen ja grundsätzlich angezeigt werden nicht nur bei den selektierten Zellen. Du bist da auf dem Holzweg und scheinbar hast Du das Konzept des CellRenderers nicht richtig verstanden.
Der Renderer "zeichnet" nur die Zelle, das Setzen der Farbinformationen muss unabhängig davon vorgenommen werden.
Hier mal ein q&d Demo:

```
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

public class CalendarColorTable extends JFrame {
	private JTable table;
	private Color[] color;
	private DefaultTableModel model;
	
	public CalendarColorTable() {
		CalendarObject[][] data = new CalendarObject[3][7];
		for (int i=0; i<data.length; i++)
			for (int k=0;k<data[i].length; k++)
				data[i][k] = new CalendarObject((i+1) * k);
		table = new JTable(model = new DefaultTableModel(data, new String[] {"A", "B", "C", "D", "E", "F", "G"}) {
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		});
		this.getContentPane().add(new JScrollPane(table));
		table.setRowSelectionAllowed(true);
		table.setColumnSelectionAllowed(true);
		table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
			private Color[] colors;
			public Component getTableCellRendererComponent(JTable table, Object value,
                    boolean isSelected, boolean hasFocus, int row, int column) {
				super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
				if (value==null) {
					this.setText("");
					this.colors = null;
				}
				else {
					CalendarObject co = (CalendarObject)value;
					this.setText("" + co.getDayOfMonth());
					this.colors = co.getColors();
				}
				return this;
			}
			
			public void paintComponent(Graphics g) {
				if (colors!=null) {
					int w = this.getWidth()/colors.length;
					for (int i=0; i<colors.length; i++) {
						g.setColor(colors[i]);
						g.fillRect(i * w, 0, w, getHeight());
					}
				}
				super.paintComponent(g);
			}
		});
		JPopupMenu popup = new JPopupMenu();
		color = new Color[] {Color.RED, Color.GREEN, Color.ORANGE, Color.BLUE};
		for (int i=0; i<color.length; i++) {
			JMenuItem item = new JMenuItem(color[i].toString());
			item.addActionListener(new MenuItemListener(color[i]));
			popup.add(item);
		}
		table.setComponentPopupMenu(popup);
	}
	
	class MenuItemListener implements ActionListener {
		Color color;
		public MenuItemListener(Color color) {
			this.color = color;
		}
		
		public void actionPerformed(ActionEvent e) {
			int row[] = table.getSelectedRows();
			int column[] = table.getSelectedColumns();
			for (int r=0; r<row.length; r++) {
				for (int c=0; c<column.length; c++) {
					Object o = table.getValueAt(row[r], column[c]);
					if (o instanceof CalendarObject) {
						CalendarObject co = (CalendarObject)o;
						co.addColor(color);
					}
				}
			}
			model.fireTableDataChanged();
		}
	}
	
	class CalendarObject {
		private int dayOfMonth;
		private List<Color> colorList;
		
		public CalendarObject(int day) {
			this.dayOfMonth = day;
		}
		
		public int getDayOfMonth() {
			return this.dayOfMonth;
		}
		
		public void addColor(Color color) {
			if (colorList==null)
				colorList = new ArrayList<Color>();
			colorList.add(color);
		}
		
		public Color[] getColors() {
			if (colorList==null || colorList.size()==0)
				return new Color[] {Color.WHITE};
			else
				return this.colorList.toArray(new Color[colorList.size()]);
		}
	}
	
	public static void main(String[] args) {
		JFrame frame = new CalendarColorTable();
		frame.setBounds(0, 0, 500, 300);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}
```


----------



## Crasher (27. Mai 2010)

Hi,
danke für dein Beispiel. Wieder was dazu gelernt 
Ich habe es auf meinen Code angepasst und es funktioniert einwandfrei.
Ich habe nur noch ein Problem beim Speichern der Daten. Ich speicher die Daten in einer CSV-Datei indem ich die Farben aus dem CalendarObject auslese.
Die Farben speicher ich einzeln in ror, grün und blau. Sind es mehrere werden Sie durch "|-|" getrennt.
Beim auslesen benutze ich mehrere For-Schleifen, um die Daten voneinander zu trennen und in eine Farbe mittels new Color() umwandel:

```
public void setColorsToCalendarObject(){
    getYear();
    trainnumber = mt.selection;
    
    File isFile = new File("data/trains/" + trainnumber + "_" + currentYear + ".csv");
    if(isFile.isFile()){
      readCSV("data/trains/" + trainnumber + "_" + currentYear + ".csv");
      closeBufferedReader();

      //Daten einlesen und in Tabelle schreiben
      for(int i=0; i<cast.length; ++i){
        for(int j=0; j<line.length; ++j){
          Object o = jTable1.getValueAt(i, j);
          if (o instanceof CalendarObject) {
              CalendarObject co = (CalendarObject)o;
              String[] currentCellContent = train[i][j].toString().split("|-|");
              for (int k=0; k<currentCellContent.length; k++) {
                System.out.println(currentCellContent[k] + "   " + currentCellContent.length);
                String[] rgb = currentCellContent[k].split(",");
                Color rgbColor = new Color(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]));
                co.addColor(rgbColor);
              }
          }
        }
      }
    }
  }
```

Mein Problem ist, dass die Variable currentCellContent (wird in der zweiten For-Schleife angelegt), nicht korrekt an die dritte For-Schleife weiter gegeben wird. Der Array train_[j] enthält allerdings noch die korrekten Daten. Der Array nach dem Splitten wohl nicht mehr.
Fällt dir zufällig auf, woran das liegen könnte!?.

Vielen dank schonmal.
Greetz
Kevin_


----------



## Michael... (27. Mai 2010)

Bei regulären Ausdrücken ist der *|* ein Metazeichen und muss daher maskiert werden, wenn er normales Zeichen interpretiert werden soll. In etwa so:

```
split("\\|-\\|");
```
Eventuell muss das *-* auch noch maskiert werden (bin mir nicht sicher, ob das nicht nur innerhalb einer Zeichenauswahl als Metazeichen gilt)

```
split("\\|\\-\\|");
```

Du hast Dir also ziemlich ungünstige Trennzeichen ausgesucht ;-)


----------



## Crasher (28. Mai 2010)

Prima. Jetzt läuft alles genau so, wie ich es brauche.

Schönen Abend noch 

Greetz
Kevin


----------

