eigene Tabellenklasse - wie mache ich das richtig

MScalli

Erfahrenes Mitglied
Hi Leutz.
Ich habe eine Frage die eigentlich Java Basic ist.
Trotzdem bekomme ich es irgendwie nicht wirklich hin.

Ich möchte eine MyTable Klasse schreiben mit der ich eine Instanz einer JTable erzeugen kann und dann auch genau mit dieser weiter arbeiten kann.

Ich habe KEINE Frage zur Tabelle ansich.. Das funktioniert alles einwandfrei.

Hier mal ein Beispiel wie ich es bis jetzt mache.
Leider bekomme ich immer wieder Probleme da ich diese Klasse mehrmals gebrauche und ich glaube da wird immer wieder was überschrieben(obwohl ich ja eine neue Instanz erstelle)

Bspl. aufruf
Code:
			// Aufruf Panel mit Tabelle Kunden-Adressen
			String tmp_sql_string = "SELECT adr_lfd_num, adr_zeile1, adr_zeile2, adr_zeile3, adr_zeile4, adr_zeile5, adr_zeile6, adr_zeile7 FROM f_adr WHERE " +
									"adr_nr = '" + str_key + "' " +
									"AND adr_kz = 'K'";
			int[] arr_length = {50, 290, 290, 290, 290, 290, 290, 290};
			String[] arr_col_names = {"Lfd. Nr.", "adr_zeile1", "adr_zeile2", "adr_zeile3", "adr_zeile4", "adr_zeile5", "adr_zeile6", "adr_zeile7"};
			
			PanWithTable_Auftrag_Adr pwt = new PanWithTable_Auftrag_Adr("pack.V0100", "fillTextFieldsAAnschrift", tmp_sql_string, arr_col_names, arr_length, 970, 140, true);
			pan_table_adressen.add(pwt);
			pan_table_adressen.repaint();

und hier die Klasse mit einer JTabel die auf einem JPanel/JScrollPane liegt

Code:
import java.awt.Color;
import java.awt.Dimension;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.Vector;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

import pack.DBHandler;

/**
 * Diese Klasse erzeugt eine JTable auf einem JPanel.<br>
 * Ausserdem kann Sie eine Methode der Übergebenden Klasse aufrufen<br>
 *
 */
public class PanWithTable_Auftrag_Adr extends JPanel{

	private static final long serialVersionUID = -768633293737339371L;
	
	static JTable table;
	static DefaultTableModel model;
	private static String str_key1 = "";

	@SuppressWarnings("unchecked")

	public PanWithTable_Auftrag_Adr(	final String str_classname,
								final String str_method,
								String _sql_string, 
								final String[] _arr_column_names, 
								int[] _arr_length_columns,
								final int _width, 
								final int _height, 
								final boolean _chooseable){
		
	  Vector columnNames = new Vector();
      Vector data = new Vector();

      this.setSize(_width, _height);

      try
      {
    	  Connection con = DBHandler.getConnection();

          //  Read data from a table
          Statement stmt = con.createStatement();
          ResultSet rs = stmt.executeQuery( _sql_string );
          ResultSetMetaData md = rs.getMetaData();
          
          int columns = md.getColumnCount();

          //  Get column names
          for (int i = 1; i <= columns; i++){
              columnNames.addElement( _arr_column_names[i-1] );
          }
          
          //  Get row data
          while (rs.next()){
              Vector row = new Vector(columns);
  
              for (int i = 1; i <= columns; i++){
                  row.addElement( rs.getObject(i) );
              }
              data.addElement( row );
          }
  
          rs.close();
          stmt.close();
      }
      catch(Exception e){
    	  JOptionPane.showMessageDialog(null, "Exception: Klasse PanWithTable_Auftrag_Adr \nFehler beim Lesen der Datenbank");
          System.out.println( e );
      }

      // TableModel Sortierung geht von alleine!!
      model = new DefaultTableModel(data, columnNames) {
        private static final long serialVersionUID = -7946186467395546994L;

        public boolean isCellEditable(int row, int col) {
            	return false;
        }
      };
      
      table = new JTable(model);
      table.setSelectionBackground(new Color(255,255,0));
      TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
      table.setRowSorter(sorter);
      table.getTableHeader().setReorderingAllowed(false);
      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
      
      initColumn(table, _arr_length_columns);
      
      JScrollPane scrollPane = new JScrollPane(table);
      scrollPane.setPreferredSize(new Dimension(_width,_height - 5));
      add(scrollPane);
    
      table.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent e) {
				if(_chooseable == true){
					if ( e.getClickCount() == 2 ) { 
						System.out.println("Doppelklick");
						
						str_key1 = table.getValueAt(table.getSelectedRow(), 0).toString();

		            	// Aufruf der Übergebenen Klasse/Methode
		    			Class c;
						try {
							c = Class.forName(str_classname);
			    			Object object = c.newInstance();
			    			Method method = object.getClass().getMethod(str_method, new Class[] {});
			    			method.invoke(object, new Object [] {});
			    			
						} catch (Exception ex) {
							ex.printStackTrace();
						}
						
					}
				}
			}
	  });
    }
	  
	private void initColumn(final JTable table, int[] _width_array) {
        TableColumn column = null;
        
        for (int i = 0; i < _width_array.length; i++) {
            column = table.getColumnModel().getColumn(i);
            column.setPreferredWidth(_width_array[i]);
        }
	}
	public static String getKey1(){
		return str_key1;
	}
	public static JTable getTable(){
		return table;	
	}
	public static DefaultTableModel getModel(){
		return model;	
	}
}

