Java-Tipp 102: Fügen Sie mehrere JTable-Zelleneditoren pro Spalte hinzu

Standardmäßig können JTablenicht mehr als ein Editor pro Spalte verwendet werden. Eine Visual Basic-ähnliche Eigenschaftsseite ist eine Stelle, an der Sie mehr als einen Editor in einer Spalte benötigen würden. Glücklicherweise können Sie mit dem Klassendesign für JTabledie JTableFunktionalität um einen Zeileneditor mit minimalem Code erweitern.

Was ist ein TableCellEditor?

TableCellEditorObjekte definieren, wie Daten in JTableZellen bearbeitet werden. Das Konzept von a TableCellEditorwird in Java als Schnittstelle erfasst : javax.swing.table.TableCellEditor. Diese Schnittstelle definiert eine einzelne Methode, die eine Komponente zurückgibt. Die Methode wird JTableimmer dann aufgerufen, wenn JTablefestgestellt wird, dass eine bestimmte Zelle bearbeitet wird. Sobald die Methode eine Komponente zurückgibt, wird die Größe der Komponente so geändert, dass sie in die Tabellenzelle passt, und dann in der entsprechenden JTableZelle angezeigt .

Mit dieser Methode können Sie JTable.setDefaultEditor(Class, TableCellEditor)mehrere Editoren JTablebasierend auf der darin enthaltenen Datenelementklasse einrichten. JTableBerücksichtigt jedoch intern nur die Möglichkeit, dass eine Spalte nur eine Klasse enthält. Diese Annahme wird durch die Schnittstelle demonstriert javax.swing.table.AbstractTableModel, in der die Methode getColumnClass(int)definiert, dass eine bestimmte Spalte nur eine Klasse hat.

Glücklicherweise JTablewird die Methode verwendet getCellEditor(int, int), um a TableCellEditorfür eine bestimmte Zelle zu bestimmen . In diesem Tipp werde ich diese Methode überschreiben, um die Funktionalität zu erweitern und zu ermöglichen, dass TableCellEditors auf dem Zeilenindex basiert.

Wo speichern Sie die neuen Editoren für JTable?

Ich habe eine neue Klasse namens erstellt RowEditorModel, die im Grunde ein Wrapper um die Hashtable ist, die TableCellEditors enthält. Jeder Editor ist einem Integer-Objekt zugeordnet, das den Index der Zeile darstellt, für die der Editor verwendet werden soll.

Der Code für RowEditorModelist unten aufgeführt:

1 import javax.swing.table. *; 2 import java.util. *; 3 öffentliche Klasse RowEditorModel 4 {5 private Hashtable-Daten; 6 public RowEditorModel () 7 {8 data = new Hashtable (); 9} 10 public void addEditorForRow (int row, TableCellEditor e) 11 {12 data.put (neue Ganzzahl (row), e); 13} 14 public void removeEditorForRow (int row) 15 {16 data.remove (neue Ganzzahl (row)); 17} 18 public TableCellEditor getEditor (int row) 19 {20 return (TableCellEditor) data.get (new Integer (row)); 21} 22}

Benutzer registrieren neue Editoren bei der

addEditorForRow()

Methode in Zeile 10. Die

RowEditorModel

Außerdem kann der Benutzer einen Editor für eine Zeile löschen. Und schließlich gibt es in Zeile 18 einen Accessor, der einen Editor basierend auf einem Zeilenindex zurückgibt. Beachten Sie, dass die

RowEditorModel

verweist nicht auf a

JTable

in irgendeiner Weise. Die anderen Änderungen, die vorgenommen werden müssen, betreffen die

JTable

selbst. Unten finden Sie eine Codeliste für die neue Version von

JTable

, namens

JTableX

.

