1. Trang chủ
  2. » Công Nghệ Thông Tin

Beginning Java SE 6 Platform From Novice to Professional phần 4 pps

51 432 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 51
Dung lượng 451,13 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Then pass the resulting RowSorter to JTable’s public void setRowSorterRowSorter... If you explicitly attach a Comparatorto a column via public void setComparatorint column, Comparator co

Trang 1

• Its abstract javax.swing.DefaultRowSorter<M, I>subclass, which supports sortingand filtering around a grid-based data model

• The DefaultRowSorter<M, I>’s javax.swing.table.TableRowSorter<M extends TableModel>subclass, which provides table component sorting and filtering via a javax.swing.table.TableModel

It is easy to introduce sorting to a table component After creating the table’s model and initializing the table component with this model, pass the model to

TableRowSorter<M extends TableModel>’s constructor Then pass the resulting RowSorter<M>

to JTable’s public void setRowSorter(RowSorter<? extends TableModel> sorter)method:TableModel model =

JTable table = new JTable (model);

RowSorter<TableModel> sorter = new TableRowSorter<TableModel> (model);

table.setRowSorter (sorter);

To demonstrate how easy it is to add sorting to your tables, I have designed a simpleapplication that itemizes some grocery items and their prices in a two-column table.Listing 4-3 presents the source code

{ "Bag of potatoes", 10.98 },{ "Magazine", 7.99 },

Trang 2

{ "Can of soup", 0.89 },{ "DVD movie", 39.99 }};

TableModel model = new DefaultTableModel (rows, columns);

JTable table = new JTable (model);

RowSorter<TableModel> sorter = new TableRowSorter<TableModel> (model);

new PriceList1 ("Price List #1");

}};

java.awt.EventQueue.invokeLater (r);

}}

Run this application, and you will see output similar to the table shown in Figure 4-3

Figure 4-3.Unsorted table

Click the Item column’s header, and the rows will sort in ascending order of this column’s values A small up triangle will appear beside the column name to identify

the current sort direction, as shown in Figure 4-4

Trang 3

Figure 4-4.Sorted table based on the Item column

Suppose that you decide to sort the items in ascending order of price (smallest priceitem first) After clicking the Price column’s header, a small up triangle appears beside the column name However, as Figure 4-5 indicates, the sort result is unexpected

Figure 4-5.Prices are sorted based on string comparisons.

The prices are not sorted based on their numerical values If they were, the row taining DVD movie and 39.99 would be the last row in the table Instead, rows have beensorted based on the string representations of the price values

con-According to the JDK documentation for the TableRowSorter<M extends TableModel>class, java.util.Comparator<T>comparators are used to compare objects during a sort.The Comparator<T>comparator that is chosen is based on five rules, which I have

excerpted (with minor additions) from the documentation (in the top-down order inwhich the decision is made):

• If a Comparator<T>has been specified for the column by the setComparatormethod,use it

• If the column class as returned by getColumnClassis String, use the Comparator<T>returned by Collator.getInstance()

• If the column class implements Comparable<T>, use a Comparator<T>that invokes thecompareTomethod

Trang 4

• If a javax.swing.table.TableStringConverterhas been specified, use it to convert thevalues to Strings and then use the Comparator<T>returned by Collator.getInstance().

• Otherwise, use the Comparator<T>returned by Collator.getInstance()on the results from calling toStringon the objects

If you explicitly attach a Comparator<T>to a column via public void setComparator(int column, Comparator<?> comparator), this Comparator<T>will

be used during the sort (as indicated by the first rule) In contrast, it is easier to

subclass javax.swing.table.DefaultTableModeland override the public Class

getColumnClass(int column)method, which is what Listing 4-4 accomplishes

{ "Bag of potatoes", 10.98 },{ "Magazine", 7.99 },

{ "Can of soup", 0.89 },{ "DVD movie", 39.99 }};

TableModel model = new DefaultTableModel (rows, columns)

{

public Class getColumnClass (int column) {

if (column >= 0 &&

Trang 5

column <= getColumnCount ()) return getValueAt (0, column).getClass (); else

return Object.class;

}

};

JTable table = new JTable (model);

RowSorter<TableModel> sorter = new TableRowSorter<TableModel> (model);table.setRowSorter (sorter);

getContentPane ().add (new JScrollPane (table));

setSize (200, 150);

setVisible (true);

}public static void main (String [] args){

Runnable r = new Runnable ()

{public void run (){

new PriceList2 ("Price List #2");

}};

java.awt.EventQueue.invokeLater (r);

}}

DefaultTableModelalways returns Object.classfrom its getColumnClass()method.According to the fifth rule, this results in the toString()method being called during sorting (and the result shown previously in Figure 4-5) By overriding getColumnClass()and having the overridden method return the appropriate type, sorting takes advantage

of the returned Classobject’s Comparable<T>(if there is one), according to the third rule.Figure 4-6 shows the properly sorted price list

Trang 6

Figure 4-6.The DVD movie item is now displayed in the last row, where it should be based

on its price.

Tip JTable’s public void setAutoCreateRowSorter(boolean autoCreateRowSorter)method

offers the simplest way to attach a row sorter to a table component For more information about this

method, check out “Mustang (Java SE 6) Gallops into Town” (http://www.informit.com/articles/

article.asp?p=661371&rl=1)

Filtering the Table’s Rows

The DefaultRowSorter<M, I>class provides a public void setRowFilter(RowFilter<? super

M,? super I> filter)method for installing a filter that lets you determine which rows are

displayed and which rows are hidden You can pass to filteran instance of one of the

filters returned from the static methods in the abstract javax.swing.RowFilter<M, I>class,

or pass nullto remove any installed filter and allow all rows to be displayed Table 4-2

shows RowFilter’s filter factory methods

Table 4-2.RowFilter Filter Factory Methods

public static <M,I> RowFilter<M,I> Returns a row filter that includes a row if all

andFilter(Iterable<? extends RowFilter<? of the specified row filters include the row.

super M,? super I>> filters)

public static <M,I> RowFilter<M,I> Returns a row filter that includes only those rows

dateFilter(RowFilter.ComparisonType that have at least one java.util.Date value in

type, Date date, int indices) the indices columns that meets the criteria

specified by type If the indices argument is not specified, all columns are checked.

public static <M,I> RowFilter<M,I> Returns a row filter that includes a row if the

notFilter(RowFilter<M,I> filter) specified row filter does not include the row.

public static <M,I> RowFilter<M,I> Returns a row filter that includes only those rows

numberFilter(RowFilter.ComparisonType type, that have at least one Number value in the

Number number, int indices) indices columns that meets the criteria

specified by type If the indices argument is not specified, all columns are checked.

Continued

Trang 7

public static <M,I> RowFilter<M,I> Returns a row filter that includes a row if any of orFilter(Iterable<? extends the specified row filters include the row RowFilter<? super M,? super I>> filters)

public static <M,I> RowFilter<M,I> Returns a row filter that uses a regular expression regexFilter(String regex, int indices) to determine which rows to include Each

column identified by indices is checked The row is returned if one of the column values matches the regex If the indices argument is not specified, all columns are checked.

Row filtering is useful in the context of a database application Rather than submit

a potentially expensive SQL SELECTstatement to the database management system toretrieve a subset of a table’s rows based on some criteria, filtering rows via a table compo-nent and its row filter is bound to be much faster For example, suppose your table

component presents a log of bugs (bug identifier, description, date filed, and dated fixed)found while testing software Furthermore, suppose that you want to present only thoserows whose description matches some entered regular expression Listing 4-5 presents anapplication that accomplishes this task

private static DateFormat df;

public BugLog (String title) throws ParseException

Table 4-2.Continued

Trang 8

{super (title);

{ 1000, "Crash during file read", df.parse ("2/10/07 10:12 am"),df.parse ("2/11/07 11:15 pm") },

{ 1020, "GUI not repainted", df.parse ("3/5/07 6:00 pm"),df.parse ("3/8/07 3:00 am") },

{ 1025, "File not found exception", df.parse ("1/18/07 9:30 am"),df.parse ("1/22/07 4:13 pm") }

};

TableModel model = new DefaultTableModel (rows, columns);

JTable table = new JTable (model);

final TableRowSorter<TableModel> sorter;

sorter = new TableRowSorter<TableModel> (model);

table.setRowSorter (sorter);

getContentPane ().add (new JScrollPane (table));

JPanel pnl = new JPanel ();

pnl.add (new JLabel ("Filter expression:"));

final JTextField txtFE = new JTextField (25);

pnl.add (txtFE);

JButton btnSetFE = new JButton ("Set Filter Expression");

ActionListener al;

al = new ActionListener (){

public void actionPerformed (ActionEvent e){

String expr = txtFE.getText ();

sorter.setRowFilter (RowFilter.regexFilter (expr));

sorter.setSortKeys (null);

}};

Trang 9

Runnable r = new Runnable ()

{public void run (){

try{new BugLog ("Bug Log");

}catch (ParseException pe){

JOptionPane.showMessageDialog (null,

pe.getMessage ());System.exit (1);

}}};

EventQueue.invokeLater (r);

}}

Run this application, specify [F|f]ileas a regular expression, and click the Set FilterExpression button In response, only the first and third rows will be displayed To restoreall rows, simply leave the text field blank and click the button

Note The sorter.setSortKeys (null);method call unsorts the view of the underlying model afterchanging the row filter In other words, if you have performed a sort by clicking some column header, thesorted view will revert to the unsorted view following this method call

Trang 10

Look and Feel Enhancements

Unlike other Java-based GUI toolkits, Swing decouples its API from the underlying

plat-form’s windowing system toolkit This decoupling has resulted in trade-offs between

platform independence and the faithful reproduction of a native windowing system’s

look and feel Because of user demand for the best possible fidelity of system look and

feels, Java SE 6 improves the Windows look and feel and the GTK look and feel by

allow-ing them to use the native widget rasterizer to render Swallow-ing’s widgets (components, if

you prefer)

Starting with Java SE 6, Sun engineers have reimplemented the Windows look andfeel to use UxTheme, a Windows API hammered out between Microsoft and the author

of the popular WindowBlinds (http://www.stardock.com/products/windowblinds/) theming

engine This API exposes the manner in which Windows controls are rendered As a

result, a Swing application running under Windows XP should look like XP; when this

application runs under Windows Vista, it should look like Vista For completeness, the

original Windows look and feel is still available as the Windows Classic look and feel

(com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel)

Sun engineers have also reimplemented the GTK look and feel to employ native calls to GIMP Toolkit (GTK) engines, which makes it possible to reuse any installed GTK

engine to render Swing components If you are running Linux or Solaris, you can now

use all of your favorite GTK themes to render Swing applications and make these

applications integrate (visually) nicely with the desktop

New SwingWorker

Multithreaded Swing programs can include long-running tasks, such as a task that

per-forms an exhaustive database search across a network If these tasks are run on the

event-dispatching thread (the thread that dispatches events to GUI listeners), the

application will become unresponsive For this reason, a task must run on a worker

thread, which is also known as a background thread When the task completes and the

GUI needs to be updated, the worker thread must make sure that the GUI is updated

on the event-dispatching thread, because most Swing methods are not thread-safe

Although the javax.swing.SwingUtilities public static void invokeLater(Runnable doRun)

and public static void invokeAndWait(Runnable doRun)methods (or their java.awt

EventQueuecounterparts) could be used for this purpose, it is easier to work with Java SE

6’s new javax.swing.SwingWorker<T, V>class, because this class takes care of interthread

communication

Trang 11

Note Although the new SwingWorker<T, V>class shares the same name as an older SwingWorkerclass, which was widely used for some of the same purposes (but never officially part of Swing), the twoclasses are very different For example, methods that perform the same functions have different names.Also, a separate instance of the new SwingWorker<T, V>class is required for each new background task,whereas old SwingWorkerinstances were reusable.

SwingWorker<T, V>is an abstract class that implements the java.util.concurrent.RunnableFuture<T, V>interface A subclass must implement the protected abstract TdoInBackground()method, which runs on a worker thread, to perform a long-runningtask When this method finishes, the protected void done()method is invoked on theevent-dispatching thread By default, this method does nothing However, you can override done()to safely update the GUI

Type parameter Tspecifies doInBackground()’s return type, and is also the return type of the SwingWorker<T, V>class’s public final T get()and public final T get(longtimeout, TimeUnit unit)methods These methods, which normally wait indefinitely orfor a specific period of time for a task to complete, return immediately with the task’sresult when invoked from within the done()method

Type parameter Vspecifies the type for interim results calculated by the workerthread Specifically, this type parameter is used by the protected final void

publish(V chunks)method, which is designed to be called from within

doInBackground(), to send intermediate results for processing to the

event-dispatching thread These results are retrieved by an overridden protected void

process(List<V> chunks)method whose code runs on the event-dispatching thread

If there are no intermediate results to process, you can specify Voidfor V(and avoid using the publish()and process()methods)

Image loading is one example where SwingWorker<T, V>comes in handy Without thisclass, you might consider loading all images before displaying the GUI, or loading themfrom the event-dispatching thread If you load the images prior to displaying the GUI,there might be a significant delay before the GUI appears Of course, the new splash-screen feature (see Chapter 3) obviates this concern If you attempt to load the imagesfrom the event-dispatching thread, the GUI will be unresponsive for the amount of time

it takes to finish loading all of the images For an example of using SwingWorker<T, V>

to load images, check out the “Simple Background Tasks” lesson in The Java Tutorial

(http://java.sun.com/docs/books/tutorial/uiswing/concurrency/simple.html)

To demonstrate SwingWorker<T, V>, I’ve created a simple application that lets youenter an integer and click a button to find out if this integer is prime This application’sGUI consists of a labeled text field for entering a number, a button for checking if thenumber is prime, and another label that shows the result Listing 4-6 presents the application’s source code

Trang 12

super ("Prime Check");

setDefaultCloseOperation (EXIT_ON_CLOSE);

final JLabel lblResult = new JLabel (" ");

JPanel pnl = new JPanel ();

pnl.add (new JLabel ("Enter integer:"));

final JTextField txtNumber = new JTextField (10);

pnl.add (txtNumber);

JButton btnCheck = new JButton ("Check");

ActionListener al;

al = new ActionListener (){

public void actionPerformed (ActionEvent ae){

try{BigInteger bi = new BigInteger (txtNumber.getText ());

lblResult.setText ("One moment ");

new PrimeCheckTask (bi, lblResult).execute ();

}catch (NumberFormatException nfe){

lblResult.setText ("Invalid input");

}

Trang 13

Runnable r = new Runnable ()

{public void run (){

new PrimeCheck ();

}};

EventQueue.invokeLater (r);

}}

class PrimeCheckTask extends SwingWorker<Boolean, Void>

{

private BigInteger bi;

private JLabel lblResult;

PrimeCheckTask (BigInteger bi, JLabel lblResult){

Trang 14

if (isPrime) lblResult.setText ("Integer is prime");

else lblResult.setText ("Integer is not prime");

} catch (InterruptedException ie) {

lblResult.setText ("Interrupted");

} } catch (ExecutionException ee) {

String reason = null;

Throwable cause = ee.getCause ();

if (cause == null) reason = ee.getMessage ();

else reason = cause.getMessage ();

lblResult.setText ("Unable to determine primeness");

} }

}

When the user clicks the button, its action listener invokes new PrimeCheckTask (bi, lblResult).execute ()to instantiate and execute an instance of PrimeCheckTask,

a SwingWorker<T, V>subclass The biparameter references a java.math.BigInteger

argument that contains the integer to check The lblResultparameter references a

javax.swing.Jlabel, which shows the prime/not prime result (or an error message)

Execution results in a new worker thread starting and invoking the overridden doInBackground()method When this method completes, it returns a value that is stored

Trang 15

in a future (A future is an object that stores the result of an asynchronous computation,

as discussed in Chapter 2.) Furthermore, method completion results in a call to the ridden done()method on the event-dispatching thread Within this method, the call toget()returns the value stored within the future, which is then used to set the label’s text.The doInBackground()method invokes bi.isProbablePrime (1000)to determine if theinteger stored in biis a prime number It returns true if the probability that the integer isprime exceeds 1-1/21000(which is practically 100% certainty that the integer is prime).Because it takes longer to determine whether an integer with a lot of digits is a prime, the

over-“One moment ” message will be displayed for longer periods when such a number isentered As long as this message is displayed, the GUI remains responsive You can easilyclose the application, or even click the Check button (although you should not click thisbutton until you see the message stating whether or not the integer is prime)

Text Component Printing

Java 5 integrated printing support into JTablevia several new print()methods and a new getPrintable()method Java SE 6 does the same thing for javax.swing.JTextField,javax.swing.JTextArea, and javax.swing.JEditorPaneby integrating new methods intotheir common JTextComponentsuperclass

One new method is public Printable getPrintable(MessageFormat headerFormat,MessageFormat footerFormat) It returns a java.awt.print.Printablethat prints the con-tents of this JTextComponentas it looks on the screen, but reformatted so that it fits on theprinted page You can wrap this Printableinside another Printableto create complexreports and other kinds of complex documents Because Printableshares the documentwith the JTextComponent, this document must not be changed while the document isbeing printed Otherwise, the printing behavior is undefined

Another new method is public boolean print(MessageFormat headerFormat, MessageFormat footerFormat, boolean showPrintDialog, PrintService service,

PrintRequestAttributeSet attributes, boolean interactive) This method prints thisJTextComponent’s content Specify its parameters as follows:

• Specify page header and footer text via headerFormatand footerFormat.Eachjava.text.MessageFormatidentifies a format pattern, which can contain only a single format item—an Integerthat identifies the current page number—in addition to literal text Pass nullto headerFormatif there is no header; pass null

to footerFormatif there is no footer

• If you would like to display a print dialog (unless headless mode is in effect) that lets the user change printing attributes or cancel printing, pass trueto showPrintDialog

Trang 16

• Specify the initial javax.print.PrintServicefor the print dialog via service Pass nullto use the default print service.

• Specify a javax.print.attribute.PrintRequestAttributeSetcontaining an initial set

of attributes for the print dialog via attributes These attributes might be a number

of copies to print or supply needed values when the dialog is not shown Pass null

if there are no print attributes

• Determine if printing is performed in interactivemode If headless mode is not

in effect, passing trueto interactivecauses a modal (when called on the dispatching thread; otherwise, nonmodal) progress dialog with an abort option

to be displayed for the duration of printing If you call this method on the dispatching thread with interactiveset to false, all events (including repaints) are blocked until printing completes As a result, you should do this only if there

event-is no vevent-isible GUI

A java.awt.print.PrinterExceptionis thrown if the print job is aborted because of aprint system error If the current thread is not allowed to initiate a print job request by

an installed security manager, the print()method throws a SecurityException

Two convenience methods are also provided public boolean print(MessageFormatheaderFormat, MessageFormat footerFormat)invokes the more general print()method via

print(headerFormat, footerFormat, true, null, null, true) The public boolean print()

method invokes the more general print()method via print(null, null, true, null,

Trang 17

private JTextField txtURL;

private JTabbedPane tp;

private JLabel lblStatus;

private ImageIcon ii = new ImageIcon ("close.gif");

private Dimension iiSize = new Dimension (ii.getIconWidth (),

ii.getIconHeight ());

private int tabCounter = 0;

public BrowserWithPrint (){

super ("Browser");

setDefaultCloseOperation (EXIT_ON_CLOSE);

JMenuBar mb = new JMenuBar ();

JMenu mFile = new JMenu ("File");

JMenuItem miFile = new JMenuItem ("Add Tab");

ActionListener addTabl = new ActionListener ()

{public void actionPerformed (ActionEvent e){

addTab ();

}};

Component c = tp.getSelectedComponent ();JScrollPane sp = (JScrollPane) c;

c = sp.getViewport ().getView ();

JEditorPane ep = (JEditorPane) c;

try

Trang 18

{ ep.print ();

} catch (PrinterException pe) {

JOptionPane.showMessageDialog (BrowserWithPrint.this,

"Print error: "+pe.getMessage ());

}

}};

miPrint.addActionListener (printl);

mFile.add (miPrint);

