# Checkbox in JTable (again), bei true Daten in Header



## Louis2 (10. Aug 2005)

Hallo,

also ich möchte zuerst sagen, dass ich die FAQ und auch viele andere Beiträge zu Checkbox&JTable studiert habe, aber so richtig verstehe ich es -leider- immer noch nicht.

Hintergrund: 
- 2 Frames: 
Frame 1 - JComboBox (gefüllt mit DB Tabellen Namen) und JTable
Frame 2 - JTable, 2 Spalten 1ste Felder aus DB 2te Checkbox
- Wenn in JComboBox Tabelle xxx ausgewählt wird, Frame 2 öffnet ist, zeigt in der JTable die Felder der Tabelle xxx und in Spalte2 Checkboxen.
- Auswahl der Checkboxen, klick auf JButton --> nur die ausgewählte Felder erscheinen in Frame 1 im Header der JTable

--> Wenn 3 Checkboxen selektiert werden in Frame1 3 Spalten erscheinen, im Header die 3 Feldnamen.

*Problem1: Checkboxen in JTable*
Also ich habe ein DefaultTableModel, füge auch Zeilenweise ein boolean Wert ein, ist aber noch keine Checkbox, das will ich erreichen.
So wenn ich es richtig verstanden habe brauche ich ein DefaultTableCellRenderer und was mache ich mit meinem DefaultTableModel, kann das eine vom anderen ganz separat behandelt werden? Bruchstücke hab ich bisher, ich stehe auf dem Schlauch...

```
table.setCellRenderer(new MyTableCellRenderer());
static class MyTableCellRenderer extends DefaultTableCellRenderer {
      public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
.
```


```
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel; 
import java.sql.*;
import java.util.*;
import java.util.List;

public class FieldsSelection extends JFrame 
{
      EmailClient main3;
      JTable table;
      String comboinhalt[];
      boolean isselected = false;
      JButton adopt = new JButton("Adopt the settings");
      List listfields;
      int fieldslen;
      DefaultTableModel model;
      String resultTable;
            
      public FieldsSelection(EmailClient emailclient)
      {
          super("Java bulk-email (Fields Selection)");
          
          this.main3 = emailclient;
          Container contentPane = this.getContentPane();
          contentPane.setLayout(new BorderLayout());
          JPanel select = new JPanel();
          select.setLayout(new FlowLayout(FlowLayout.LEFT));
          select.add(adopt);
          contentPane.add(select);
          
          String[] title = new String[]
          { 
            "Fields", "Selection" 
          }; 
          model = new DefaultTableModel (title,0); 
          table = new JTable(model)
          {
            public boolean isCellEditable(int rowIndex, int vColIndex) 
            {
                return false;
            }
          };
          getContentPane().add(new JScrollPane(table), BorderLayout.SOUTH);
          table.setRowSelectionAllowed(true);
          table.setColumnSelectionAllowed(false);
          table.setCellSelectionEnabled(true);
                    
          try
          {
            String resultselectedtable=new String();
            String resulttablefields=new String();
            Statement selectedtable = main3.connection.createStatement(); 
            resultselectedtable = "SELECT do.doctable FROM doctable do, description d WHERE do.active='1' and do.doctable=d.code and d.language='de' and d.description='" + main3.choice + "'";
            ResultSet rs1 = selectedtable.executeQuery(resultselectedtable); 
            
            List result = new ArrayList(); 
            while (rs1.next())
            {
                result.add(rs1.getString(1));
            }
            selectedtable.close();
            List listresult = (java.util.List) result; 
            resultTable = (String) listresult.get(0);
                                    
            Statement tablefields = main3.connection.createStatement(); 
            resulttablefields = "SELECT column_name FROM all_tab_columns WHERE table_name='" + resultTable + "'";
            ResultSet rs = tablefields.executeQuery(resulttablefields);
                       
            List fields = new ArrayList(); 
            while (rs.next()) 
            { 
                fields.add(rs.getString(1));
            }
            listfields = (java.util.List) fields; 
            fieldslen=listfields.size();
            
            for (int i=0;i<fieldslen;i++) 
            { 
                String outlistfields = (String) listfields.get(i);
                model.addRow(new Object[] {outlistfields, isselected}); 
            }
          }
          catch(Exception e3) 
          {    
            e3.printStackTrace();
            JOptionPane.showMessageDialog(null, "Error: " + "\n" + e3.getMessage()); 
          }
          this.pack();
      }
}
```


