📄 swing2.html
字号:
to move to a different layer.
<H4>JContentPane</H4>
The <CODE>JContentPane</CODE> manages adding components to heavyweight containers.
So, you have to call the <CODE>getContentPane</CODE> method to add a component to
the <CODE>ContentPane</CODE> of the <CODE>RootPane</CODE>. By default, a
<CODE>ContentPane</CODE> is initialized with a <CODE>BorderLayout</CODE>
layout manager. There are two ways to change the layout manager. You can
call the <CODE>setLayout</CODE> method like this:
<PRE>
getContentPane()).setLayout(new BoxLayout())
</PRE>
Or you can replace the default <CODE>ContentPane</CODE> with your own
<CODE>ContentPane</CODE>, such as a <CODE>JPanel</CODE>, like this:
<PRE>
JPanel pane= new JPanel();
pane.setLayout(new BoxLayout());
setContentPane(pane);
</PRE>
<H4>GlassPane</H4>
The <CODE>GlassPane</CODE> is usually completely transparent and just
acts as a sheet of glass in front of the components. You can implement
your own <CODE>GlassPane</CODE> by using a component like <CODE>JPanel</CODE>
and installing it as the <CODE>GlassPane</CODE> by calling the
<CODE>setGlassPane</CODE> method. The <CODE>RootPane</CODE> is configured with
a <CODE>GlassPane</CODE> that can be retrieved by calling <CODE>getGlassPane</CODE>.
<P>
One way to use a <CODE>GlassPane</CODE> is to implement a component
that invisibly handles all mouse and keyboard events, effectively
blocking user input until an event completes. The <CODE>GlassPane</CODE>
can block the events, but currently the cursor will not return
to its default state if you have set the cursor to be a busy cursor
in the <CODE>GlassPane</CODE>. An additional mouse event is required for
the refresh.
<PRE>
MyGlassPane glassPane = new MyGlassPane();
setGlassPane(glassPane);
setGlassPane.setVisible(true); //before worker thread
..
setGlassPane.setVisible(false); //after worker thread
private class MyGlassPane extends JPanel {
public MyGlassPane() {
addKeyListener(new KeyAdapter() { });
addMouseListener(new MouseAdapter() { });
super.setCursor(
Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
}
</PRE>
<A NAME="model"></A>
<H3>Data Models</H3>
Numerous model layers are combined to form the tables of the
<CODE>AuctionClient</CODE> GUI.
At a foundational level, the <CODE>TableModel</CODE> interface and its two
implementations <CODE>AbstractTableModel</CODE> and <CODE>DefaultTableModel</CODE>
provide the most basic means for storage, retrieval and modification of the
underlying data.
<P>
The <CODE>TableModel</CODE> is responsible for defining and categorizing the
data by its class. It also determines if the data can be edited and how
the data is grouped into columns and rows.
It is important to note, however, that while the <CODE>TableModel</CODE>
interface is used
most often in the construction of a <CODE>JTable</CODE>, it is not
fundamentally tied to
their display. Implementations could just as easily form the basis of a
spreadsheet component, or even a non-GUI class that calls for the organization
of data in tabular format.
<P>
The <CODE>ResultsModel</CODE> class is at the heart of the
<CODE>AuctionClient</CODE> tables.
It defines a dynamic data set, dictates whether class users can
edit the data through its <CODE>ResultsModel.isCellEditable</CODE> method,
and provides the <CODE>update</CODE> method to keep the data current.
The model underlies the scrolling and fixed tables, and lets
modifications to be reflected in each view.
<P>
At a higher level, and representing an intermediate layer between data and its
graphical representation, is the <CODE>TableColumnModel</CODE>. At this level
the data is grouped by column in anticipation of its ultimate display in the
table. The visibility and size of these columns, their headers, and the
component types of their cell renderers and editors are all managed by
the <CODE>TableColumnModel</CODE> class.
<P>
For example, freezing the left-most columns in the <CODE>AuctionClient</CODE>
GUI is possible because column data is easily exchanged among multiple
<CODE>TableColumnModel</CODE> and <CODE>JTable</CODE>
objects. This translates to the <CODE>fixedTable</CODE> and <CODE>scrollTable</CODE>
objects of the <CODE>AuctionClient</CODE> program.
<P>
Higher still lie the various renderers, editors, and header components whose
combination define the look and organization of the <CODE>JTable</CODE> component.
This level is where the fundamental layout and display decisions of the
<CODE>JTable</CODE> are made.
<P>
The creation of the inner classes <CODE>CustomRenderer</CODE> and
<CODE>CustomButtonRenderer</CODE> within the AuctionClient application
allows users of those classes to redefine the components upon which the
appearance of table cells are based. Likewise, the <CODE>CustomButtonEditor</CODE>
class takes the place of the table's default editor.
In true object-oriented fashion, the default editors and renderers are easily
replaced, affecting neither the data they represent nor the function of the
component in which they reside.
<P>
Finally, the various component user interfaces are responsible for the ultimate
appearance of the <CODE>JTable</CODE>. It is here the look-and-feel-specific
representation of the <CODE>AuctionClient</CODE> tables and their data are
rendered in final form to the user. The end result is that adding a Project
Swing front-end to existing services requires little additional code.
In fact, coding the model is one of the easier tasks in building a Project
Swing application.
<H4>Table Model</H4>
The <CODE>JTable</CODE> class has an associated <CODE>DefaultTableModel</CODE>
class that internally uses a Vector of vectors to store data internally. The
data for each row is stored in a singl <CODE>Vector</CODE> object while another
<CODE>Vector</CODE> object stores each of those rows as its constituent elements.
The <CODE>DefaultTableModel</CODE> object can be initialized with data in
several different ways. This code shows the <CODE>DefaultTableModel</CODE>
created with a two-dimensional array and a second array representing column
headings. The <CODE>DefaultTableModel</CODE> in turn converts the <CODE>Object</CODE>
arrays into the appropriate <CODE>Vector</CODE> objects:
<PRE>
Object[][] data = new Object[][]{ {"row 1 col1",
"Row 1 col2" },
{"row 2 col 1",
"row 2 col 2"}
};
Object[] headers = new Object[] {"first header",
"second header"};
DefaultTableModel model = new DefaultTableModel(data,
headers);
table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
</PRE>
Creating a custom table model is nearly as easy as using
<CODE>DefaultTableModel</CODE>, 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 <CODE>JTable</CODE> model can be
implemented from <CODE>javax.swing.table.AbstractTableModel</CODE> by
implementing the methods <CODE>getColumnCount</CODE>, <CODE>getRowCount</CODE>
and <CODE>getValueAt</CODE> as shown here:
<PRE>
final Object[][] data = new Object[][]{ {
"row 1 col1",
"row 1 col2" },
{"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>
This table is read-only and its data values are already known. In fact,
the data is even declared <CODE>final</CODE> so it can be retrieved
by the inner <CODE>TableModel</CODE> class. This is not normally the situation
when working with live data.
<P>
You can create an editable table by by adding the <CODE>isCellEditable</CODE>
verification method, which is used by the default cell editor, and the
<CODE>AbstractTableModel</CODE> method for setting a value at a position.
Up until this change, the <CODE>AbstractTableModel</CODE> has been handling
the repainting and resizing of the table by firing different table changed
events. Because the <CODE>AbtractTableModel</CODE> does not
know that something has occured to the table data, you need to inform
it by calling the <CODE>fireTableCellUpdated</CODE> method. The following
lines are added to the <CODE>AbstractTableModel</CODE> inner class to
allow editing of the data:
<PRE>
public void setValueAt (Object value,
int row, int col) {
data[row][col] = value;
fireTableCellUpdated (row, col);
}
public boolean isCellEditable(int row,
int col) {
return true;
}
</PRE>
<H4>More Table Models</H4>
A common requirement for the display of tabular data is the inclusion
of a non-scrolling 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>
The base table model in this example implements the
<CODE>AbstractTableModel</CODE> class. Its <CODE>update</CODE> 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
<CODE>fireTableStructureChanged</CODE> method to indicate the
number of rows or columns in the table have changed.
<PRE>
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 {
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");
while((enum !=null) &&
(enum.hasMoreElements())) {
while(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);
}
}
fireTableStructureChanged();
} catch (Exception e) {
System.out.println("Exception e"+e);
}
}
}
</PRE>
The table is created from the <CODE>ResultsModel</CODE> 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 <CODE>ListSelectionModel</CODE> object
to set the selection on the table row in the other tables that were not
selected by calling the <CODE>setRowSelectionInterval</CODE> method.
<P>
The full example can be found in the
<A HREF="./Code/admin/AuctionClient.java">AuctionClient.java</A>
source file:
<PRE>
private void listAllItems() throws IOException{
ResultsModel rm=new ResultsModel();
if (!standaloneMode) {
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);
}
} else {
TestData td= new TestData();
rm.update(td.results());
}
scrollTable=new JTable(rm);
adjustColumnWidth(scrollTable.getColumn(
"End Date"), 150);
adjustColumnWidth(scrollTable.getColumn(
"Description"), 120);
scrollColumnModel = scrollTable.getColumnModel();
fixedColumnModel = new DefaultTableColumnModel();
TableColumn col = scrollColumnModel.getColumn(0);
scrollColumnModel.removeColumn(col);
fixedColumnModel.addColumn(col);
fixedTable = new JTable(rm,fixedColumnModel);
fixedTable.setRowHeight(scrollTable.getRowHeight());
headers = new JViewport();
ListSelectionModel fixedSelection =
fixedTable.getSelectionModel();
fixedSelection.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (
ListSelectionModel)e.getSource();
if (!lsm.isSelectionEmpty()) {
setScrollableRow();
}
}
});
ListSelectionModel scrollSelection =
scrollTable.getSelectionModel();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -