Tables(三)

來源:互聯網
上載者:User
18.5 JTableHeader類

每一個JTableHeader執行個體表示所有不同列的頭集合中的一個。JTableHeader對象集合放置在JScrollPane中列頭視圖中。

我們很少需要直接使用JTableHeader。然而我們可以配置列頭的某些特徵。

18.5.1 建立JTableHeader

JTableHeader有兩個屬性。一個使用預設的TableColumnModel,而另一個需要顯式指定模型。

public JTableHeader()JComponent headerComponent = new JTableHeader()public JTableHeader(TableColumnModel columnModel)JComponent headerComponent = new JTableHeader(aColumnModel)

18.5.2 JTableHeader屬性

如表18-11所示,JTableHeader有十個不同的屬性。這些屬性可以使得我們配置使用者可以通過特定的列頭做什麼或是列頭如何顯示。

18.5.3 在表格頭中使用工具提示

預設情況下,如果我們為表格頭設定工具提示,所有的列頭都會共用相同的工具提示文本。要為特定的列指定工具提示文本,我們需要建立或是擷取渲染器,然後為渲染器設定工具提示。對於單個的單元也是如些。圖18-12顯示了這種定製結果顯示的樣子。

圖18-12中定製的源碼顯示在列表18-13中。除非我們在前面設定了列頭,並沒有必要首先檢測特定列的頭是null。

JLabel headerRenderer = new DefaultTableCellRenderer();String columnName = table.getModel().getColumnName(0);headerRenderer.setText(columnName);headerRenderer.setToolTipText("Wave");TableColumnModel columnModel = table.getColumnModel();TableColumn englishColumn = columnModel.getColumn(0);englishColumn.setHeaderRenderer((TableCellRenderer)headerRenderer);

18.5.4 自訂JTableHeader觀感

JTableHeaderUIResource相關屬性的可用集合顯示在表18-12中。五個屬性用於控制頭渲染器的顏色,字型與邊框。

18.6 編輯表格單元

編輯JTable單元與編輯JTree單元基本上是相同的。事實上,預設的表格單元編輯器,DefaultCellEditor,同時實現了TableCellEditor與TreeCellEditor介面,從而使得我們可以為表格與樹使用相同的編輯器。

點擊可編輯器的單元將會使得單元處理架構模式。(所需要的點擊次數依賴於編輯器的類型。)所有單元的預設編輯器是JTextField。儘管這對於許多資料類型可以工作得很好,但是對於其他的許多資料類型卻並不合適。所以,我們或者不支援非文本資訊的編輯或者是為我們的JTable設定特殊的編輯器。對於JTable,我們可以為一個特定的類類型或是列註冊一個編輯器。然後,當表格在多個相應類型的單元上運行時,則會使用所需要的編輯器。

注意,當沒有安裝特殊的編輯器時,則會使用JTextField,儘管他對於內容並不合適。

18.6.1 TableCellEditor介面與DefaultCellEditor類

TableCellEditor介面定義了JTable擷取編輯器所必須的方法。TableCellEditor的參數列表與TableCellRenderer相同,所不同的是hasFocused參數。因為單元正在被編輯,已知他已經具有輸入焦點。

public interface TableCellEditor extends CellEditor {  public Component getTableCellEditorComponent(JTable table, Object value,    boolean isSelected, int row, int column);}

正如第17章所描述的,DefaultCellEditor提供了介面的實現。他提供了JTextField作為一個編輯器,JCheckBox作為另一個編輯器,而JComboBox作為第三個編輯器。

如表格18-13所示,在大多數情況下,預設編輯器為JTextField。如果單中繼資料可以由一個字串轉換而成或是轉換成一個字串,類提供了一個具有String參數的建構函式,編輯器提供了資料的文本表示作為初始編輯值。然後我們可以編輯內容。

18.6.2 建立一個簡單的單元編輯器

作為修改JTable中非String單元的簡單樣本,我們可以為使用者提供一個固定的顏色選擇集合。然後當使用者選擇顏色時,我們可以向表格模型返回相應的Color值。DefaultCellEditor為這種情況提供了一個JComboBox。在配置JComboBox的ListCellRenderer正確的顯示顏色之後,我們就會有一個TableCellEditor用於選擇顏色。圖18-13顯示了可能顯示結果。

提示,任何時候我們都可以重新定義所有的選項,我們可以通過DefaultCellEditor將JComboBox作為我們的編輯器。

列表18-14顯示了表示了圖18-13中所示的用於Color列事件的TableCellRenderer類以及JComboBox TableCellEditor的ListCellRenderer。由於這兩個渲染器組件的相似性,他們的定義被組合在一個類中。

package swingstudy.ch18; import java.awt.Color;import java.awt.Component; import javax.swing.DefaultListCellRenderer;import javax.swing.JLabel;import javax.swing.JList;import javax.swing.JTable;import javax.swing.ListCellRenderer;import javax.swing.table.DefaultTableCellRenderer;import javax.swing.table.TableCellRenderer; import swingstudy.ch04.DiamondIcon; public class ComboTableCellRenderer implements ListCellRenderer,TableCellRenderer { DefaultListCellRenderer listRenderer = new DefaultListCellRenderer();DefaultTableCellRenderer tableRenderer = new DefaultTableCellRenderer(); public void configureRenderer(JLabel renderer, Object value) {if((value != null) && (value instanceof Color)) {renderer.setIcon(new DiamondIcon((Color)value));renderer.setText("");}else {renderer.setIcon(null);renderer.setText((String)value);}}@Overridepublic Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) {// TODO Auto-generated method stubtableRenderer = (DefaultTableCellRenderer)tableRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);configureRenderer(tableRenderer, value);return tableRenderer;} @Overridepublic Component getListCellRendererComponent(JList list, Object value,int index, boolean isSelected, boolean cellHasFocus) {// TODO Auto-generated method stublistRenderer = (DefaultListCellRenderer)listRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);configureRenderer(listRenderer, value);return listRenderer;} }為了示範新的組合渲染器的使用以及顯示一個簡單的表格單元編輯器,顯示在列表18-15中的程式建立了一個資料模型,其中一個列為Color。在兩次安裝渲染器並且設定表格單元編輯器以後,就可以顯示表格並且Color可以被編輯。package swingstudy.ch18; import java.awt.BorderLayout;import java.awt.Color;import java.awt.EventQueue; import javax.swing.DefaultCellEditor;import javax.swing.JComboBox;import javax.swing.JFrame;import javax.swing.JScrollPane;import javax.swing.JTable;import javax.swing.table.TableCellEditor;import javax.swing.table.TableColumn;import javax.swing.table.TableModel; public class EditableColorColumn { /** * @param args */public static void main(String[] args) {// TODO Auto-generated method stub Runnable runner = new Runnable() {public void run() {Color choices[] = {Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};ComboTableCellRenderer renderer = new ComboTableCellRenderer();JComboBox comboBox = new JComboBox(choices);comboBox.setRenderer(renderer);TableCellEditor editor = new DefaultCellEditor(comboBox); JFrame frame = new JFrame("Editable Color Table");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);TableModel model = new ColorTableModel();JTable table = new JTable(model); TableColumn column = table.getColumnModel().getColumn(3);column.setCellRenderer(renderer);column.setCellEditor(editor); JScrollPane scrollPane = new JScrollPane(table);frame.add(scrollPane, BorderLayout.CENTER);frame.setSize(400, 150);frame.setVisible(true);}};EventQueue.invokeLater(runner);} }

列表18-16顯示在這個樣本以及下個樣本中所用的表格模型。

package swingstudy.ch18; import java.awt.BorderLayout;import java.awt.Color;import java.awt.EventQueue; import javax.swing.DefaultCellEditor;import javax.swing.JComboBox;import javax.swing.JFrame;import javax.swing.JScrollPane;import javax.swing.JTable;import javax.swing.table.TableCellEditor;import javax.swing.table.TableColumn;import javax.swing.table.TableModel; public class EditableColorColumn { /** * @param args */public static void main(String[] args) {// TODO Auto-generated method stub Runnable runner = new Runnable() {public void run() {Color choices[] = {Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};ComboTableCellRenderer renderer = new ComboTableCellRenderer();JComboBox comboBox = new JComboBox(choices);comboBox.setRenderer(renderer);TableCellEditor editor = new DefaultCellEditor(comboBox); JFrame frame = new JFrame("Editable Color Table");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);TableModel model = new ColorTableModel();JTable table = new JTable(model); TableColumn column = table.getColumnModel().getColumn(3);column.setCellRenderer(renderer);column.setCellEditor(editor); JScrollPane scrollPane = new JScrollPane(table);frame.add(scrollPane, BorderLayout.CENTER);frame.setSize(400, 150);frame.setVisible(true);}};EventQueue.invokeLater(runner);} }

18.6.3 建立複雜的單元編輯器

儘管前面的例子示範了如何以列表框TableCellEditor的方向使用者提供一個確定的選項集合,但是提供一個JColorChooser作為選項似乎是更好的選擇(至少,在顏色選擇中是如此)。當定義我們自己的TableCellEditor時,我們必須實現單一的TableCellEditor方法來獲得相應的組件。我們必須同時實現CellEditor的七個方法,因為他們管理並通知一個CellEditorListener對象列表,同時控制一個單元何時可以編輯。以一個AbstractCellEditor子類作為起點會使得定義我們自己的TableCellEditor更為簡單。

通過擴充AbstractCellEditor類,只有CellEditor方法中的getCellEditorValue()方法需要為編輯器進行自訂。實現上述步驟並且提供了一個JButton,當點擊整個編輯器組件時彈出JColorChooser。列表18-17顯示了自訂編輯器的源碼。

package swingstudy.ch18; import java.awt.Color;import java.awt.Component;import java.awt.event.ActionEvent;import java.awt.event.ActionListener; import javax.swing.AbstractCellEditor;import javax.swing.JButton;import javax.swing.JColorChooser;import javax.swing.JTable;import javax.swing.table.TableCellEditor; import swingstudy.ch04.DiamondIcon; public class ColorChooserEditor extends AbstractCellEditor implementsTableCellEditor { private JButton delegate = new JButton(); Color savedColor; public ColorChooserEditor() {ActionListener actionListener = new ActionListener() {public void actionPerformed(ActionEvent event) {Color color = JColorChooser.showDialog(delegate, "Color Chooser", savedColor);ColorChooserEditor.this.changeColor(color);}};delegate.addActionListener(actionListener);}@Overridepublic Object getCellEditorValue() {// TODO Auto-generated method stubreturn savedColor;} public void changeColor(Color color) {if(color != null) {savedColor = color;delegate.setIcon(new DiamondIcon(color));}}@Overridepublic Component getTableCellEditorComponent(JTable table, Object value,boolean isSelected, int row, int column) {// TODO Auto-generated method stubchangeColor((Color)value);return delegate;} }

圖18-14顯示了ColorChooserEditor的運行結果。

使用新的ColorChooserEditor的樣本程式顯示在列表18-18中。樣本程式重用了前面顯示在列表18-16中的ColorTableModel資料模型。設定ColorChooserEditor簡單的涉及為相應的列設定TableCellEditor。

package swingstudy.ch18; import java.awt.BorderLayout;import java.awt.EventQueue; import javax.swing.JFrame;import javax.swing.JScrollPane;import javax.swing.JTable;import javax.swing.table.TableCellEditor;import javax.swing.table.TableColumn;import javax.swing.table.TableModel;  public class ChooserTableSample { /** * @param args */public static void main(String[] args) {// TODO Auto-generated method stub Runnable runner = new Runnable() {public void run() {JFrame frame = new JFrame("Editable Color Table");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);TableModel model =  new ColorTableModel();JTable table = new JTable(model); TableColumn column = table.getColumnModel().getColumn(3); ComboTableCellRenderer renderer = new ComboTableCellRenderer();column.setCellRenderer(renderer); TableCellEditor editor = new ColorChooserEditor();column.setCellEditor(editor); JScrollPane scrollPane = new JScrollPane(table);frame.add(scrollPane, BorderLayout.CENTER);frame.setSize(400, 150);frame.setVisible(true);}};EventQueue.invokeLater(runner);} }

18.7 列印表格

JDK5.0的一個新特性也是最容易使用一個特性:列印表格功能。通過簡單的JTable的public boolean print() throws PrinterException方法,我們就可以在印表機在多面上列印一個大表格。甚至是如果我們不喜歡將表格適應整頁紙的寬度的預設行為,我們可以在多個頁面上擴充列。

為了示範這種行為,列表18-19使用基本的JTable範例程式碼來產生圖18-1,向表格添加更多的行,並且添加一個列印按鈕。

package swingstudy.ch18; import java.awt.BorderLayout;import java.awt.EventQueue;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.print.PrinterException; import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JScrollPane;import javax.swing.JTable; public class TablePrint { /** * @param args */public static void main(String[] args) {// TODO Auto-generated method stub final Object rows[][] = {{"1", "ichi - \u4E00"},{"2", "ni -\u4E8C"},{"3", "san - \u4E09"},{"4", "shi - \u56DB"},{"5", "go - \u4E94"},{"6", "roku - \u516D"},{"7", "shichi - \u4E03"},{"8", "hachi - \u516B"},{"9", "kyu - \u4E5D"},{"10","ju - \u5341"},{"1", "ichi - \u4E00"},{"2", "ni -\u4E8C"},{"3", "san - \u4E09"},{"4", "shi - \u56DB"},{"5", "go - \u4E94"},{"6", "roku - \u516D"},{"7", "shichi - \u4E03"},{"8", "hachi - \u516B"},{"9", "kyu - \u4E5D"},{"10","ju - \u5341"},{"1", "ichi - \u4E00"},{"2", "ni -\u4E8C"},{"3", "san - \u4E09"},{"4", "shi - \u56DB"},{"5", "go - \u4E94"},{"6", "roku - \u516D"},{"7", "shichi - \u4E03"},{"8", "hachi - \u516B"},{"9", "kyu - \u4E5D"},{"10","ju - \u5341"}};final Object headers[] = {"English", "Japanese"}; Runnable runner = new Runnable() {public void run() {JFrame frame = new JFrame("Table Printing");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);final JTable table = new JTable(rows, headers);JScrollPane scrollPane = new JScrollPane(table);frame.add(scrollPane, BorderLayout.CENTER);JButton button = new JButton("Print");ActionListener printAction =  new ActionListener() {public void actionPerformed(ActionEvent event) {try {table.print();}catch(PrinterException pe) {System.out.println("Error printing: "+pe.getMessage());}}};button.addActionListener(printAction);frame.add(button, BorderLayout.SOUTH);frame.setSize(300, 150);frame.setVisible(true);}};EventQueue.invokeLater(runner);} }

在點擊列印Print按鈕之後,會向使用者提示一個經典的印表機選擇對話方塊,18-15所示。

在使用者點擊列印對話方塊中的列印按鈕之後,列印開始。會顯示一個類似於圖18-16中所示的對話方塊。

確實,很容易使用JDK 5.0列印多頁表格。print()方法會返回一個boolean值,從而我們可以發現使用者是否關閉了操作。

對於尋找更多列印操作控制的使用者,JTable具有多個重載的print()方法版本。類似於簡單的print()方法,他們都拋出PrinterException。

其中一個print()版本會允許我們指定列印模式:

public boolean print(JTable.PrintModel printMode)

JTable.PrintModel參數是一個FIT_WIDTH與NORMAL的枚舉。當使用無參數的print()版本沒有指定時,則預設為FIT_WIDTH。

另一個版本的方法允許我們指定頁首與頁尾:

public boolean print(JTable.PrintMode printMode, MessageFormat headerFormat,  MessageFormat footerFormat

MessageFormat來自於java.text包。頁首與頁尾格式化字串的一個參數是頁數。要顯示頁數,在我們的格式化字串我們希望顯示頁數的地方包含{0}。兩個都會顯示在頁面的中間,而頁首使用稍大一些的字元。為了示範,將列表18-19中的print()方法調用改為下面的形式:

MessageFormat headerFormat = new MessageFormat("Page {0}");MessageFormat footerFormat = new MessageFormat("- {0} -");table.print(JTable.PrintMode.FIT_WIDTH, headerFormat, footerFormat);

最後一個print()版本是一個綜合版本,使得我們在不顯示印表機對話方塊的情況配置預設印表機所需要的屬性,例如要列印多少份。

public boolean print(JTable.PrintMode printMode, MessageFormat headerFormat,MessageFormat footerFormat, boolean showPrintDialog,PrintRequestAttributeSet attr, boolean interactive)

對於我們不希望使用者與印表機互動的情況下,可以考慮使用最後一個版本。

18.8 小結

在本章中我們探討了JTable組件的內部細節。我們瞭解了如何為JTable自訂TableModel,TableColumnModel與ListSelectionModel。我們深入了不同的表格模型的抽象與具體實現。另外,我們探討了各種表格模型的內部元素,例如TableColumn與JTableHeader類。我們同時瞭解了如何通過提供一個自訂的TableCellRenderer與TableCellEditor來自訂JTable的顯示與編輯。最後,我們瞭解了通過print()方法列印表格。

在第19章中,我們將會探討JFC/Swing組件集合的拖拽體繫結構。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.