*Problem2: Ausgewählte Felder in Frame1 einfügen im Header*
Dazu habe ich mir auch Gedanken gemacht. Ich konnte es noch nicht testen, da ich vorher die Checkboxen in die JTable einfügen muss. Aber was meint Ihr so zum Code?

```
if (action == main2.adopt) //Button von Klasse FieldsSelection
        {
           List selectedfieldsList = new ArrayList();
           for (int i=0;i<main2.fieldslen;i++) // fieldslen Länge der JTable mit Felder
           { 
                if (main2.isselected == true) // wenn CheckBox true dann pack Wert in neue Liste
                {
                    String selectedfields = (String) main2.listfields.get(i);
                    selectedfieldsList.add(selectedfields);
                }
           } 
           int selectedfieldslen = selectedfieldsList.size();
           TableColumn column = new TableColumn();
           for (int j=0;j<selectedfieldslen;j++) //Gib Werte in JTable im Header aus
           { 
                column.setHeaderValue(selectedfieldsList.get(j)); 
                columnModel.addColumn(column); 
           } 
        }
```


----------



## Beni (11. Aug 2005)

Zu 1:
Einfache Lösung: Checkboxen gibt es bereits in der JTable. Überschreib bei deinem TableModel die Methode "getColumnClass", und gib für die Spalte mit den booleans "Boolean.class" zurück.

Wenn du unbedingt deinen eigenen Renderer machen willst: dann ist das einfachste auch hier "getColumnClass" in TableModel zu überschreiben, und auch "JTable.setDefaultRenderer( Boolean.class, deinRenderer );" aufzurufen.

Ein Renderer zeichnet genau (!) eine einzige Zelle.
Das funktioniert so:
1. Die JTable fragt über "getTableCellRendererComponent" ab, wie die Zelle aussehen soll.
2. Die Zelle wird gezeichnet.
3. Zurück zu 1, aber für eine andere Zelle.

Eine sehr einfache Version würde dann so aussehen:

```
public class BooleanRendere implements TableCellRenderer{
  private JCheckBox box = new JCheckBox();
  public Component getTableCellRendererComponent( ... ){
    box.setSelected( ((Boolean)value).booleanValue );
    return box;
  }
}
```

Damit kann man noch keine Werte verändern, dazu müsstest du einen TableCellEdtior implementieren, und mit "setDefaultEditor( Boolean.class, deinEditor );" registrieren. Ein Editor funktioniert genau gleich wie ein Renderer, nur dass der Wert des Editors (hier true/false) von der JTable abgefragt werden kann. (Sie leitet diesen Wert dann an "TableModel.setValueAt" weiter).


Zu 2: sieht für mich komisch aus. Veränderungen der Daten sollten immer über das TableModel laufen, wenn man direkt mit den Column's arbeitet, geht schnell was schief (Man kann ja auch über das TableModel Header-Titel verändern, und Spalten hinzufügen...).


----------



## Louis2 (11. Aug 2005)

*Zu 1:*
So sieht die ganze Klasse nun aus indem ich paar Sachen hinzugefügt habe, dargestellt wird die Checkbox allerdings immer noch nicht.

```
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel; 
import java.sql.*;
import java.util.*;
import java.util.List;

public class FieldsSelection extends JFrame 
{
      EmailClient main3;
      JTable table;
      String comboinhalt[];
      Boolean isselected = new Boolean(false);
      JButton adopt = new JButton("Adopt the settings");
      List listfields;
      int fieldslen;
      DefaultTableModel model;
      String resultTable;
      private Class[] classes; 
            
      public FieldsSelection(EmailClient emailclient)
      {
          super("Java bulk-email (Fields Selection)");
          
          this.main3 = emailclient;
          Container contentPane = this.getContentPane();
          contentPane.setLayout(new BorderLayout());
          JPanel select = new JPanel();
          select.setLayout(new FlowLayout(FlowLayout.LEFT));
          select.add(adopt);
          contentPane.add(select);
          
          classes = new Class[]
          { 
            String.class, 
            Boolean.class, 
          }; 
          
          String[] title = new String[]
          { 
            "Fields", "Selection" 
          }; 
          model = new DefaultTableModel (title,0); 
          table = new JTable(model)
          {
            public boolean isCellEditable(int rowIndex, int vColIndex) 
            {
                return false;
            }
          };
          getContentPane().add(new JScrollPane(table), BorderLayout.SOUTH);
          table.setRowSelectionAllowed(true);
          table.setColumnSelectionAllowed(false);
          table.setCellSelectionEnabled(true);
                    
          try
          {
            String resultselectedtable=new String();
            String resulttablefields=new String();
            Statement selectedtable = main3.connection.createStatement(); 
            resultselectedtable = "SELECT do.doctable FROM doctable do, description d WHERE do.active='1' and do.doctable=d.code and d.language='de' and d.description='" + main3.choice + "'";
            System.out.println(resultselectedtable);
            ResultSet rs1 = selectedtable.executeQuery(resultselectedtable); 
            
            List result = new ArrayList(); 
            while (rs1.next())
            {
                result.add(rs1.getString(1));
            }
            selectedtable.close();
            List listresult = (java.util.List) result; 
            resultTable = (String) listresult.get(0);
            System.out.println(resultTable);
                                    
            Statement tablefields = main3.connection.createStatement(); 
            resulttablefields = "SELECT column_name FROM all_tab_columns WHERE table_name='" + resultTable + "'";
            ResultSet rs = tablefields.executeQuery(resulttablefields);
                       
            List fields = new ArrayList(); 
            while (rs.next()) 
            { 
                fields.add(rs.getString(1));
            }
            listfields = (java.util.List) fields; 
            fieldslen=listfields.size();
            
            for (int i=0;i<fieldslen;i++) 
            { 
                String outlistfields = (String) listfields.get(i);
                model.addRow(new Object[] {outlistfields, isselected}); 
            }
          }
          catch(Exception e3) 
          {    
            e3.printStackTrace();
            JOptionPane.showMessageDialog(null, "Error: " + "\n" + e3.getMessage()); 
          }
          this.pack();
      }
      public Class getColumnClass(int columnIndex) 
      { 
         return classes[columnIndex]; 
      } 
}
```


----------



## Beni (11. Aug 2005)

Auch wenn ich dir glaube, dass du in der FAQ rumgelesen hast, guck dir mal dieses Beispiel an. Das zeigt doch, wie man CheckBoxen darzeigen lässt.

Es läuft darauf hinaus, dass du


			
				Beni hat gesagt.:
			
		

> Überschreib bei deinem TableModel die Methode "getColumnClass", und gib für die Spalte mit den booleans "Boolean.class" zurück.


dies mal machen sollst.


```
model = new DefaultTableModel (title,0){
  public Class getColumnClass( int column ){
    if( column == 0 ) return Boolean.class;
    if( ...
  }
}
```


----------



## Louis2 (11. Aug 2005)

*Zu Problem 2:*

Nun habe ich meine zweite JTable, wähle paar Zeilen mit den CheckBoxen aus, klicke auf dem Button und nun müssen die Werte der ausgewählten Zeilen in dem Header der ersten JTable erscheinen.  
Ich habe Probleme das ganze in der ersten JTable anzeigen zu lassen. Wie kann ich es machen ?
Zweite Klasse (wo Einträge selektiert werden):

```
public class FieldsSelection extends JFrame implements ActionListener
{
      EmailClient main3;
      JTable table;
      Boolean isselected = new Boolean(false);
      private JButton adopt = new JButton("Adopt the settings");
      List listfields;
      int fieldslen;
      DefaultTableModel model;
      String resultTable;
                              
      public FieldsSelection(EmailClient emailclient)
      {
          .          
          this.main3 = emailclient;
          .
          select.add(adopt);
          adopt.addActionListener(main3);
          contentPane.add(select);
          
          String[] title = new String[]
          { 
            "Fields", "Selection" 
          }; 
          model = new DefaultTableModel (title,0)
          {
            public Class getColumnClass(int column) 
            { 
                if(column == 0) 
                    return String.class; 
                else 
                    return Boolean.class; 
            } 
          };
          table = new JTable(model);
          
          getContentPane().add(new JScrollPane(table), BorderLayout.SOUTH);
                              
          try
          {
            .
            .
            for (int i=0;i<fieldslen;i++) 
            { 
                String outlistfields = (String) listfields.get(i);
                model.addRow(new Object[] {outlistfields, isselected}); 
            }
          }
          catch(Exception e3) 
          {    
            e3.printStackTrace();
            JOptionPane.showMessageDialog(null, "Error: " + "\n" + e3.getMessage()); 
          }
      }
      
      public void actionPerformed(ActionEvent e) // Action Performed
      {
        Object action=e.getSource();
                
        if (action == adopt)
        {
           int len = table.getRowCount()-1; 
           List selectedfieldsList = new ArrayList();
           for (int i=0;i<len;i++) // Gehe aktuelle Tabelle durch 
           { 
                if ((Boolean) table.getModel().getValueAt(i, 1) == true) // Wenn Checkbox true
                {
                    String selectedfields = (String) table.getModel().getValueAt(i, 0); // Wert als String
                    selectedfieldsList.add(selectedfields); // Und in Liste speichern
                }
           } 
           int selectedfieldslen = selectedfieldsList.size();
           
           String[] titlenew = new String[selectedfieldslen]; // Anzahl der Werte bei denen es true war
           for (int j=0;j<selectedfieldslen;j++) 
           { 
                String resultListSelected = (String) selectedfieldsList.get(j);
                titlenew[j] = resultListSelected; // Füll das Array
           } 
           main3.NewSelectedDefaultTableModel(titlenew); // Nun soll irgendwie die aktualisierte JTable in Frame 1 erscheinen???
        }
      }
}
```

Erste Klasse:

```
public class EmailClient extends JFrame implements WindowListener, ActionListener
{
    .
    .
     public EmailClient() 
    {
        .
        .
        title = new String[] // So sieht sie beim laden aus
        { 
            "CustomerNo", "Firmenname", "E-Mail", "AuftragsNr.", "Komm.Nr.", "Gedruckt am", "Umsatzwert", "WE", "Zustand" 
        }; 
        model = new DefaultTableModel (title,0);        
        .
        .
        .
        for (int i = 0; i < comboinhalt.length; i++)
            combo.addItem(comboinhalt[i]);
            choice = (String) combo.getSelectedItem();
            getContentPane().add(combo, BorderLayout.WEST);
            final FieldsSelection main2 = new FieldsSelection(this);
            combo.addItemListener(new ItemListener()
        {
            //Action when combo value selected
            public void itemStateChanged(ItemEvent e) 
            {
                String resultauftrag=new String();
                selectedChoice = (JComboBox)e.getSource();
                choice = (String) selectedChoice.getSelectedItem();
                main2.setVisible(true);
                // JETZT MUSS DIE NEUE JTABLE von main2 (zweite Klasse) geladen werden.
```

Wie geht das ? Sowas wie 
	
	
	
	





```
main2.DefaultTableModel(main2.titlenew,0);
```
 ??


----------



## Louis2 (11. Aug 2005)

Hmm vielleicht ist die Lösung im ersten Frame eine Methode zu schreiben, die das neue Model für die JTable ausgibt... das ganze würde dann im zweiten Frame aufgerufen werden, nachdem die Header (titlenew) gesetzt wurden...
oder gibt es andere Möglichkeiten ?


----------



## Beni (11. Aug 2005)

Sorry, dass ich nicht geantwortet habe. Ich hab auf den Thread gedrückt, und dann irgendwie vergessen weiterzumachen...

Eigentlich sollte doch ein Aufruf von setColumnIdentifiers reichen. Die Identifier sind ja die Dinger, die als Titel angezeigt werden.


----------



## Louis2 (12. Aug 2005)

@Beni: Super, danke, genau sowas habe ich gebraucht :wink:


----------