mb.add (mFile);

setJMenuBar (mb);

JPanel pnlURL = new JPanel ();

pnlURL.setLayout (new BorderLayout ());

pnlURL.add (new JLabel ("URL: "), BorderLayout.WEST);

txtURL = new JTextField ("");

pnlURL.add (txtURL, BorderLayout.CENTER);

getContentPane ().add (pnlURL, BorderLayout.NORTH);

tp = new JTabbedPane ();

addTab ();

getContentPane ().add (tp, BorderLayout.CENTER);

lblStatus = new JLabel (" ");

getContentPane ().add (lblStatus, BorderLayout.SOUTH);

ActionListener al;

al = new ActionListener (){

public void actionPerformed (ActionEvent ae){

try{Component c = tp.getSelectedComponent ();

JScrollPane sp = (JScrollPane) c;

c = sp.getViewport ().getView ();

JEditorPane ep = (JEditorPane) c;

ep.setPage (ae.getActionCommand ());

Trang 19

miPrint.setEnabled (true);

}catch (Exception e){

lblStatus.setText ("Browser problem: "+e.getMessage ());}

}};

JEditorPane ep = new JEditorPane ();

ep.setEditable (false);

ep.addHyperlinkListener (this);

tp.addTab (null, new JScrollPane (ep));

JButton tabCloseButton = new JButton (ii);

tabCloseButton.setActionCommand (""+tabCounter);

tabCloseButton.setPreferredSize (iiSize);

ActionListener al;

al = new ActionListener (){

public void actionPerformed (ActionEvent ae){

JButton btn = (JButton) ae.getSource ();

tp.removeTabAt (i);

break;

}

Trang 20

tabCloseButton.addActionListener (al);

if (tabCounter != 0){

JPanel pnl = new JPanel ();

else

if (evtype == HyperlinkEvent.EventType.EXITED)lblStatus.setText (" ");

}public static void main (String [] args){

Runnable r = new Runnable ()

{public void run (){

new BrowserWithPrint ();

}};

EventQueue.invokeLater (r);

}}

Trang 21

After selecting the Print menu item, the current tab’s editor pane is retrieved and itsprint()method is invoked to print the HTML content Figure 4-7 shows the print dialog.

Figure 4-7.The print dialog presents its own tabbed interface.

compo-combination of a string label and an icon on a tab header

The SpringLayout layout manager makes it possible to lay out a GUI using springsand struts Although this layout manager predates Java SE 6, it has suffered from bugssuch as not always correctly resolving its constraints Java SE 6 fixes this bug by basingthe algorithm used to calculate springs on the last two specified springs, along each axis.Java SE 6 has also greatly improved drag-and-drop for Swing components Theseimprovements have to do with telling a component how to determine drop locations and having Swing provide all relevant transfer information during a transfer

The ability to sort and filter a JTable’s contents has been simplified by Java SE 6 Byclicking a column header, you can sort rows according to the column’s contents You canalso filter rows based on regular expressions and other criteria, and display only thoserows that match the criteria

Trang 22

Java SE 6 improves the Windows look and feel and the GTK look and feel by allowingthem to use the native widget rasterizer to render Swing’s components These improve-

ments make it possible to faithfully reproduce a native windowing system’s look and feel

on Windows, Linux, and Solaris platforms

A multithreaded Swing program can include a long-running task that needs to updatethe GUI when it completes This task must not be run on the event-dispatching thread;

otherwise, the GUI will be unresponsive The GUI must not be updated on any thread other

than the event-dispatching thread; otherwise, the program will violate the single-threaded

nature of the Swing toolkit Because it can be difficult to code for these requirements, Java

SE 6 introduces a new SwingWorker<T, V>class A subclass implements the doInBackground()

method, which runs on a worker thread, to perform a long-running task When this method

finishes, the done()method (overridden by the subclass) is invoked on the event-dispatching

thread, and the GUI can be safely updated from that method

Finally, Java SE 6 integrates printing support into JTextComponentso that you canprint the contents of various text components This support consists of a getPrintable()

method and three print()methods

Test Your Understanding

How well do you understand the changes to the Swing toolkit? Test your understanding

by answering the following questions and performing the following exercises (The

answers are presented in Appendix D.)

1. What does indexOfTabComponent()return if a tab is not associated with its Componentargument?

2. Which of DropMode.INSERTand DropMode.USE_SELECTIONcauses selected text to betemporarily deselected?

3. JTable’s public int convertRowIndexToModel(int viewRowIndex)method maps arow’s index in terms of the view to the underlying model The public int convertRowIndexToView(int modelRowIndex)method maps a row’s index in terms ofthe model to the view To better understand the relationship between the view andmodel indices, extend PriceList1with a list selection listener that presents theselected row’s (view) index and model index (via convertRowIndexToModel()) via anoption pane dialog As you sort this table via different column headers and selectdifferent rows (you might want to set the table’s selection mode to single selec-tion), you will notice that sorting affects only the view and not the model

4. Why is it necessary to have SwingWorker<T, V>’s doInBackground()method return avalue, and then retrieve this value from within the done()method?

5. Modify BrowseWithPrint.java(Listing 4-7) to work with PrintRequestAttributeSet

Trang 24

Java SE 6’s internationalization (i18n) support ranges from Abstract Windowing

Toolkit-oriented non-English locale input bug fixes (see Chapter 3), to network-oriented

internationalized domain names (see Chapter 8), to these i18n-specific features:

• Japanese Imperial Era calendar

• Locale-sensitive services

• New locales

• Normalizer API

• ResourceBundleenhancements

Japanese Imperial Era Calendar

Many Japanese commonly use the Gregorian calendar Because Japanese governments

also use the Japanese Imperial Era calendar for various government documents, Java SE 6

introduces support for this calendar

In the Japanese Imperial Era calendar, eras are based on the reigning periods ofemperors; an era begins with an emperor’s ascension This calendar regards a year as a

combination of a Japanese era name (Heisei, for example) and the one-based year

num-ber within this era For example, Heisei 1 corresponds to 1989, and Heisei 19 corresponds

to 2007 Other eras supported by Java’s implementation of the Japanese Imperial Era

cal-endar are Meiji, Taisho, and Showa The calcal-endar rules keep track of eras and years

Date Handling

You can obtain an instance of the Japanese Imperial Era calendar by invoking the

java.util.Calendarclass’s public static Calendar getInstance(Locale aLocale)method

153

C H A P T E R 5

Trang 25

with ja_JP_JPas the locale After obtaining this instance, you can set, fetch, and modifydates, as follows:

Calendar cal = Calendar.getInstance (new Locale ("ja", "JP", "JP"));

cal.setTime (new Date ());

System.out.println (cal.get (Calendar.ERA));

System.out.println (cal.get (Calendar.YEAR));

cal.add (Calendar.DAY_OF_MONTH, -120);

System.out.println (cal.get (Calendar.ERA));

System.out.println (cal.get (Calendar.YEAR));

If the current date were April 13, 2007, for example, the first two System.out.println()method calls would output 4 (which corresponds to the Heisei era) and 19, respectively.After subtracting 120 days from this date, the era would remain the same, but the yearwould change to 18

Note Sun’s Supported Calendars documentation (http://java.sun.com/javase/6/docs/

technotes/guides/intl/calendar.doc.html) provides a detailed look at its support for the JapaneseImperial Era calendar

Calendar Page Display

Let’s suppose you want to create a Swing program whose calendar page component presents a calendar page for the current month This component will adapt to differentcalendars based on locale For simplicity, let’s limit this program to English Gregorian,Japanese Gregorian, and Japanese Imperial Era calendars Let’s also assume that you’veinstalled appropriate fonts for rendering Japanese text The requirements for this pro-gram are as follows:

Present the month and era using locale-specific text Both requirements are

accom-modated by Calendar’s new public String getDisplayName(int field, int style,Locale locale)method, which is used with Calendar’s new LONGand SHORTstyle constants to obtain locale-specific display names with long and short styles (January versus Jan, for example) for certain calendar fields, such as Calendar.ERA.This method returns null if no string representation is applicable to the specific calendar field

Ngày đăng: 09/08/2014, 14:21

TỪ KHÓA LIÊN QUAN