📄 ch06.html
字号:
<a name="pgfId-1087581"></a>//API Ref: <a name="77268"></a>void setAutoResizeMode(int mode)</pre> <pre class="CODE"><a name="pgfId-1087586"></a> <a name="marker-1087582"></a><a name="setAutoResizeMode method"></a><a name="javax.swing.JTable class"></a><a name="JTable class"></a>table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);</pre> <p class="Body"><a name="pgfId-1087588"></a><a name="marker-1087587"></a>Creating a custom table model is nearly as easy as using <em class="CODE">DefaultTableModel</em> and requires little additional coding. You can implement a table model by implementing a method to return the number of entries in the model and a method to retrieve an element at a specific position in that model. For example, the <em class="CODE">JTable</em> model can be implemented from <em class="CODE">javax.swing.table.AbstractTableModel</em> <a name="marker-1087589"></a>by implementing the methods <em class="CODE">getColumnCount</em> <a name="marker-1087590"></a>, <em class="CODE">getRowCount</em> <a name="marker-1087591"></a>, and <em class="CODE">getValueAt</em> <a name="marker-1087592"></a>, as shown here:</p> <pre class="CODE"><a name="pgfId-1087593"></a>final Object[][] data = new Object[][]{ {"row 1 col1","row 1 col2" },</pre> <pre class="CODE"><a name="pgfId-1087594"></a> {"row 2 col 1","row 2 col 2"} };final Object[] headers = new Object[] {"first header","second header"};TableModel model = new AbstractTableModel(){ public int getColumnCount() { return data[0].length; } public int getRowCount() { return data.length; } public String getColumnName(int col) { return (String)headers[col]; } public Object getValueAt(int row,int col) { return data[row][col]; }};table = new JTable(model);table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); </pre> <pre class="CODE"><a name="pgfId-1087595"></a> </pre> <p class="Body"><a name="pgfId-1087596"></a>This table is read-only and its data values are already known. In fact, the data are even declared final so they can be retrieved by the inner <em class="CODE">TableModel</em> class. This is not normally the situation when working with live data.</p> <p class="Body"><a name="pgfId-1087598"></a>You can create an editable table by adding the <em class="CODE">isCellEditable</em> <a name="marker-1087597"></a>verification method, which is used by the default cell editor and the <em class="CODE">AbstractTableModel</em> class for setting a value at a position. Up until this change, the <em class="CODE">AbstractTableModel</em> has been handling the repainting and resizing of the table by firing different table changed events. Because the <em class="CODE">AbtractTableModel</em> does not know that something has occurred to the table data, you need to inform it by calling the <em class="CODE">fireTableCellUpdated</em> <a name="marker-1087599"></a>method. The following lines are added to the <em class="CODE">AbstractTableModel</em> inner class to allow editing of the data:</p> <pre class="CODE"><a name="pgfId-1087600"></a> public void setValueAt (Object value, int row, int col) { data[row][col] = value; fireTableCellUpdated (row, col); }</pre> <pre class="CODE-caption"><a name="pgfId-1087602"></a>//API Ref: <a name="41991"></a>boolean isCellEditable(int row, int column)</pre> <pre class="CODE"><a name="pgfId-1087605"></a> <a name="marker-1087603"></a><a name="isCellEditable method"></a>public boolean isCellEditable(int row, int col) { return true; }</pre> <p class="Body"><a name="pgfId-1087607"></a><em class="Bold">More Table Models. </em><a name="marker-1087606"></a>A common requirement for the display of tabular data is the inclusion of a nonscrolling column. This column provides a set of anchor data that remains stationary and visible while its neighboring columns are scrolled horizontally (and often out of view). This is particularly important in cases where row data can be identified by a unique value in the fixed column, such as a name or identification number. The next code example uses a fixed table column to display a list of the auction items.</p> <p class="Body"><a name="pgfId-1087608"></a>The base table model in this example implements the <em class="CODE">AbstractTableModel</em> class. Its update method dynamically populates the table data from a call to the database. It sends an event that the table has been updated by calling the <em class="CODE">fireTableStructureChanged</em> <a name="marker-1087609"></a>method to indicate that the number of rows or columns in the table have changed.</p> <pre class="CODE"><a name="pgfId-1087613"></a><a name="marker-1087610"></a><a name="marker-1087611"></a><a name="marker-1087612"></a>package auction;import javax.swing.table.AbstractTableModel;import javax.swing.event.TableModelEvent;import java.text.NumberFormat; import java.util.*;import java.awt.*;public class ResultsModel extends AbstractTableModel{ String[] columnNames={}; Vector rows = new Vector(); public String getColumnName(int column) { if(columnNames[column] != null) { return columnNames[column]; } else { return ""; } } public boolean isCellEditable(int row, int column){ return false; } public int getColumnCount() { return columnNames.length; } public int getRowCount() { return rows.size(); } public Object getValueAt(int row, int column){ Vector tmprow = (Vector)rows.elementAt(row); return tmprow.elementAt(column); } public void update(Enumeration enum) { try { //Create the column headers which are later accessed through //the getColumnName method columnNames = new String[5]; columnNames[0]=new String("Auction Id #"); columnNames[1]=new String("Description"); columnNames[2]=new String("High Bid"); columnNames[3]=new String("# of bids"); columnNames[4]=new String("End Date");</pre> <pre class="CODE"><a name="pgfId-1087614"></a> //Create each vector row from the AuctionItem data while((enum !=null) && (enum.hasMoreElements())) { AuctionItem auctionItem=(AuctionItem)enum.nextElement(); Vector items=new Vector(); items.addElement(new Integer(auctionItem.getId())); items.addElement(auctionItem.getSummary()); int bidcount= auctionItem.getBidCount(); if(bidcount >0) { items.addElement(NumberFormat.getCurrencyInstance().format( auctionItem.getHighBid())); } else { items.addElement("-"); } items.addElement(new Integer(bidcount)); items.addElement(auctionItem.getEndDate()); rows.addElement(items); }</pre> <pre class="CODE-caption"><a name="pgfId-1087616"></a>//API Ref: <a name="95529"></a>void fireTableStructureChanged()</pre> <pre class="CODE"><a name="pgfId-1087621"></a> <a name="javax.swing.table.DefaultTableModel class"></a><a name="DefaulttableModel class"></a><a name="fireTableStructureChanged method"></a><a name="marker-1087620"></a>fireTableStructureChanged(); } catch (Exception e) { System.out.println("Exception e"+e); } }</pre> <pre class="CODE"><a name="pgfId-1087622"></a>}</pre> <p class="Body"><a name="pgfId-1087623"></a>The table is created from the <em class="CODE">ResultsModel</em> model. Then, the first table column is removed from that table and added to a new table. Because there are now two tables, the only way the selections can be kept in sync is to use a <em class="CODE">ListSelectionModel</em> <a name="marker-1087624"></a>object to set the selection on the table row in the other tables that were not selected by calling the <em class="CODE">setRowSelectionInterval</em> <a name="marker-1087625"></a>method. The full example can be found in the <em class="CODE">AuctionClient</em> source file:</p> <pre class="CODE"><a name="pgfId-1087626"></a> private void listAllItems() throws IOException{ ResultsModel rm=new ResultsModel(); try { BidderHome bhome=(BidderHome)ctx.lookup("bidder"); Bidder bid=bhome.create(); Enumeration enum=(Enumeration)bid.getItemList(); if (enum != null) { rm.update(enum); } } catch (Exception e) { System.out.println("AuctionServlet <list>:"+e); } //Create a new table using the ResultsModel object as the table model</pre> <pre class="CODE"><a name="pgfId-1087627"></a> scrollTable=new JTable(rm);</pre> <pre class="CODE"><a name="pgfId-1087628"></a> //Force the End Date and Description columns to have </pre> <pre class="CODE"><a name="pgfId-1087629"></a> //a set width</pre> <pre class="CODE"><a name="pgfId-1087630"></a> adjustColumnWidth(scrollTable.getColumn("End Date"), 150); adjustColumnWidth(scrollTable.getColumn("Description"), 120);</pre> <pre class="CODE"><a name="pgfId-1087631"></a> //The scroll column model is initially mapped to //display all the table data. The fixed column model //is initially empty scrollColumnModel = scrollTable.getColumnModel(); fixedColumnModel = new DefaultTableColumnModel();</pre> <pre class="CODE"><a name="pgfId-1087632"></a> //Get the first column, remove it from the scroll column, and //add it to the fixed table TableColumn col = scrollColumnModel.getColumn(0); scrollColumnModel.removeColumn(col); fixedColumnModel.addColumn(col); //Create a new table based on the fixed column model (1 column) fixedTable = new JTable(rm,fixedColumnModel); //Keep the heights of the fixed and scroll tables the same fixedTable.setRowHeight(scrollTable.getRowHeight()); headers = new JViewport(); //Get the selection model used in this table and override it //so we can also update the scroll table if the fixed table //is selected and vice versa ListSelectionModel fixedSelection = fixedTable.getSelectionModel(); fixedSelection.addListSelectionListener( new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { ListSelectionModel lsm = (ListSelectionModel)e.getSource(); if (!lsm.isSelectionEmpty()) { setScrollableRow(); } } });</pre> <pre class="CODE-caption">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -