Tải bản đầy đủ - 0 (trang)
6 A Comparison: Constructors Versus Static Methods

6 A Comparison: Constructors Versus Static Methods

Tải bản đầy đủ - 0trang

This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



setContentPane(desk);

// Add a simple menu bar.

JMenuBar mb = new JMenuBar( );

setJMenuBar(mb);

JMenu menu = new JMenu("Dialog");

JMenu imenu = new JMenu("Internal");

mb.add(menu);

mb.add(imenu);

final JMenuItem construct = new JMenuItem("Constructor");

final JMenuItem stat = new JMenuItem("Static Method");

final JMenuItem iconstruct = new JMenuItem("Constructor");

final JMenuItem istat = new JMenuItem("Static Method");

menu.add(construct);

menu.add(stat);

imenu.add(iconstruct);

imenu.add(istat);

// Create our JOptionPane. We're asking for input, so we call setWantsInput.

// Note that we cannot specify this via constructor parameters.

optPane = new JOptionPane(message, msgType, optType);

optPane.setWantsInput(true);

// Add a listener for each menu item that will display the appropriate

// dialog/internal frame.

construct.addActionListener(new ActionListener( ) {

public void actionPerformed(ActionEvent ev) {

// Create and display the dialog.

JDialog d = optPane.createDialog(desk, title);

d.setVisible(true);

respond(getOptionPaneValue( ));

}

});

stat.addActionListener(new ActionListener( ) {

public void actionPerformed(ActionEvent ev) {

String s = JOptionPane.showInputDialog

(desk, message, title, msgType);

respond(s);

}

});

iconstruct.addActionListener(new ActionListener( ) {



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



public void actionPerformed(ActionEvent ev) {

// Create and display the dialog.

JInternalFrame f = optPane.createInternalFrame(desk, title);

f.setVisible(true);

// Listen for the frame to close before getting the value from it.

f.addPropertyChangeListener(new PropertyChangeListener( ) {

public void propertyChange(PropertyChangeEvent ev) {

if ((ev.getPropertyName( ).equals(JInternalFrame.IS_CLOSED_PROPERTY))

&& (ev.getNewValue( ) == Boolean.TRUE)) {

respond(getOptionPaneValue( ));

}

}

});

}

});

istat.addActionListener(new ActionListener( ) {

public void actionPerformed(ActionEvent ev) {

String s = JOptionPane.showInternalInputDialog

(desk, message, title, msgType);

respond(s);

}

});

}

// This method gets the selected value from the option pane and resets the

// value to null so we can use it again.

protected String getOptionPaneValue( ) {

// Get the result . . .

Object o = optPane.getInputValue( );

String s = "";

if (o != null)

s = (String)o;

Object val = optPane.getValue( ); // which button?

// Check for Cancel button or closed option.

if (val != null) {

if (val instanceof Integer) {

int intVal = ((Integer)val).intValue( );

if((intVal == JOptionPane.CANCEL_OPTION) ||

(intVal == JOptionPane.CLOSED_OPTION))

s = "";



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



.



}

}

// A little trick to clean the text field. It is updated only if the initial

// value is changed. To do this, we'll set it to a dummy value ("X")

// and then clear it.

optPane.setValue("");

optPane.setInitialValue("X");

optPane.setInitialValue("");

return s;

}

protected void respond(String s) {

if (s == null)

System.out.println("Never mind.");

else

System.out.println("You entered: " + s);

}

protected JOptionPane optPane;

}



The user interface for this example (Figure 10-14) is simple. We provide two menus: one to create standard dialogs

and one to create internal frame dialogs. Each menu allows us to create a dialog using the JOptionPane we're

holding (created via a constructor) or create a new dialog with a static method call.



Figure 10-14. OptPaneComparison display



There are a few details here worth pointing out. First, notice that we called setWantsInput(true) on our



JOptionPane object. This is how we create a pane that looks like those created by the

showInputDialog( ) methods.

Without this call, there would not be a text field in our dialog.

The next point of interest is the way we handle the JInternalFrame we get from theJOptionPane . Since this is just

an ordinary internal frame, we don't have any simple way to block while we wait for input. Instead, we add a property



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



change listener to the frame, which will wait for the frame to be closed. Alternatively, we could have added a property

change listener to the JOptionPane and listened for theINPUT_VALUE_PROPERTY.

One last thing to point out is the little trick at the end of our getOptionPaneValue( ) method. We want to clear the

value from the text field so that it won't show up there the next time we use the same option pane. Since we have no

[11]

way of getting to the text field directly, and no way of explicitly clearing the value,

we resort to making two

changes to the initial value of the field. The reason we have to make two calls is that the text field is cleared only

when the initialValue property changes. If we just set it to an empty string every time, that wouldn't be considered a

