⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch06.html

📁 java2高级编程
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"><html>	<head>		<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">		<meta name="generator" content="Adobe GoLive 4">		<title>Covered in this Chapter</title>		<meta http-equiv="Content-Style-Type" content="text/css">		<link rel="STYLESHEET" href="CH06.css" charset="ISO-8859-1" type="text/css">	</head>	<body bgcolor="white">		<p class="CT"><a name="pgfId-1087399"></a>6</p>		<p class="CT"><a name="pgfId-1087400"></a>Project Swing: Building a User Interface</p>		<p class="Body"><a name="pgfId-1087401"></a>The Java Foundation Classes (JFC) Project Swing and Enterprise JavaBeans architectures share one key design element: the separation of data from the display or manipulation of that data. In Enterprise JavaBeans applications, the entity bean provides a view of the data. The underlying data storage mechanism can be swapped out and replaced without changing the entity bean view or recompiling any code that uses the view.</p>		<p class="Body"><a name="pgfId-1087402"></a>Project Swing separates the view and control of a visual component from its contents, or data model. However, although Project Swing does have the components that make up a <a name="marker-1087403"></a>Model-View-Controller (MVC) architecture, it is more accurately described as a <a name="marker-1087404"></a>model-delegate architecture. This is because the controller part of the Project Swing interface, often the mouse and keyboard events the component responds to, is combined with the physical view in one <a name="marker-1087405"></a>User Interface (UI) delegate object.</p>		<p class="Body"><a name="pgfId-1087406"></a>Each component, for example, a <em class="CODE">JButton</em> or a <em class="CODE">JScrollBar</em> , has a separate UI delegate class that inherits from the <em class="CODE">ComponentUI</em> <a name="marker-1087407"></a>class and is under the control of a separate UI manager. Although each component has a basic UI delegate, it is no longer tied to the underlying data, so a new set of delegates--a set of metal-styled components, for example--can be swapped in while the application is still running. The ability to change the look and behavior reflects the <a name="marker-1087408"></a>pluggable look and feel (PLAF) feature available in Project Swing.</p>		<div>			<h4 class="A"><a name="pgfId-1087409"></a>Covered in this Chapter</h4>			<ul>				<li class="BL"><a name="pgfId-1087410"></a>Components and Data Models (page 160)				<li class="BL"><a name="pgfId-1087411"></a>Printing API (page 181)				<li class="BL"><a name="pgfId-1087412"></a>Advanced Printing (page 188)				<li class="BL"><a name="pgfId-1087413"></a>AuctionClient (page 193)				<li class="BL"><a name="pgfId-1087414"></a>Report (page 202)				<li class="BL"><a name="pgfId-1087415"></a>SalesReport (page 204)			</ul>		</div>		<div>			<h4 class="A"><a name="pgfId-1087417"></a><a name="76351"></a>Components and Data Models</h4>			<p class="Body"><a name="pgfId-1087418"></a>This section explains Project Swing in terms of the <em class="CODE">AuctionClient</em> (page 193) program shown in Figure 6.1. It is a simple GUI application that lets auction administrators list and browse auction items.</p>			<div>				<h6 class="FC"><a name="pgfId-1087423"></a>Figure 6.1 <a name="19581"></a>Administration applet</h6>				<div>					<img src="CH06-1.gif"></div>			</div>			<div>				<h5 class="B"><a name="pgfId-1087424"></a>Lightweight Components</h5>				<p class="Body"><a name="pgfId-1087427"></a><a name="marker-1087425"></a><a name="marker-1087426"></a>All components in Project Swing, except <em class="CODE">JApplet</em> , <em class="CODE">JDialog</em> , <em class="CODE">JFrame</em> , and <em class="CODE">JWindow</em> are <a name="marker-1087428"></a>lightweight components. Lightweight components, unlike their Abstract Window Toolkit (AWT) counterparts, do not depend on the local windowing toolkit.</p>				<p class="Body"><a name="pgfId-1087430"></a>For example, a <a name="marker-1087429"></a>heavyweight <em class="CODE">java.awt.Button</em> running on the Java platform for the Unix platform maps to a real <em class="CODE">Motif</em> <a name="marker-1087431"></a><a name="marker-1087432"></a><a name="marker-1087433"></a>button. In this relationship, the <em class="CODE">Motif</em> button is called the peer to the <em class="CODE">java.awt.Button</em> . If you create two <em class="CODE">java.awt.Buttons</em> in an application, two peers and hence two <em class="CODE">Motif</em> buttons are also created. The Java platform communicates with the <em class="CODE">Motif</em> buttons using the Java Native Interface (JNI). For each and every component added to the application, there is additional overhead tied to the local windowing system, which is why these components are called heavyweight.</p>				<p class="Body"><a name="pgfId-1087436"></a>Lightweight components are termed <a name="marker-1087434"></a><a name="marker-1087435"></a>peerless components and emulate the local window system components. A lightweight button is represented as a rectangle with a label inside that accepts mouse events. Adding more lightweight buttons means drawing more rectangles.</p>				<p class="Body"><a name="pgfId-1087437"></a>A lightweight component needs to be drawn on something, and an application written in the Java programming language needs to interact with the local window manager so that the main application window can be closed or minimized. This is why the top-level parent components mentioned above (<em class="CODE"> JFrame</em> , <em class="CODE">JApplet</em> , and others) are implemented as heavyweight components--they need to be mapped to a component in the local window toolkit.</p>				<p class="Body"><a name="pgfId-1087438"></a>A <em class="CODE">JButton</em> is a very simple shape to draw. For more complex components like <em class="CODE">JList</em> or <em class="CODE">JTable</em> , the elements or cells of the list or table are drawn by a <em class="CODE">CellRenderer</em> <a name="marker-1087439"></a>object. A <em class="CODE">CellRenderer</em> object provides flexibility because it makes it possible for any type of object to be displayed in any row or column.</p>				<p class="Body"><a name="pgfId-1087441"></a><a name="marker-1087440"></a>For example, a <em class="CODE">JTable</em> can use a different <em class="CODE">CellRenderer</em> for each column. This code segment sets the second column, which is referenced as <em class="CODE">index</em> <em class="CODE">1</em> , to use a <em class="CODE">CustomRenderer</em> object to create the cells for that column.</p>				<pre class="CODE"><a name="pgfId-1087442"></a>JTable scrollTable=new JTable(rm); TableColumnModel scrollColumnModel = scrollTable.getColumnModel(); CustomRenderer custom = new CustomRenderer();</pre>				<pre class="CODE-caption"><a name="pgfId-1087444"></a>//API Ref: <a name="56786"></a>TableColumn getColumn(int index)</pre>				<pre class="CODE"><a name="pgfId-1087449"></a><a name="marker-1087445"></a><a name="javax.swing.table.TableColumnModel class"></a><a name="TableColumnModel class"></a><a name="getColumn method"></a>scrollColumnModel.getColumn(1).setCellRenderer(custom);</pre>			</div>			<div>				<h5 class="B"><a name="pgfId-1087450"></a>Ordering Components</h5>				<p class="Body"><a name="pgfId-1087453"></a><a name="marker-1087451"></a><a name="marker-1087452"></a>Each Project Swing applet or application needs at least one heavyweight container component (a <em class="CODE">JFrame</em> , <em class="CODE">JWindow</em> , <em class="CODE">JApplet</em> , or <em class="CODE">JDialog</em> ). Each of these containers with <em class="CODE">JFrame</em> 's lightweight multiple document interface (MDI) counterpart, <em class="CODE">JInternalFrame</em> <a name="marker-1087454"></a>, contains a component called a root pane. The <em class="CODE">JRootPane</em> <a name="marker-1087455"></a>manages the additional layers used in the container such as the <em class="CODE">JLayeredPane</em> , <em class="CODE">JContentPane</em> , <em class="CODE">GlassPane</em> , and the optional <em class="CODE">JMenuBar</em> . It also lets all emulated (lightweight) components interact with the AWT event queue to send and receive events. Interacting with the event queue gives emulated components indirect interaction with the local window manager.</p>				<p class="Body"><a name="pgfId-1087459"></a><em class="C-Code">JLayeredPane</em> . <a name="marker-1087456"></a><a name="marker-1087457"></a>The <em class="CODE">JLayeredPane</em> <a name="marker-1087458"></a>sits on top of the <em class="CODE">JRootPane</em> , and as its name implies, controls the layers of the components contained within the boundary of the heavyweight container. The components are not added to the <em class="CODE">JLayeredPane</em> , but to the <em class="CODE">JContentPane</em> instead. The <em class="CODE">JLayeredPane</em> determines the <a name="marker-1087460"></a><a name="marker-1087461"></a>Z-ordering of the components in the <em class="CODE">JRootPane</em> . The Z-order can be thought of as the order of overlay among the various components. If you drag-and-drop a component or request a dialog to pop up, you want that component to appear in front of the others in the application window. The <em class="CODE">JLayeredPane</em> lets you layer components.</p>				<p class="Body"><a name="pgfId-1087462"></a>The <em class="CODE">JLayeredPane</em> divides the depth of the container into different bands that can be used to assign a component to a type-appropriate level. The <em class="CODE">DRAG_LAYER</em> band, value 400, appears above all other defined component layers. The lowermost level of <em class="CODE">JLayeredPane</em> , the <em class="CODE">DEFAULT_FRAME_LAYER</em> band, has value -3,000 and is the level of the heavyweight containers, including the <em class="CODE">MenuBar</em> . The bands are as follows:</p>				<p>				<table>					<tr>						<th>							<p class="TCH"><a name="pgfId-1087465"></a>Value</th>						<th>							<p class="TCH"><a name="pgfId-1087467"></a>Layer Name</th>						<th>							<p class="TCH"><a name="pgfId-1087469"></a>&nbsp;</th>						<th>							<p class="TCH"><a name="pgfId-1087471"></a>Component Types</th>						<th>							<p class="TCH"><a name="pgfId-1087473"></a>&nbsp;</th>					</tr>					<tr>						<td>							<p class="TB1"><a name="pgfId-1087475"></a>-3,000</td>						<td>							<p class="TB1"><a name="pgfId-1087478"></a><em class="CODE">DEFAULT_FRAME_LAYER</em> <a name="marker-1087477"></a></td>						<td>							<p class="TB1"><a name="pgfId-1087480"></a>&nbsp;</td>						<td>							<p class="TB1"><a name="pgfId-1087482"></a><em class="CODE">JMenubar</em></td>						<td>							<p class="TB1"><a name="pgfId-1087484"></a>&nbsp;</td>					</tr>					<tr>						<td>							<p class="TB"><a name="pgfId-1087486"></a>0</td>						<td>							<p class="TB"><a name="pgfId-1087489"></a><em class="CODE">DEFAULT_LAYER</em> <a name="marker-1087488"></a></td>						<td>							<p class="TB"><a name="pgfId-1087491"></a>&nbsp;</td>						<td>							<p class="TB"><a name="pgfId-1087493"></a><em class="CODE">JButton</em> ,<em class="CODE"> JTable</em> , . . .</td>						<td>							<p class="TB"><a name="pgfId-1087495"></a>&nbsp;</td>					</tr>					<tr>						<td>							<p class="TB"><a name="pgfId-1087497"></a>&nbsp;</td>						<td>							<p class="TB"><a name="pgfId-1087500"></a><em class="CODE">PALETTE_LAYER</em> <a name="marker-1087499"></a></td>						<td>							<p class="TB"><a name="pgfId-1087502"></a>&nbsp;</td>						<td>							<p class="TB"><a name="pgfId-1087504"></a>Floating components such as <em class="CODE">JToolBar</em></td>						<td>							<p class="TB"><a name="pgfId-1087506"></a>&nbsp;</td>					</tr>					<tr>						<td>							<p class="TB"><a name="pgfId-1087508"></a>&nbsp;</td>						<td>							<p class="TB"><a name="pgfId-1087511"></a><em class="CODE">MODAL_LAYER</em> <a name="marker-1087510"></a></td>						<td>							<p class="TB"><a name="pgfId-1087513"></a>&nbsp;</td>						<td>							<p class="TB"><a name="pgfId-1087515"></a>Modal dialogs</td>						<td>							<p class="TB"><a name="pgfId-1087517"></a>&nbsp;</td>					</tr>					<tr>						<td>							<p class="TB"><a name="pgfId-1087519"></a>400</td>						<td>							<p class="TB"><a name="pgfId-1087522"></a><em class="CODE">DRAG_LAYER</em> <a name="marker-1087521"></a></td>						<td>							<p class="TB"><a name="pgfId-1087524"></a>&nbsp;</td>						<td>							<p class="TB"><a name="pgfId-1087526"></a>Drag-and-drop over all layers</td>						<td>							<p class="TB"><a name="pgfId-1087528"></a>&nbsp;</td>					</tr>				</table>				<p class="Body"><a name="pgfId-1087529"></a>Within these general depth bands, components can be further arranged with another numbering system to order the components in a particular band, but this system reverses the numbering priority.</p>				<p class="Body"><a name="pgfId-1087530"></a>For example, in a specific band such as <em class="CODE">DEFAULT_LAYER</em> , components with a value of 0 appear in front of others in that band; whereas, components with a higher number or -1 appear behind them. The highest number in this scheme is the number of components minus 1, so one way to visualize it is shown in Figure 6.2, which shows a vector of components that steps through painting the components with a higher number first, finishing with the one at position 0.</p>				<div>					<h6 class="FC"><a name="pgfId-1087535"></a>Figure 6.2 <a name="93385"></a>Painting components</h6>					<div>						<img src="CH06-2.gif"></div>					<p class="Body"><a name="pgfId-1087536"></a>For example, the following code adds a <em class="CODE">JButton</em> to the default layer and specifies that it appear in front of the other components in that same layer:</p>					<pre class="CODE"><a name="pgfId-1087537"></a>JButton enterButton = new JButton(&quot;Enter&quot;); layeredPane.add(enterButton, LayeredPane.Default_Layer, 0);</pre>					<p class="Body"><a name="pgfId-1087539"></a>You can achieve the same effect by calling the <em class="CODE">LayeredPane.moveToFront</em> <a name="marker-1087538"></a>method within a layer or by using the <em class="CODE">LayeredPane.setLayer</em> method to move to a different layer.</p>					<p class="Body"><a name="pgfId-1087542"></a><em class="C-Code">JContentPane</em> . <a name="marker-1087540"></a>The <em class="CODE">JContentPane</em> manages adding components to <a name="marker-1087541"></a>heavyweight containers. So, you have to call the <em class="CODE">getContentPane</em> <a name="marker-1087543"></a>method to add a component to the <em class="CODE">ContentPane</em> of the <em class="CODE">RootPane</em> . By default, a <em class="CODE">ContentPane</em> is initialized with a <em class="CODE">BorderLayout</em> <a name="marker-1087544"></a>layout manager. There are two ways to change the layout manager. You can call the <em class="CODE">setLayout</em> <a name="marker-1087545"></a>method like this:</p>					<pre class="CODE"><a name="pgfId-1087546"></a>getContentPane()).setLayout(new BoxLayout())</pre>					<p class="Body"><a name="pgfId-1087547"></a>Or you can replace the default <em class="CODE">ContentPane</em> with your own <em class="CODE">ContentPane</em> , such as a <em class="CODE">JPanel</em> , like this:</p>					<pre class="CODE"><a name="pgfId-1087548"></a>  JPanel pane= new JPanel();     pane.setLayout(new BoxLayout());     setContentPane(pane);</pre>					<p class="Body"><a name="pgfId-1087550"></a><em class="C-Code">GlassPane</em> . The <em class="CODE">GlassPane</em> <a name="marker-1087549"></a>is usually completely transparent and just acts as a sheet of glass in front of the components. You can implement your own <em class="CODE">GlassPane</em> by using a component like <em class="CODE">JPanel</em> and installing it as the <em class="CODE">GlassPane</em> by calling the <em class="CODE">setGlassPane</em> method. The <em class="CODE">RootPane</em> is configured with a <em class="CODE">GlassPane</em> that can be retrieved by calling <em class="CODE">getGlassPane</em> <a name="marker-1087551"></a>.</p>					<p class="Body"><a name="pgfId-1087552"></a>One way to use a <em class="CODE">GlassPane</em> is to implement a component that invisibly handles all mouse and keyboard events, effectively blocking user input until an event completes. The <em class="CODE">GlassPane</em> 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 <em class="CODE">GlassPane</em> . An additional mouse event is required for the refresh.</p>					<pre class="CODE"><a name="pgfId-1087553"></a>MyGlassPane  glassPane = new MyGlassPane();setGlassPane(glassPane);       glassPane.setVisible(true); //before worker thread  ..glassPane.setVisible(false); //after worker threadprivate class MyGlassPane extends JPanel {  public MyGlassPane() {    addKeyListener(new KeyAdapter() { });    addMouseListener(new MouseAdapter() { });    super.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));  }}</pre>					<p class="Body"><a name="pgfId-1087556"></a><em class="Bold">Data Models. </em><a name="marker-1087554"></a><a name="marker-1087555"></a>Numerous model layers are combined to form the tables of the <em class="CODE">AuctionClient</em> GUI. At a foundational level, the <em class="CODE">TableModel</em> <a name="marker-1087557"></a>interface and its two implementations <em class="CODE">AbstractTableModel</em> and <em class="CODE">DefaultTableModel</em> provide the most basic means for storage, retrieval, and modification of the underlying data.</p>					<p class="Body"><a name="pgfId-1087559"></a><a name="marker-1087558"></a>The <em class="CODE">TableModel</em> defines and categorizes the data by its class. It also determines if the data can be edited and how the <a name="marker-1087560"></a>data is grouped into columns and rows. It is important to note, however, that while the <em class="CODE">TableModel</em> interface is used most often in the construction of a <em class="CODE">JTable</em> , 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>					<p class="Body"><a name="pgfId-1087562"></a>The <em class="CODE">ResultsModel</em> <a name="marker-1087561"></a>class is at the heart of the <em class="CODE">AuctionClient</em> tables. It defines a dynamic data set, dictates whether class users can edit the data through its <em class="CODE">ResultsModel.isCellEditable</em> <a name="marker-1087563"></a>method, and provides the <em class="CODE">update</em> method to keep the data current. The model underlies the scrolling and fixed tables and lets modifications be reflected in each view.</p>					<p class="Body"><a name="pgfId-1087564"></a>At a higher level, representing an intermediate layer between data and its graphical representation, is the <em class="CODE">TableColumnModel</em> <a name="marker-1087565"></a>. 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 <em class="CODE">TableColumnModel</em> class.</p>					<p class="Body"><a name="pgfId-1087567"></a><a name="marker-1087566"></a>For example, freezing the leftmost columns in the <em class="CODE">AuctionClient</em> GUI is possible because column data is easily exchanged among multiple <em class="CODE">TableColumnModel</em> and <em class="CODE">JTable</em> objects. This translates to the <em class="CODE">fixedTable</em> and <em class="CODE">scrollTable</em> objects of the <em class="CODE">AuctionClient</em> program.</p>					<p class="Body"><a name="pgfId-1087568"></a>Higher still lie the various renderers, editors, and header components whose combination defines the look and organization of the <em class="CODE">JTable</em> component. This level is where the fundamental layout and display decisions of the <em class="CODE">JTable</em> are made.</p>					<p class="Body"><a name="pgfId-1087571"></a>The creation of the inner classes <em class="CODE">CustomRenderer</em> <a name="marker-1087569"></a>and <em class="CODE">CustomButtonRenderer</em> <a name="marker-1087570"></a>within the <em class="CODE">AuctionClient</em> application allows users of those classes to redefine the components upon which the appearance of table cells are based. Likewise, the <em class="CODE">CustomButtonEditor</em> <a name="marker-1087572"></a>class takes the place of the table's default editor. In true object-oriented style, 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>					<p class="Body"><a name="pgfId-1087573"></a>Finally, the various component user interfaces are responsible for the ultimate appearance of the <em class="CODE">JTable</em> . It is here the look-and-feel specific representation of the <em class="CODE">AuctionClient</em> 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.</p>					<p class="Body"><a name="pgfId-1087577"></a><em class="Bold">Table Model. </em><a name="marker-1087574"></a><a name="marker-1087575"></a>The <em class="CODE">JTable</em> class has an associated <em class="CODE">DefaultTableModel</em> <a name="marker-1087576"></a>class that internally uses a <em class="CODE">Vector</em> of vectors to store data. The data for each row is stored in a single <em class="CODE">Vector</em> object while another <em class="CODE">Vector</em> object stores each of those rows as its constituent elements. The <em class="CODE">DefaultTableModel</em> object can be initialized with data in several different ways. This code shows the <em class="CODE">DefaultTableModel</em> created with a two-dimensional array and with a second array representing column headings. The <em class="CODE">DefaultTableModel</em> in turn converts the <em class="CODE">Object</em> arrays into the appropriate <em class="CODE">Vector</em> objects:</p>					<pre class="CODE"><a name="pgfId-1087578"></a>  Object[][] data = new Object[][]{{&quot;row 1 col1&quot;, &quot;row 1 col2&quot; },</pre>					<pre class="CODE"><a name="pgfId-1087579"></a>                                   {&quot;row 2 col 1&quot;, &quot;row 2 col 2&quot;}};  Object[] headers = new Object[] {&quot;first header&quot;,&quot;second header&quot;};  DefaultTableModel model = new DefaultTableModel(data, headers);  table = new JTable(model);</pre>					<pre class="CODE-caption">

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -