Tip 102 Java: Tambahkan beberapa editor sel JTable per kolom

Secara default JTabletidak menawarkan kemampuan untuk memiliki lebih dari satu editor per kolom. Halaman properti seperti Visual Basic adalah satu tempat di mana Anda akan membutuhkan lebih dari satu editor dalam satu kolom. Untungnya, desain kelas untuk JTablememungkinkan Anda memperluas JTablefungsionalitas untuk menyertakan editor per baris dengan kode minimal.

Apa itu TableCellEditor?

TableCellEditorobjek menentukan bagaimana data dalam JTablesel diedit. Konsep TableCellEditorditangkap di Jawa sebagai interface: javax.swing.table.TableCellEditor. Antarmuka tersebut mendefinisikan metode tunggal yang mengembalikan sebuah Komponen. Metode ini dipanggil oleh JTablesetiap kali JTablemenentukan bahwa sel tertentu sedang diedit. Setelah metode mengembalikan Komponen, Komponen diubah ukurannya agar pas dengan sel tabel dan kemudian ditampilkan ke JTablesel yang sesuai .

Anda dapat menggunakan metode ini JTable.setDefaultEditor(Class, TableCellEditor)untuk menyiapkan beberapa editor JTableberdasarkan kelas item data yang ada di dalamnya. Namun, secara internal, JTablehanya mempertimbangkan kemungkinan bahwa kolom hanya akan menampung satu kelas. Asumsi tersebut ditunjukkan oleh antarmuka javax.swing.table.AbstractTableModel, di mana metode tersebut getColumnClass(int)mendefinisikan bahwa kolom tertentu hanya memiliki satu kelas.

Untungnya, JTablemenggunakan metode getCellEditor(int, int)untuk menentukan a TableCellEditoruntuk sel tertentu. Dalam tip ini, saya akan mengganti metode itu untuk memperluas fungsionalitas dan memungkinkan TableCellEditoruntuk didasarkan pada indeks baris.

Di mana Anda menyimpan editor baru untuk JTable?

Saya membuat kelas baru yang disebut RowEditorModelyang pada dasarnya pembungkus di sekitar Hashtable yang menampung TableCellEditors. Setiap editor dikaitkan dengan objek Integer yang mewakili indeks baris yang editornya harus digunakan.

Kode untuk RowEditorModeltercantum di bawah ini:

1 impor javax.swing.table. *; 2 import java.util. *; 3 kelas publik RowEditorModel 4 {5 data Hashtable pribadi; 6 publik RowEditorModel () 7 {8 data = baru Hashtable (); 9} 10 public void addEditorForRow (baris int, TableCellEditor e) 11 {12 data.put (new Integer (row), e); 13} 14 public void removeEditorForRow (int baris) 15 {16 data.remove (new Integer (row)); 17} 18 publik TableCellEditor getEditor (int baris) 19 {20 kembali (TableCellEditor) data.get (baru Integer (baris)); 21} 22}

Pengguna mendaftarkan editor baru dengan

addEditorForRow()

metode pada baris 10. The

RowEditorModel

juga memungkinkan pengguna untuk menghapus editor untuk satu baris. Dan terakhir pada baris 18 ada aksesor yang mengembalikan editor berdasarkan indeks baris. Perhatikan bahwa

RowEditorModel

tidak mengacu pada a

JTable

dengan cara apapun. Perubahan lain yang harus dilakukan adalah pada

JTable

diri. Di bawah ini adalah daftar kode untuk versi baru

JTable

, dipanggil

JTableX

.