change, so the field wouldn't be updated.

[11]



The setValue( ) call with an empty string might seem promising, but it isn't enough.



In this example, we held onto the JOptionPane object. You might be tempted to hold onto theJDialog you get from

the pane instead. This is generally not a good idea. The JOptionPane "disposes" of the dialog when it closes,

meaning that, among other things, its peer is destroyed. It's easier to reuse the JOptionPane . Similar difficulties

arise if you try to reuse the JInternalFrame created by theJOptionPane . Reusing theJOptionPane seems like a

safer strategy, but there are still problems.



Reusing a JOptionPane is not recommended. Read this section for details.



If you experiment with the program carefully, you'll discover some lingering and subtle problems with any attempt to

reuse a single JOptionPane for multiple interactions with the user—for example, use theConstructor method in the

Dialog menu, enter a name, and then click on OK. Then try the same method again, enter some text (or not, it doesn't

make a difference), and close the window manually instead of clicking on either of the buttons. The program will

report that you entered the same name as when you last clicked on OK, and there's no way to get it to forget this!

You can even show the dialog multiple times and click on Cancel. If you then show it and close the window again,

you'll see that the program still believes you entered the name you last said "OK" to.

This problem, on top of the fact that we needed to resort to trickery to get an empty initial value displayed at all,

suggests that any savings in efficiency we might gain by reusing a JOptionPane are more than offset by the fact

that, at least as it is currently implemented, this is not a safe or well-supported thing to do.

If you want to see even more disturbing behavior, remove the line in the "little trick" that reads



optPane.setValue(""). The program seems at first to work the same way, but if you use the Constructor option in

the Internal menu and try to enter the same name more than once, the OK button fails to work, leaving the internal

frame open. Trying to cancel that method twice in a row fails in the same way.



10.6.1 Nonstatic Methods

Most of the



methods defined in JOptionPane are static (or accessors for the pane's properties). Here are the only



other nonstatic methods in the class:



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



.



public JDialog createDialog(Component parentComponent, String title)

Create a new JDialog containing thisJOptionPane . The dialog's parent is the specified component, and

the input string is used as the window's title. The dialog is centered on the input parent component. This

method is used by all of the static "show dialog" methods, and it is also the method to use when you

construct a JOptionPane directly and want to use it in a dialog.



public JInternalFrame createInternalFrame(Component parentComponent, String title)

Create a new JInternalFrame containing thisJOptionPane . The frame's parent is the specified

component, and the input string is used as the frame's title. The parent component is used to search (up the

parent chain) for an enclosing JDesktopPane. (See the detailed discussion of theparentComponent

parameter earlier in this chapter.) This method is used by all of the static "show internal frame" methods; it

is the method to use when you construct a JOptionPane directly and want to use it in an internal frame.



public void selectInitialValue( )

Select the initial value, causing the default button to receive focus. If you are going to use a JOptionPane

to display a dialog multiple times, you should call this method before making the dialog visible.



public void updateUI( )

Called to indicate that the L&F has changed.



10.6.2 Miscellaneous Static Methods

In addition to all of the static methods defined for showing dialogs (of which we saw some examples earlier), several

other static methods are also defined:

public static Frame getFrameForComponent(Component parentComponent)

Search the parent hierarchy of the given Component until it finds aFrame, which it returns. If it

encounters a null parent (or if the input component isnull), it returns the result of a call togetRootFrame( ).

public static JDesktopPane getDesktopPaneForComponent(Component parentComponent)

Search the parent hierarchy of the given Component until it finds aJDesktopPane, which it returns. If it

encounters a null parent (or if the input component isnull), it returns null.

public static void setRootFrame(Frame newRootFrame)

Set a default Frame to be used when an attempt is made to create a dialog and a parent

Frame cannot be

found.



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



public static Frame getRootFrame( )

Return the value set bysetRootFrame( ). The value is initially determined by the L&F.

I l@ve RuBoard



.



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



I l@ve RuBoard



10.7 Using Internal Frame Dialogs with JDesktopPane

In



order to get the best results when using internal frame dialogs created by

JOptionPane , the dialogs need to be



placed in a JDesktopPane. However, this may not be convenient if your application does not use JDesktopPane

a

.

In this section, we'll show how you can easily adapt your application to use a JDesktopPane so that you can use

internal frame dialogs.

Recall that JDesktopPane has a null layout manager, leaving the management of the location of its contents up to

the DesktopManager and the user. This makesJDesktopPane a poor choice when you just need a container in

which to build your main application. As a result, if you want to have an internal frame dialog displayed in a "normal"

container, you need a solution that gives you the features of both JDesktopPane and a more layout-friendly

container.