1 import javax.swing. *; 2 import javax.swing.table. *; 3 import java.util.Vector; 4 5 public class JTableX erweitert JTable 6 {7 protected RowEditorModel rm; 8 9 public JTableX () 10 {11 super (); 12 rm = null; 13} 14 15 public JTableX (TableModel tm) 16 {17 super (tm); 18 rm = null; 19} 20 21 public JTableX (TableModel tm, TableColumnModel cm) 22 {23 super (tm, cm); 24 rm = null; 25} 26 27 public JTableX (TableModel tm, TableColumnModel cm, 28 ListSelectionModel sm) 29 {30 super (tm, cm, sm); 31 rm = null; 32} 33 34 public JTableX (int Zeilen, int Spalten) 35 {36 super (Zeilen, Spalten); 37 rm = null; 38} 39 40 public JTableX (final Vector rowData, final Vector columnNames) 41 {42 super (rowData, columnNames); 43 rm = null; 44} 45 46 public JTableX (endgültiges Objekt [] [] rowData, endgültiges Objekt [] colNames) 47 {48 super (rowData, colNames); 49 rm = null;50} 51 52 // neuer Konstruktor 53 public JTableX (TableModel tm, RowEditorModel rm) 54 {55 super (tm, null, null); 56 this.rm = rm; 57} 58 59 public void setRowEditorModel (RowEditorModel rm) 60 {61 this.rm = rm; 62} 63 64 public RowEditorModel getRowEditorModel () 65 {66 return rm; 67} 68 69 public TableCellEditor getCellEditor (int row, int col) 70 {71 TableCellEditor tmpEditor = null; 72 if (rm! = Null) 73 tmpEditor = rm.getEditor (Zeile); 74 if (tmpEditor! = Null) 75 return tmpEditor; 76 return super.getCellEditor (row, col); 77} 78}int col) 70 {71 TableCellEditor tmpEditor = null; 72 if (rm! = Null) 73 tmpEditor = rm.getEditor (Zeile); 74 if (tmpEditor! = Null) 75 return tmpEditor; 76 return super.getCellEditor (row, col); 77} 78}int col) 70 {71 TableCellEditor tmpEditor = null; 72 if (rm! = Null) 73 tmpEditor = rm.getEditor (Zeile); 74 if (tmpEditor! = Null) 75 return tmpEditor; 76 return super.getCellEditor (row, col); 77} 78}

Der größte Teil des Codes in der obigen Liste besteht aus Konstruktoraufrufen. Ich habe alle Konstruktoren eingeschlossen, die JTabledefinieren, sowie einen zusätzlichen, mit dem der Benutzer einen JTablemit einem zugeordneten erstellen kann RowEditorModel(Zeilen 53-57). Optional können Sie das hinzufügen, RowEditorModelnachdem das erstellt wurde JTable. Im Allgemeinen möchten Sie das RowEditorModelentweder mithilfe des neuen Konstruktors oder der setRowEditorModelMethode zuweisen , bevor das JTableangezeigt wird.

Der größte Teil der Aktion wird in der überschriebenen Methode ausgeführt getCellEditor. Wenn JTableXfestgestellt wird, dass ein TableCellEditorfür eine Zelle benötigt wird, überprüft der Code die RowEditorModel(Zeile 72 und 73), um zuerst die richtige zu bestimmen TableCellEditor. Wenn no von zurückgegeben TableCellEditorwird RowEditorModel, verwendet die Methode standardmäßig die Version von getCellEditorin der Basisklasse JTable.

Ich habe ein kleines Beispielprogramm beigefügt, das die Verwendung des neuen Programms demonstriert JTableX. Die Eigenschaftenseiten sehen folgendermaßen aus:

Hier ist der Code:

import javax.swing. *; import java.awt. *; import java.awt.event. *; import javax.swing.table. *; import javax.swing.border. *; öffentliche Klasse PropPageTest erweitert JPanel {private JComboBox b; private JTableX-Tabelle; privates DefaultTableModel-Modell; private String [] col_names = {"Name", "Wert"}; private String [] anchor_values ​​= {"CENTER", "NORTH", "NORTHEAST", "EAST", "SOUTHEAST", "SOUTH", "SOUTHWEST", "WEST", "NORTHWEST"}; private String [] fill_values ​​= {"NONE", "HORIZONTAL", "VERTICAL", "BOTH"}; private void createGUI () {setLayout (neues BorderLayout ()); setBorder (BorderFactory.createBevelBorder (BevelBorder.LOWERED)); b = neue JComboBox (); model = new DefaultTableModel (col_names,12) {public String [] prop_names = {"Name", "Anchor", "Fill", "GridHeight", "GridWidth", "GridX", "GridY", "Insets", "Ipadx", "Ipady", "WeightX", "WeightY"}; öffentliches Objekt getValueAt (int row, int col) {if (col == 0) return prop_names [row]; return super.getValueAt (row, col); } public boolean isCellEditable (int row, int col) {if (col == 0) return false; return true; }}; Tabelle = neues JTableX (Modell); table.setRowSelectionAllowed (false); table.setColumnSelectionAllowed (false); // ein RowEditorModel erstellen ... dies wird verwendet, um die zusätzlichen // Informationen zu speichern, die für den Umgang mit zeilenspezifischen Editoren erforderlich sind RowEditorModel rm = new RowEditorModel (); // JTableX mitteilen, welches RowEditorModel wir verwenden table.setRowEditorModel (rm);// eine neue JComboBox und einen neuen DefaultCellEditor erstellen, die in der // JTableX-Spalte verwendet werden sollen JComboBox cb = new JComboBox (anchor_values); DefaultCellEditor ed = neuer DefaultCellEditor (cb); // weise das RowEditorModel an, ed für Zeile 1 zu verwenden rm.addEditorForRow (1, ed); // Erstelle eine neue JComboBox und einen neuen Editor für eine andere Zeile cb = new JComboBox (fill_values); ed = neuer DefaultCellEditor (cb); // informiere den RowEditorMode über die Situation rm.addEditorForRow (2, ed); add (b, BorderLayout.NORTH); add (Tabelle, BorderLayout.CENTER); } public PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = neuer JFrame ("Test"); f.setSize (300, 350); f.getContentPane (). add (neuer PropPageTest (), BorderLayout.CENTER); f.addWindowListener (neuer WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (true); }}}}}}}}}}}}}}// weise das RowEditorModel an, ed für Zeile 1 zu verwenden rm.addEditorForRow (1, ed); // Erstelle eine neue JComboBox und einen neuen Editor für eine andere Zeile cb = new JComboBox (fill_values); ed = neuer DefaultCellEditor (cb); // informiere den RowEditorMode über die Situation rm.addEditorForRow (2, ed); add (b, BorderLayout.NORTH); add (Tabelle, BorderLayout.CENTER); } public PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = neuer JFrame ("Test"); f.setSize (300, 350); f.getContentPane (). add (neuer PropPageTest (), BorderLayout.CENTER); f.addWindowListener (neuer WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (true); }}// weise das RowEditorModel an, ed für Zeile 1 zu verwenden rm.addEditorForRow (1, ed); // Erstelle eine neue JComboBox und einen neuen Editor für eine andere Zeile cb = new JComboBox (fill_values); ed = neuer DefaultCellEditor (cb); // informiere den RowEditorMode über die Situation rm.addEditorForRow (2, ed); add (b, BorderLayout.NORTH); add (Tabelle, BorderLayout.CENTER); } public PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = neuer JFrame ("Test"); f.setSize (300, 350); f.getContentPane (). add (neuer PropPageTest (), BorderLayout.CENTER); f.addWindowListener (neuer WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (true); }}// informiere den RowEditorMode über die Situation rm.addEditorForRow (2, ed); add (b, BorderLayout.NORTH); add (Tabelle, BorderLayout.CENTER); } public PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = neuer JFrame ("Test"); f.setSize (300, 350); f.getContentPane (). add (neuer PropPageTest (), BorderLayout.CENTER); f.addWindowListener (neuer WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (true); }}// informiere den RowEditorMode über die Situation rm.addEditorForRow (2, ed); add (b, BorderLayout.NORTH); add (Tabelle, BorderLayout.CENTER); } public PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = neuer JFrame ("Test"); f.setSize (300, 350); f.getContentPane (). add (neuer PropPageTest (), BorderLayout.CENTER); f.addWindowListener (neuer WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (true); }}addWindowListener (neuer WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (true); }}addWindowListener (neuer WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (true); }}

Fazit

JTableist eine flexible und gut geschriebene Komponente, unterstützt jedoch standardmäßig nicht die Verwendung mehrerer TableCellEditors pro Spalte. Da die Swing-Designer JTableso flexibel geschrieben haben, konnte ich es mit wenig Code erweitern und eine neue Version erstellen JTable, die mehrere Editoren pro Spalte unterstützt.

Tony Colston programmiert seit 1991 professionell, beginnend mit der Entwicklung von Geldautomaten und Debitkarten. Heute arbeitet er für Buckman Labs in Tennessee, wo er seine Tage damit verbringt, sich neue Wege auszudenken, um Berichte in Echtzeit über das Web zu verteilen. Zu seinen Hobbys zählen Basketball (schlecht) und Quake III und Diablo II. Wenn er kein Nerd ist, verbringt er seine Zeit damit, seine Frau Beth anzubeten, die seltsamerweise Nerds für cool hält. Sie können seine Webseite unter //members.xoom.com/Tonetheman überprüfen

Erfahren Sie mehr über dieses Thema

  • Weitere Informationen zur Verwendung von JTable finden Sie unter

    //web2.java.sun.com/docs/books/tutorial/uiswing/components/table.html

  • Graphic Java 2Mastering the JFC, Band 2 Swing, 3. Auflage, David M. Geary ( Prentice Hall, März 1999)

    //www1.fatbrain.com/asp/bookinfo/bookinfo.asp?theisbn=0130796670

  • Kernklassen der Java Foundation, Kim Topley ( Prentice Hall Computer Books, Juni 1998)

    //www1.fatbrain.com/asp/bookinfo/bookinfo.asp?theisbn=0130803014

  • Lesen Sie diese anderen JavaWorld- Artikel zu Swing und JTable:
    • "Making the Forum Swing, Teil 1", Michael Shoffner ( JavaWorld, Sept. 1998)

      //www.javaworld.com/javaworld/jw-09-1998/jw-09-step.html

    • " Machen Sie sich bereit zum Schwingen (1.0)", Kane Scarlett ( JavaWorld, März 1998)

      //www.javaworld.com/jw-03-1998/jw-03-swinggui.html

    • "Java-Tipp 77Eine Funktion zum Kopieren und Einfügen zwischen JTables und Excel von Swing aktivieren", Ashok Banerjee und Jignesh Mehtra ( JavaWorld, April 2000)

      //www.javaworld.com/javaworld/javatips/jw-javatip77.html

    • "Java-Tipp 100JFileChooser einen Verlaufsmechanismus hinzufügen", Klaus Berg ( JavaWorld, August 2000)

      //www.javaworld.com/javaworld/javatips/jw-javatip100.html

  • Zeigen Sie alle vorherigen Java-Tipps an und senden Sie Ihre eigenen

    //www.javaworld.com/javatips/jw-javatips.index.html

Diese Geschichte "Java-Tipp 102: Hinzufügen mehrerer JTable-Zelleneditoren pro Spalte" wurde ursprünglich von JavaWorld veröffentlicht.