Hat evtl. jemand ein Beispiel wie ich so eine Klasse aufbauen könnte.

Ich hoffe es lacht jetzt keiner^^ Aber irgendwie bekomme ich das nicht so hin wie ich das will, und ich habe es schon auf soviel verschiedene arten probiert.

Es müssen auch keine Daten oder sonst was gefüllt werden, oder sonstwas mit der Tabelle gemacht werden.
Einfach ein Beispiel wie man eine eigene Tabellen-Klasse erstellt und diese addet.
Denn ich bekomm immer grössere Probleme so wie ich es z.Z. mache

schon mal thx an alle die Paar Tipps und/oder bisschen Quellcode für mich haben

gruss
MScalli
 
Hallo,

was ist denn genau dein Problem mit deiner vorhandenen Klasse.

Wenn du eine Tabellen-Klasse möchtest, solltest du vielleicht auch erklären, wie in etwa die Klasse aussehen soll. Also was soll die Klasse können.


MFG

Sascha
 
Irgendwie glaub ich das immer etwas überschrieben wird.
Denn wenn ich die für jede Tabelle die ich brauche genau dieselbe Klasse Kopiere, umbenenne und dann benutze, dann geht alles immer einwandfrei.

Was die Klasse können muss..
Ja ok, wenn ich mal die grund-Klasse habe kann ich ja verschieden Konstruktoren benutzen.
Bis jetzt will ich beim Aufruf nur eine übergebene Methode der aufrufenden Klasse aufrufen. Das geht ja soweit(mittels reflection).
Und dann den gewählten(per Dopppelklick) Satz holen können.

Wie macht Ihr das denn so!
 
Irgendwie glaub ich das immer etwas überschrieben wird. Denn wenn ich die für jede Tabelle die ich brauche genau dieselbe Klasse Kopiere, umbenenne und dann benutze, dann geht alles immer einwandfrei.

Ohne mir jetzt wirklich den Code angeschaut zu haben: Die static Attribute und Methoden sehen suspekt aus.

Wie macht Ihr das denn so!

Ein eigenes Model auf Basis des javax.swing.table.TableModel Interface oder der abstrakten Klasse javax.swing.table.AbstractTableModel. Es gibt einfach keinen Grund JTable zu spezialisieren (ausser man will zwingend schlecht wartbaren Code produzieren).

Ansonsten gilt Grundlagentutorials lesen!
 
Zuletzt bearbeitet:
Also dann hol ich mal bisschen aus.

Mein Ziel ist es eine Klasse aufzurufen die mir eine JTable erstellt und ich mittels Doppelklick eine übergebene Methode aufrufen kann.
In dieser Methode brauche ich den key dieses Satzes( will ich über die Methode getKey1() holen)

d.h. ich übergebe meinen Klassennamen inkl. Package(brauch ich so wegen der Reflection), dann den Methodennamen, den SQL-String der die Tabelle füllen soll, ein int[] damit ich die breite der Zellen Steuern kann, und ein String[] um die Überschriften der Spalten setzten zu können, ausserdem die Breite und die Höhe die die Tabelle haben soll.

beim Doppelklick auf die Tabelle wird jetzt die Methode der Ursprünglichen Klasse aufgerufen, diese soll dann irgendwas mit dem gewählten Satz machen.
Bspl.

Code:
PanWithTable_Auftrag_Adr tab = new PanWithTable_Auftrag_Adr(.....);
....

und in der aufgerufenen Methode will ich dann etwas mit dem key machen

Code:
System.out.println(tab.getKey1());

und genau da ist das Problem.. den hier bekomme ich dann werte wie -1

dies Passiert aber nur wenn ich diese Klasse(PanWithTable_Auftrag_Adr) öfter aufrufe. Wenn ich z.B. die Klasse immer anderst benenne also z.b PanWithTable_Auftrag_Adr1 und PanWithTable_Auftrag_Adr2 dann geht alles ohne Probleme.

Ich will hier wirklich keine fertigen Lösungen oder so..
nur 1 Beispiel wie Ihr so etwas macht, oder wie man so etwas machen sollte.
Ich dachte eigentlich am anfang das das wie ich es probiert habe(mit ner Klasse die ein JPanel ist und eine Tabelle beeinhaltet) ziemlich gut ist, nur irgendwie geht das nicht so wie ich das will.

Auf keinen fall will ich anfangen für jede Tabelle ne extra klasse zu schreiben :(

Bin dankbar für jeden Tipp, link oder code die zeigen wie man so etwas lösen sollte/kann.
 
Mein Ziel ist es doch nur so etwas sauber zu programmieren um es immer wieder ohne Probleme benutzen zu können, es lesbarer zu machen(auch für andere), es "richtig" zu programmieren und Fehler gleich im vornherein gar nicht erst auftreten zu lassen.

Das Tutorial zu den Tabellen bringt mir leider nichts, denn ich habe mit JTable überhaupt keine Probleme^^

deswegen auch meine Überschrift
wie mache ich es RICHTIG

Wie ICH es bis jetzt mache sieht man ja im 1 Thread.
Evtl. ist das ja schon die richtige richtung! Was für änderungen wären dann angebracht
Es wäre halt schön zu wissen wie es leute machen die schon länger mit Java arbeiten.
Die evtl. kommende Probleme schon kennen und durch "saubere" Programmierung Fehlern schon vorweg den gar aus machen.

Ich will hier echt keine fertig ausprogrammierte Klasse oder so.. eher einen Bauplan.. wie könnte diese Klasse aussehen, was für Methoden brauche ich und was machen die(2-3Beispiele) , wie komme ich dann an den ausgewählten satz(beim Doppelklick ne set Methode?)

Ich habe dieses Thema bewusst bei Java Grundlagen gepostet weil es genau das ist was mir in diesem Fall Probleme bereitet.

gruss und THX im vorraus
MScalli
 
Noch ein letzter verzweifelter versuch^^

Mein Problem ist nicht die Tabelle sondern grundlegend der aufbau einer sauberen Klasse mit get und set methoden die in sich "geschlossen" und ohne viele static-variablen, methoden auskommt damit nicht irgendwas überschrieben wird(wie es bis jetzt ist glaub ich).

Ich habe mal ein ausführbares Beispiel erstellt und wollte Fragen.

1. Wie kann ich die Klasse PanWithTable verändern um sie immer wieder benutzen zu können.. für verschiedene aufrufende Klassen, Tabellen usw.(bis jetzt habe ich den Namen der Aufrufenden Klasse und eine Methode dieser Klasse als String übergeben und konnte so diese Methode per Reflection aufrufen. mit einer get Methode habe ich mir den Key des gewählten Satzes geholt und diesen einfach neu aus der Datenbank ausgelesen)

2. Ist mein ansatz so üblich/ sauber programmiert, oder macht IHR das irgendwie ganz anderst(wenn ja wie)

3. Wie kann ich in der Aufrufenden Klasse irgendwas anstossen(z.B. eine Methode) die dann z.B. den gewählten Satz bekommt/holt und irgendwas damit machen kann?


Schon mal vielen Dank an alle die es sich anschauen und versuchen mir dabei zu helfen.

gruss
MScalli


aufrufende Klasse JTableTest

Code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;


public class JTableTest extends JFrame{

	static JTextField tf1, tf2, tf3;
	
	JTableTest(){
		this.setSize(500, 500);
		this.setLayout(null);
		// **********************************************************************
		
		tf1 = new JTextField();
		tf1.setBounds(10, 10, 100, 20);
		this.add(tf1);
		
		tf2 = new JTextField();
		tf2.setBounds(10, 40, 100, 20);
		this.add(tf2);
		
		tf3 = new JTextField();
		tf3.setBounds(10, 70, 100, 20);
		this.add(tf3);
		
		JPanel pan = new JPanel();
		pan.setBounds(10, 100, 230, 220);
		this.add(pan);
		
		// Hier werden später ein Select-Befehl usw übergeben um die Tabelle aus der Datenbank zu erzeugen
		PanWithTable pan_tab = new PanWithTable();
		pan.add(pan_tab);
		
		
		// **********************************************************************
		this.setVisible(true);
	}
	
	public static void main(String[] args) {
		new JTableTest();
	}
}

Klasse PanWithTable die ein JPanel ist das eine Tabelle beeinhaltet und die ich allgemein benutzen will
Code:
import java.awt.Color;
import java.awt.Dimension;
import java.util.Vector;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class PanWithTable extends JPanel{

	private static final long serialVersionUID = -768633293737339371L;

	@SuppressWarnings("unchecked")

	public PanWithTable(){
		

      this.setSize(300, 200);

      // Testdaten --> wird normalerweise aus einer Datenbank gefüllt************
      Vector<String> rowOne = new Vector<String>();
      rowOne.addElement("Row1-Column1");
      rowOne.addElement("Row1-Column2");
      rowOne.addElement("Row1-Column3");
      
      Vector<String> rowTwo = new Vector<String>();
      rowTwo.addElement("Row2-Column1");
      rowTwo.addElement("Row2-Column2");
      rowTwo.addElement("Row2-Column3");
      
      Vector<Vector> rowData = new Vector<Vector>();
      rowData.addElement(rowOne);
      rowData.addElement(rowTwo);
      
      Vector<String> columnNames = new Vector<String>();
      columnNames.addElement("Column One");
      columnNames.addElement("Column Two");
      columnNames.addElement("Column Three");
      // Testdaten ENDE *********************************************************

      
      // TableModel Sortierung geht von alleine!!
      DefaultTableModel model = new DefaultTableModel(rowData, columnNames) {
        private static final long serialVersionUID = -7946186467395546994L;

        public boolean isCellEditable(int row, int col) {
            	return false;
        }
      };
      
      final JTable table = new JTable(model);
      table.setSelectionBackground(new Color(255,255,0));
      TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
      table.setRowSorter(sorter);
      table.getTableHeader().setReorderingAllowed(false);
      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
      
      JScrollPane scrollPane = new JScrollPane(table);
      scrollPane.setPreferredSize(new Dimension(225,100 - 5));
      add(scrollPane);
    
      table.addMouseListener(new java.awt.event.MouseAdapter() {
			public void mouseClicked(java.awt.event.MouseEvent e) {

				if ( e.getClickCount() == 2 ) { 
					System.out.println("Doppelklick");
					
					// Das es so geht ist klar. Aber es soll ja für mehrere  Klassen aufrufbar sein
					// und es sind mal mehr mal weniger TextFelder zu füllen oder sonst was mit
					// den Daten zu machen
					// Wie kann ich das bewerkstelligen !
					JTableTest.tf1.setText(table.getValueAt(table.getSelectedRow(), 0).toString());
					JTableTest.tf2.setText(table.getValueAt(table.getSelectedRow(), 1).toString());
					JTableTest.tf3.setText(table.getValueAt(table.getSelectedRow(), 2).toString());

				}
			}
	  });
    }
}
 
Ich denke, Reflection ist Overkill. Versuch es doch mal mit Interfaces, damit sollte alles machbar sein, was Du beschrieben hast.
 
Zurück