This is actually a pretty straightforward goal to achieve. You need to create a JDesktopPane and add your

application container to it so that it fills an entire layer of the desktop. When there are no internal frames displayed,

this looks the same as if you were displaying the application container alone. The benefit is that when you need to

add an internal frame dialog, you have a desktop to add it to.

Here's a simple example that shows how this works. It also shows how you can make sure your container fills the

desktop, even if the desktop changes size (since there's no layout manager, this won't happen automatically).



// DialogDesktop.java

//

import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

// A frame that can easily support internal frame dialogs

public class DialogDesktop extends JFrame {

public DialogDesktop(String title) {

super(title);

setDefaultCloseOperation(EXIT_ON_CLOSE);

final JDesktopPane desk = new JDesktopPane( );

setContentPane(desk);

// Create our "real" application container; use any layout manager we want.

final JPanel p = new JPanel(new GridBagLayout( ));

// Listen for desktop resize events so we can resize p. This will ensure that



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



// our container always fills the entire desktop.

desk.addComponentListener(new ComponentAdapter( ) {

public void componentResized(ComponentEvent ev) {

Dimension deskSize = desk.getSize( );

p.setBounds(0, 0, deskSize.width, deskSize.height);

p.validate( );

}

});

// Add our application panel to the desktop. Any layer below the MODAL_LAYER

// (where the dialogs will appear) is fine. We'll just use the default in

// this example.

desk.add(p);

// Fill out our app with a few buttons that create dialogs.

JButton input = new JButton("Input");

JButton confirm = new JButton("Confirm");

JButton message = new JButton("Message");

p.add(input);

p.add(confirm);

p.add(message);

input.addActionListener(new ActionListener( ) {

public void actionPerformed(ActionEvent ev) {

JOptionPane.showInternalInputDialog(desk, "Enter Name");

}

});

confirm.addActionListener(new ActionListener( ) {

public void actionPerformed(ActionEvent ev) {

JOptionPane.showInternalConfirmDialog(desk, "Is this OK?");

}

});

message.addActionListener(new ActionListener( ) {

public void actionPerformed(ActionEvent ev) {

JOptionPane.showInternalMessageDialog(desk, "The End");

}

});

}

// A simple test program

public static void main(String[] args) {

DialogDesktop td = new DialogDesktop("Desktop");

td.setSize(350, 250);

td.setVisible(true);



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



}

}

Most of this class is just a sample program proving that the strategy works. The key ideas come early on in the code.

The first important thing is the creation of a JDesktopPane, which we set as the frame's content pane. We then add

the "real" application container to the desktop. The last important detail is the little ComponentListener we add to

the desktop pane to ensure that our main application container is resized when the size of the desktop changes.

Figure 10-15 shows what the simple test program looks like after expanding it slightly, with two of the internal dialogs

open.



Figure 10-15. DialogDesktop display



I l@ve RuBoard



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



.



I l@ve RuBoard



Chapter 11. Specialty Panes and Layout Managers

With all the spiffy Swing components out there, you might expect to see a few new layout managers to help place them, and

you wouldn't be disappointed. The Swing package includes several layout managers. However, most of these managers are

designed for specific containers— JScrollPane has its own ScrollPaneLayout manager, for example. The Swing package

also includes several new convenience containers that handle things such as scrolling and tabs. (We'll take a close look at

these containers and their associated layout managers in this chapter.) Figure 11-1 shows a class diagram of Swing's specialty

panes and their layout managers. The OverlayLayout and SpringLayout general layout managers can be used with any

containers. We tackle them separately at the end of this chapter. (SpringLayout was added in SDK 1.4.)



Figure 11-1. Class diagram for Swing's specialty panes and their layout managers



I l@ve RuBoard



This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks



I l@ve RuBoard



11.1 The JSplitPane Class

The JSplitPane component allows you to place two (and only two) components side by side in a single pane. You

can separate the pane horizontally or vertically, and the user can adjust this separator graphically at runtime. You

have probably seen such a split pane approach in things like a file chooser or a news reader. The top or left side

holds the list of directories or news subject lines while the bottom (or right side) contains the files or body of the

currently selected directory or article. To get started, Figure 11-2 shows a simple split pane example that shows two

text areas with a horizontal split. You can adjust the width of the split by grabbing the divider and sliding it left or right.



Figure 11-2. Simple JSplitPane with two text areas



Even with the code required to make the text areas behave (more on that in Chapter 19), the following example is still

fairly simple. If you are looking to get up and running with a quick split pane, this is the way to go.



// SimpleSplitPane.java

// A quick test of the JSplitPane class

//

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class SimpleSplitPane extends JFrame {



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

6 A Comparison: Constructors Versus Static Methods

Tải bản đầy đủ ngay(0 tr)

×