1 impor javax.swing. *; 2 impor javax.swing.table. *; 3 impor java.util.Vector; 4 5 kelas publik JTableX memperluas JTable 6 {7 RowEditorModel rm yang dilindungi; 8 9 publik JTableX () 10 {11 super (); 12 rm = nol; 13} 14 15 publik JTableX (TableModel tm) 16 {17 super (tm); 18 rm = nol; 19} 20 21 JTableX publik (TableModel tm, TableColumnModel cm) 22 {23 super (tm, cm); 24 rm = nol; 25} 26 27 JTableX publik (TableModel tm, TableColumnModel cm, 28 ListSelectionModel sm) 29 {30 super (tm, cm, sm); 31 rm = nol; 32} 33 34 JTableX publik (baris int, kolom int) 35 {36 super (baris, kolom); 37 rm = nol; 38} 39 40 JTableX publik (Vector terakhir rowData, Vektor akhir nama kolom) 41 {42 super (rowData, columnNames); 43 rm = nol; 44} 45 46 JTableX publik (Objek akhir [] [] rowData, Objek akhir [] colNames) 47 {48 super (rowData, colNames); 49 rm = nol;50} 51 52 // konstruktor baru 53 JTableX publik (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 publik RowEditorModel getRowEditorModel () 65 {66 return rm; 67} 68 69 publik TableCellEditor getCellEditor (int baris, int col) 70 {71 TableCellEditor tmpEditor = null; 72 jika (rm! = Null) 73 tmpEditor = rm.getEditor (baris); 74 if (tmpEditor! = Null) 75 return tmpEditor; 76 kembali super.getCellEditor (row, col); 77} 78}int col) 70 {71 TableCellEditor tmpEditor = null; 72 jika (rm! = Null) 73 tmpEditor = rm.getEditor (baris); 74 if (tmpEditor! = Null) 75 return tmpEditor; 76 kembali super.getCellEditor (row, col); 77} 78}int col) 70 {71 TableCellEditor tmpEditor = null; 72 jika (rm! = Null) 73 tmpEditor = rm.getEditor (baris); 74 if (tmpEditor! = Null) 75 return tmpEditor; 76 kembali super.getCellEditor (row, col); 77} 78}

Sebagian besar kode dalam daftar di atas terdiri dari panggilan konstruktor. Saya telah menyertakan semua konstruktor yang JTablemendefinisikan, ditambah satu tambahan yang akan membiarkan pengguna membuat JTabledengan yang terkait RowEditorModel(baris 53-57). Secara opsional, Anda dapat menambahkan RowEditorModelsetelah selesai JTabledibangun. Secara umum, Anda ingin menetapkan RowEditorModel, baik dengan menggunakan konstruktor baru atau setRowEditorModelmetode, sebelum JTableditampilkan.

Sebagian besar tindakan terjadi dalam metode yang diganti getCellEditor. Ketika JTableXmenentukan bahwa TableCellEditoruntuk sel diperlukan, kode kemudian akan memeriksa RowEditorModel(baris 72 dan 73) untuk menentukan pertama yang benar TableCellEditor. Jika tidak ada TableCellEditoryang dikembalikan dari RowEditorModel, maka metode default ke versi getCellEditordi kelas dasar, yaitu JTable.

Saya telah menyertakan program contoh kecil yang menunjukkan cara menggunakan yang baru JTableX. Halaman properti terlihat seperti berikut:

Ini kodenya:

import javax.swing. *; import java.awt. *; import java.awt.event. *; import javax.swing.table. *; import javax.swing.border. *; public class PropPageTest extends JPanel {private JComboBox b; tabel JTableX pribadi; model DefaultTableModel pribadi; Private String [] col_names = {"Name", "Value"}; private String [] anchor_values ​​= {"CENTER", "NORTH", "NORTHEAST", "EAST", "SOUTHEAST", "SOUTH", "SOUTHWEST", "WEST", "NORTHWEST"}; String pribadi [] fill_values ​​= {"NONE", "HORIZONTAL", "VERTICAL", "BOTH"}; private void createGUI () {setLayout (new BorderLayout ()); setBorder (BorderFactory.createBevelBorder (BevelBorder.LOWERED)); b = baru JComboBox (); model = new DefaultTableModel (col_names,12) {public String [] prop_names = {"Name", "Anchor", "Fill", "GridHeight", "GridWidth", "GridX", "GridY", "Insets", "Ipadx", "Ipady", "WeightX", "WeightY"}; Objek publik getValueAt (baris int, kolom int) {if (col == 0) return prop_names [baris]; return super.getValueAt (row, col); } public boolean isCellEditable (int row, int col) {if (col == 0) return false; kembali benar; }}; table = new JTableX (model); table.setRowSelectionAllowed (false); table.setColumnSelectionAllowed (false); // buat RowEditorModel ... ini digunakan untuk menyimpan // informasi tambahan yang diperlukan untuk menangani editor khusus baris RowEditorModel rm = new RowEditorModel (); // beri tahu JTableX RowEditorModel mana yang kita gunakan table.setRowEditorModel (rm);// buat JComboBox dan DefaultCellEditor baru untuk digunakan di // kolom JTableX JComboBox cb = new JComboBox (anchor_values); DefaultCellEditor ed = DefaultCellEditor baru (cb); // beri tahu RowEditorModel untuk menggunakan ed untuk baris 1 rm.addEditorForRow (1, ed); // buat JComboBox baru dan editor untuk baris berbeda cb = new JComboBox (fill_values); ed = new DefaultCellEditor (cb); // beri tahu RowEditorMode tentang situasi rm.addEditorForRow (2, ed); tambahkan (b, BorderLayout.NORTH); tambahkan (tabel, BorderLayout.CENTER); } publik PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = new JFrame ("test"); f. setSize (300.350); f.getContentPane (). add (baru PropPageTest (), BorderLayout.CENTER); f.addWindowListener (new WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (benar); }}}}}}}}}}}}}}// beri tahu RowEditorModel untuk menggunakan ed untuk baris 1 rm.addEditorForRow (1, ed); // buat JComboBox baru dan editor untuk baris berbeda cb = new JComboBox (fill_values); ed = new DefaultCellEditor (cb); // beri tahu RowEditorMode tentang situasi rm.addEditorForRow (2, ed); tambahkan (b, BorderLayout.NORTH); tambahkan (tabel, BorderLayout.CENTER); } publik PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = new JFrame ("test"); f. setSize (300.350); f.getContentPane (). add (baru PropPageTest (), BorderLayout.CENTER); f.addWindowListener (new WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (benar); }}// beri tahu RowEditorModel untuk menggunakan ed untuk baris 1 rm.addEditorForRow (1, ed); // buat JComboBox baru dan editor untuk baris berbeda cb = new JComboBox (fill_values); ed = new DefaultCellEditor (cb); // beri tahu RowEditorMode tentang situasi rm.addEditorForRow (2, ed); tambahkan (b, BorderLayout.NORTH); tambahkan (tabel, BorderLayout.CENTER); } publik PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = new JFrame ("test"); f. setSize (300.350); f.getContentPane (). add (baru PropPageTest (), BorderLayout.CENTER); f.addWindowListener (new WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (benar); }}// beri tahu RowEditorMode tentang situasi rm.addEditorForRow (2, ed); tambahkan (b, BorderLayout.NORTH); tambahkan (tabel, BorderLayout.CENTER); } publik PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = new JFrame ("test"); f. setSize (300.350); f.getContentPane (). add (baru PropPageTest (), BorderLayout.CENTER); f.addWindowListener (new WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (benar); }}// beri tahu RowEditorMode tentang situasi rm.addEditorForRow (2, ed); tambahkan (b, BorderLayout.NORTH); tambahkan (tabel, BorderLayout.CENTER); } publik PropPageTest () {createGUI (); } public static void main (String [] args) {JFrame f = new JFrame ("test"); f. setSize (300.350); f.getContentPane (). add (baru PropPageTest (), BorderLayout.CENTER); f.addWindowListener (new WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (benar); }}addWindowListener (new WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (benar); }}addWindowListener (new WindowAdapter () {public void windowClosing (WindowEvent e) {System.exit (0);}}); f.setVisible (benar); }}

Kesimpulan

JTableadalah komponen yang fleksibel dan ditulis dengan baik tetapi tidak, secara default, mendukung penggunaan beberapa TableCellEditors per kolom. Karena desainer Swing menulis JTabledengan fleksibilitas seperti itu, saya dapat mengembangkannya dengan sedikit kode dan membuat versi baru JTableyang mendukung banyak editor per kolom.

Tony Colston telah memprogram secara profesional sejak 1991, dimulai dengan pengembangan ATM dan kartu debit. Dia sekarang bekerja untuk Buckman Labs yang berbasis di Tennessee, tempat dia menghabiskan hari-harinya memikirkan cara baru untuk mendistribusikan laporan secara realtime melalui Web. Hobinya termasuk bermain bola basket (buruk), dan bermain Quake III dan Diablo II. Ketika dia bukan seorang kutu buku, dia menghabiskan waktunya untuk memuja istrinya Beth yang, anehnya, menganggap kutu buku itu keren. Anda dapat melihat halaman webnya di //members.xoom.com/Tonetheman

Pelajari lebih lanjut tentang topik ini

  • Untuk informasi lebih lanjut tentang cara menggunakan JTable, baca

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

  • Grafis Java 2Mastering the JFC, Volume 2 Swing, Edisi Ketiga, David M.Geary ( Prentice Hall, Maret 1999)

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

  • Kelas Core Java Foundation, Kim Topley ( Buku Komputer Prentice Hall, Juni 1998)

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

  • Lihat artikel JavaWorld lainnya tentang Swing dan JTable:
    • "Making the Forum Swing, Bagian 1," Michael Shoffner ( JavaWorld, September 1998)

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

    • "Get Ready to Swing (1.0)," Kane Scarlett ( JavaWorld, Maret 1998)

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

    • "Java Tip 77Aktifkan Fungsi Salin dan Tempel Antara JTables dan Excel Swing," Ashok Banerjee dan Jignesh Mehtra ( JavaWorld, April 2000)

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

    • "Java Tip 100Tambahkan Mekanisme Sejarah ke JFileChooser," Klaus Berg ( JavaWorld, Agustus 2000)

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

  • Lihat semua Tips Java sebelumnya dan kirimkan Tips Anda sendiri

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

Artikel ini, "Tip Java 102: Tambahkan beberapa editor sel JTable per kolom", awalnya diterbitkan oleh JavaWorld.