?? ch5.htm
字號:
at any of the cells in the spreadsheet that didn't fit onscreen.This severely reduced the applet's usefulness, but this problemcan be fixed by adding scrollbars. With horizontal and verticalscrollbars, you can scroll to the cell you want to view; therefore,the spreadsheet's full contents can be used.<H3><A NAME="AddingtheScrollbarClass">Adding the Scrollbar Class</A></H3><P>The AWT Scrollbar class is used to create vertical or horizontalscrollbars. A box at the center of the scrollbar represents thescrollbar's current position; this box has been called the <I>thumbtack</I>,the <I>thumb</I>, or <I>elevator</I>, but in this discussion "thumbtack"will be used. The thumbtack can be moved in line increments (whenthe scrollbar arrows are pressed) or in page increments (whenthe scrollbar area between the arrows is clicked). The thumbtackcan also be dragged to a specific position.<P>A Scrollbar object can be created through a variety of constructors.The most useful constructor is one that takes five integer parameters.A good way to illustrate this constructor is to look at how thevertical and horizontal scrollbars are declared and created inthe SpreadsheetFrame:<BLOCKQUOTE><TT>Scrollbar vScroll; // The vertical scrollbar<BR>Scrollbar hScroll; // The horizontal scrollbar<BR>vScroll = new Scrollbar(Scrollbar.VERTICAL,1,1,1,numRows);<BR>hScroll = new Scrollbar(Scrollbar.HORIZONTAL,1,1,1,numCols);</TT></BLOCKQUOTE><P>The first parameter refers to the scrollbar's orientation, whichcan be defined by using either the <TT>Scrollbar.HORIZONTAL</TT>or <TT>Scrollbar.VERTICAL</TT> constant.The former is a scrollbar set horizontally across the native container;the latter is displayed up the side. Figure 5.1 shows what thespreadsheet applet looks like after the scrollbars are added.The orientation of the scrollbar can be retrieved through the<TT>getOrientation()</TT> method.<P><A HREF="f5-1.gif" ><B>Figure 5.1 </B>:<I> The spreadsheet applet with scrollbars.</I></A><P>The next parameter specifies the initial value of the scrollbar.This must be between the minimum and maximum scrollbar values,specified in the last two parameters, respectively. In the caseof the spreadsheet applet, the maximum value is the number ofrows or columns supported by the spreadsheet. These are set at<TT>26</TT> and <TT>40</TT>in the SpreadsheetApplet class. The scrollbar's initial valueof <TT>1</TT> indicates that the displaybegins at the top row and leftmost column of the spreadsheet.<P>The fourth parameter indicates the range of values that shouldbe traversed when you click on the paging portion of the scrollbar.This corresponds to the visible portion of the scrollbar area.For example, if 10 rows are currently displayed on the screen,then the range is <TT>10</TT>. Thisrange is also known as the <I>page increment</I> and can be setby the <TT>setPageIncrement()</TT>method. Since it is usually possible to resize a window that hasscrollbars, you will need to modify the page increment on-the-fly.This can involve somewhat lengthy code, so it isn't used in thespreadsheet applet. There also seems to be a problem with the<TT>setPageIncrement()</TT> methodin the version of AWT available at this time. Consequently, onlythe line increment and thumbtack drag aspects of scrollbars areset up for the spreadsheet applet.<P>Recall that the SpreadsheetFrame class uses GridBagLayout as itslayout mechanism. How the scrollbars are added to the frame displayprovides another interesting example of using the complex GridBagLayoutclass. See this book's CD-ROM to find out how the scrollbars areadded to the frame's GridBagLayout instance; this is defined inthe file SpreadsheetApplet.java.<H3><A NAME="HandlingScrollbarEvents">Handling Scrollbar Events</A></H3><P>The next step in creating and using scrollbars is to catch eventsinitiated by scrollbar actions. Five constants in the Event classare allocated for handling scrollbar events. These are listedin Table 5.2. The following code shows how the SpreadsheetFrameclass traps these events:<BLOCKQUOTE><TT>public boolean handleEvent(Event evt){<BR> switch(evt.id) {<BR>case Event.SCROLL_LINE_UP:<BR> case Event.SCROLL_ABSOLUTE:<BR> case Event.SCROLL_LINE_DOWN:<BR> case Event.SCROLL_PAGE_UP:<BR> case Event.SCROLL_PAGE_DOWN:<BR> if(evt.target instanceof Scrollbar) {<BR> scrollbarAction((Scrollbar)evt.target);<BR> } //end if<BR> returntrue;<BR></TT></BLOCKQUOTE><P><CENTER><B>Table 5.2. Scrollbar events.</B></CENTER><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD WIDTH=233><I>Event</I></TD><TD WIDTH=194><I>Description</I></TD></TR><TR VALIGN=TOP><TD WIDTH=233><TT>EVENT.SCROLL_LINE_UP</TT></TD><TD WIDTH=194>User hit the line-up arrow.</TD></TR><TR VALIGN=TOP><TD WIDTH=233><TT>EVENT.SCROLL_LINE_DOWN</TT></TD><TD WIDTH=194>User hit the line-down arrow.</TD></TR><TR VALIGN=TOP><TD WIDTH=233><TT>EVENT.SCROLL_PAGE_UP</TT></TD><TD WIDTH=194>User hit the page-up arrow.</TD></TR><TR VALIGN=TOP><TD WIDTH=233><TT>EVENT.SCROLL_PAGE_DOWN</TT></TD><TD WIDTH=194>User hit the page-down arrow.</TD></TR><TR VALIGN=TOP><TD WIDTH=233><TT>EVENT.SCROLL_ABSOLUTE</TT></TD><TD WIDTH=194>User moved the thumbtack.</TD></TR></TABLE></CENTER><P><P>The event-handling code calls the <TT>scrollbarAction()</TT>method, which goes as follows:<BLOCKQUOTE><TT>// Handle scroll bar actions...<BR> void scrollbarAction(Scrollbar sb) {<BR> if (sb.getOrientation() ==Scrollbar.VERTICAL)<BR> s.setNewTop(sb.getValue());<BR> else<BR> s.setNewLeft(sb.getValue());<BR> }</TT></BLOCKQUOTE><P>It checks to see whether a horizontal or vertical scrollbar hasbeen selected by using the <TT>getOrientation()</TT>method of the target and comparing it to the Scrollbar constantvalue. The code then gets the current location of the thumbtackwith the <TT>getValue()</TT> method.This returns a value between the minimum and maximum. If it isthe minimum value, then the thumbtack is at the top or leftmostposition of the scrollbar. The maximum value represents the bottomor rightmost position. This value is set to the appropriate methodof the SpreadsheetContainer class.<P>This class is modified to support scrollbars by introducing twovariables that indicate the top row and leftmost column to bedisplayed. When the scrollbar scrolls upward or downward, thedisplay's top row is adjusted in the corresponding direction.Likewise, moving the scrollbar left or right adjusts the columnof the spreadsheet drawn on the display's leftmost portion. Theintroduction of the <TT>topCell</TT>and <TT>leftCell</TT> integer variablesare used to track where the row and column display begins.<P>Listing 5.1 provides the two SpreadsheetContainer methods calledby the <TT>scrollbarAction()</TT>method shown above. These set the top row or leftmost column tobe displayed. The SpreadsheetContainer then repaints itself, displayingthe new selections. The following code shows how this displayworks.<HR><BLOCKQUOTE><B>Listing 5.1. Setting the top row and leftmost column of theSpreadsheetContainer object.<BR></B></BLOCKQUOTE><BLOCKQUOTE><TT>// Handle scrolling by setting new top...<BR> public void setNewTop(int newTop) {<BR> // Set top, taking into accountheadings and constraints...<BR> if (newTop < numRows)<BR> topCell= newTop;<BR> else<BR> topCell= numRows - 1;<BR> resetMarking();<BR> repaint();<BR> }<BR><BR> // Set new leftmost column...<BR> public void setNewLeft(int newLeft){<BR> // Set new left, taking intoaccount headings and constraints...<BR> if (newLeft < numColumns)<BR> leftCell= newLeft;<BR> else<BR> leftCell= numColumns - 1;<BR> resetMarking();<BR> repaint();<BR> }</TT></BLOCKQUOTE><HR><H3><A NAME="InsidetheSpreadsheetContainerPaintMe">Inside theSpreadsheetContainer Paint Methods</A></H3><P>Listing 5.2 shows the code involved in painting the SpreadsheetContainer.These routines paint the row and column headers on the sides,then fill up the interior with the evaluated values of the SpreadsheetCellobjects that fit in the painted region. This painting has as itsorigin the <TT>topCell</TT> variableas the top row to display and the <TT>leftCell</TT>variable as the first column of SpreadsheetCell objects to bedisplayed.<HR><BLOCKQUOTE><B>Listing 5.2. SpreadsheetContainer paint methods.<BR></B></BLOCKQUOTE><BLOCKQUOTE><TT>// Update message sent when repaintingis needed...<BR> // Prevent paint from getting cleared out...<BR> public void update(Graphics g) {<BR> paint(g);<BR> }<BR><BR>// Draw the displayable spreadsheet contents...<BR>public synchronized void paint (Graphics g) {<BR> // Go through the calculations of the paint while painting...<BR> calculatePaint(g,true,0,0);<BR>}<BR><BR>// This goes through the motions of calculating what is on the<BR>// screen and either calculates coordinates or paints...<BR>// If it is not paint, returns cell that fits in hit region...<BR>SpreadsheetCell calculatePaint(Graphics g,boolean bPaint,int xHit,intyHit) {<BR> // Get the current size of the display area...<BR> Dimension dm = size();<BR> Rectangle r = null; // The clippingrectangle...<BR> Rectangle cellRect = null; // The cell clipping rectangle...<BR> // Calculate the cell width and height<BR> // Cell should be wide enough to show 8 digits...<BR> if (bPaint == true) {<BR> cellWidth = g.getFontMetrics().stringWidth("12345.67");<BR> cellHeight = g.getFontMetrics().getHeight();<BR> r = g.getClipRect();<BR> } // end if<BR> // Figure out how many rows and cols can be displayed<BR> int nCol = Math.min(numColumns,dm.width / cellWidth);<BR> int nRow = Math.min((numRows + 1),dm.height / cellHeight);<BR><BR> // Draw the cells...<BR> int index,i,x,j,y,currentRow,currentCol;<BR> -nRow;<BR> // Go across the rows...<BR> // Show the headers and adjust for top and left cell...<BR> for (currentRow = i = 0; i < nRow; ++i) {<BR> y = cellHeight + (i * cellHeight);<BR> // Go across the columns...<BR> for (currentCol = j = 0; j < nCol; ++j) {<BR> index = (currentRow * numColumns) + currentCol;<BR> x = (j * cellWidth);<BR> // Paint if told to...<BR> if (bPaint == true) {<BR> // See if it is in the intersection of the<BR> // clipping rectangle<BR> cellRect = new Rectangle(x,y,cellWidth,cellHeight);<BR> if (r.intersects(cellRect)) {<BR> // Paint if you are at a valid row...<BR> if ((currentRow < numRows) && (currentCol < numColumns)){<BR> matrix[index].paint(g,x,y,<BR> cellWidth,cellHeight);<BR> } // end inner if<BR> else { // Otherwise, fill it in with grey...<BR> emptyCell.paint(g,x,y,cellWidth,cellHeight);<BR> } // end else<BR> } // end if<BR> } // end if<BR> else { // Otherwise, see if cell fits for highlightcalculations…<BR>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -