13: Create a window and applet

xiaoxiao2021-03-06  40

14: The purpose of creating a window and applet is to "easily complete simple tasks, there is a way to complete complex tasks." [74]

When you originally designed Java 1.0's GUI class library, Sun's goal is to make programmers can make very beautiful interfaces under all platforms. But this goal has not been achieved. In contrast, the GUI made from Java 1.0 Abstract Window Toolkit (AWT) is so mediocre on all platforms. And its function is also very limited; only four fonts can not access the more complex GUI elements provided by the operating system. In addition, Java 1.0 AWT is very clumsy, non-objective programming mode. Once, a student in my class (in the Java start-up time, he did over SUN) explained to me: AWT from idea to design until finally a total of only one month. Although the efficiency is very high, the things made have become a reverse faculty who proof the importance of design.

The event model of Java 1.1 AWT has made the situation. It used the idea of ​​more clear object-oriented solutions, which also introduced JavaBean. JavaBean is a Visual Programming Environment component programming mode for audio-programming environment. The Java Foundation Classes (JFC) of the final Java 2 (JDK 1.2) has replaced Java 1.0 AWT and completed this transformation. The GUI portion of the JFC is called "swing". This is a group of javabeans that are easy to use, can drag and drop (of course, handwritten code), can also be satisfactory with the GUI it creates. It seems that the "third edition" of the software industry (only the third edition, the product will mature) also applies to programming languages.

This chapter only introduces the Swing class library of Java 2, and reasonably assumes Swing is the development direction of the Java GUI class library. [75] If for some reason, you need to use "old" AWT (maybe you have to maintain the old code, or the browser has restrictions), you can go to www.bruceeckel.com to download the first edition of this book (CD- There is also ROM). Note that Java has retained some AWT components, sometimes you have to use them.

The beginning of this chapter will tell, use Swing Creating Applet what is different from creating applications, and how to create an application that can run in the browser in the browser, running the program in a normal application. Most of the GUI programs in the book can run this.

Please note that this book is neither a vocabulary of a Swing component, nor is it not prepared to explain these classes and their methods. So it is intentionally simplified. The Swing class library is huge, while the purpose of this chapter is just to let you start understanding and familiar with these concepts from the basics. If you have a higher request, you will probably do it as long as you are studying.

I assume that you have downloaded and installed the HTML document from Java.sun.com and install the JDK class library, and knows the details of the Swing class library in javax.swing classes. Swing has a simple structure, so in general, these materials are already enough to solve the problem. There are also countless (also is also a giant) Swing monograph. If you want to know deeper, or to modify Swing's default behavior, you can read this book.

The more you know Swing, the more you can experience:

Swing is a much better programming model compared to other languages ​​or development environments. JavaBeans (where the end of this chapter will be introduced) is a class library designed for this architecture. For the entire Java development environment, the "GUI BUILDERS" (visual programming environment) is just a "social" level. When you put the components on the form with a graphics tool, it is actually the GUI Builder to write code for you to call JavaBeans and Swing. This can not only speed up the development speed of GUI, but also make you more experiments. This way you can try more solutions to get better results. Swing is easy to use and designed to make you get readable code even with GUI Builder. This solves an old problem of GUI Builder, which is the readability of the code. Swing includes all of the more trendy user interface elements: there should be all from the image of the image to the tree control and table control. Considering the size of the class library, its complexity is still ideal. If something is simple, the code will not be a lot, if the project is complicated, the code will become complicated accordingly. That is to say, it is easy to get started, but it can also become very powerful if necessary. Good feelings of swing are largely stem from its "orthogonality". In other words, once you understand the spirit of this class library, you can apply this concept to anywhere. This first is the naming specification of its standard. When writing this chapter, I often rely on the name of the way, and often guess, so I can save the file. Obviously, this is a characteristic of a well-designed class library. In addition, usually, if you want to nest the components in other components, you can insert it directly.

To take care of the running speed, the components are "lightweight". In order to cross the platform, Swing is written in Java.

Keyboard support is built-in; you can do not need to use your mouse when running Swing applications. This is not required. Plus rolling bars, it is easy, just embed the control directly to JScrollpane. Plus Tooltip is also as long as one line of code.

Swing also provides a more avant-garde, called "Pluggable Look and Feel" functionality, that is, the appearance of the user interface can dynamically change according to the habit of the operating system or user. You can even invent a set of appearance (of course hard).

Basic AppletJava creates Applets, which is a small program that can run in a web browser. Applet must be safe, so its function is limited. But Applet is a very powerful client programming tool, while the latter is a big topic for web development.

The restriction of Applet is much limited, so it is often referred to as "sandbox". Because there is always a person at time - just Java's runtime safety system - monitoring you.

However, you can also go out of the sandbox, write ordinary applications instead of applet, so you can access other features of the operating system. So far, we write this application, but they are all consistent processes without a graphical interface. Swing can also write the GUI interface application.

In general, if you want to know what applet can do, it is best to go to understand why there is applet: use it to extend the functionality of the web page in your browser. Because the people on the Internet can't really know that this page is from a malicious website, but you must ensure that all running code is safe. So you will find that its biggest limit is:

Applets cannot access local disks. That is to say, you can't read it, because you will never want Applet to read your private information without agreed, then pass it through the Internet. Of course, write is also banned, otherwise it is to open the door to welcome the virus. Java provides a digital signature for Applet. You can choose the applet that has a digital signature (signed by the trusted developer) accesses your hard drive, so that the applet has been released. At the back of this chapter, it will be introduced to the Java Web Start. Web Start is a scheme that securely delivers applications to the client via the Internet. Applet has a long start time, because everything has to be downloaded every time, and every time you download a class to send a request. Perhaps the browser will cache, but this is not certain. So you must put all components of the applet into a JAR (in addition to the .class file, including image, sound), so you can download the entire applet as long as you send a request. Things in JAR volumes can be "digital signature" one item by item. " The advantage of Applet If you don't care about these restrictions, Applet still has obvious advantages, especially when building Client / Server or other web applications: there is no problem with installation. Applet is a true platform-independent (including playing audio file), so you don't need to modify the program for different platforms, users don't need to be installed after installation. In fact, each time there is an Applet's web page, the installation is automatically completed. Therefore, the update of the software can not be alarmatically completed automatically. Build and install a new version of software for traditional Client / Server systems, usually a nightmare. Since the Java language and Applet have a built-in security mechanism, you don't have to worry about the error code will destroy someone else's machine. With these two advantages, Java can develop in the Intranet's Client / Server application. The so-called Intranet's Client / Server application refers to the CLIENT / Server application that exists within the company, or can define and control the user environment (web browser and plug-in) special occasions. Since the applet is automatically integrated into HTML, you have a document system that is not related to the platform, which supports the applet (the translator Note: refers to HTML). This is really interesting, because we usually think that the document is part of the program, not the opposite.

Application Framework Class libraries are usually classified according to functions. Some libraries are used directly, such as string and arraylist in the Java standard class library. Some class libraries are used to create other classes. There is also a class library called Application Framework. Its purpose is to provide a class with some basic functions to help programmers create an application. These basic functions are necessary for such applications. So when you write an application, just inherit this class, then write a few ways you are interested in as needed, customize its behavior. The default control mechanism of the application frame will call those methods you write in the appropriate timing. The application framework is a substrateful example of "will change and unchanging." Its design idea is to leave the personalized part of the program in the local area through overwriting methods. [76]

Applet is created with an application framework. You only need to inherit the Japplet class, and then overwrite several methods. The following methods can control the creation and execution of Applets on the web page:

Method Operation INIT () Applet is automatically called when the task includes the layout of the load assembly. Must override. Start () calls when the applet is displayed on a web browser. After the display is complete, Applet has started working properly, especially those with STOP () shut down). (In addition, the application framework) is called after init () will also call this method. STOP () lets Applet call from the web browser disappeared so that it will turn off some resource operations. This method will be called before () before (Application Framework Call) DESTROY (). DESTROY () When (browser) no longer needs this applet, this method will be called to release resources when uninstalling it from the page. After you know these, you can write a simple applet:

//: c14: applet1.java// Very Simple Applet.Import javax.swing. *; import java.awt. *; public class applet1 extends japplet {public void init () {getContentPane (). Add (new jlabel. Applet! "));}} ///: ~ Note that Applet does not require main (). It has been included in the application frame; you just put the boot code in init ().

This program only has a thing, just put a text label into the applet (AWT has given the name of Label and other components, so SWING components usually take "J"). The constructor of the JLabel requires a string as a parameter. In this program, the label is placed on the form.

The init () method is responsible for the component add () to the form. Maybe you will feel that it should be able to call the add () method of its own (JAPPLET). In fact, AWT is doing this. Swing requires that all components are added to the "Content Pane" ", so getContentPane () must be called before add ().

Run Applet in a web browser To run the program, first you have to put the applet into the web page, then open the page with a web browser that runs Java. You have to use a special tag [77] to put the applet in the web page, then let it tell the page how to load and run this applet.

This step was very simple. At that time, Java was very simple, everyone used the same Java, Java in the browser. So just change HTML a little, just like this:

But subsequent browser and language war makes us (not only the programmer, but also the end user) has become a lost home. Soon, Sun finds no longer counting the browser to support the flavored Java, the only solution is to provide "Plugin (add-on) using the browser extension mechanism. Through this approach (to ban Java, unless all third-party plugins are all banned, but in order to obtain competitive advantage, there is no browser's provider will do this), Sun ensures that Java will not be hostile browser The provider is forbidden.

For Internet Explorer, this extension mechanism is ActiveX control, and Netscape is Plugin. When you do the page, you must write a set of tags for these two browsers, but JDK comes with an HTMLConverter tool that automatically generates tags. Below is the HTML page of Applet1 processed by HTMLConverter:

A few lines are too long I can only fold it, otherwise I can't let it go. However, the program in the source code (can be downloaded from www.bruceeckel.com) can run normally, do not have to worry about the problem. The value of the Code is the name of the .class file in the Applet, Width and Height represent the initial size of the applet (as in front, in pixels). In addition, the Applet tag can also put something: where to find a .class file (codebase), how to align, Applet, the identifier (name) to be used, and the parameters supplied to the applet. The format of the parameter is like this:

You can add any multiple parameters as needed.

This book source code (www.bruceeckel.com provides free download) an HTML page for each applet, and there is also a number of examples of how to use the Applet tag. These pages are controlled by INDEX.HTML of this chapter. In addition, you can refer to java.sun.com, how to insert the latest and most complete information on the Applet in the web page.

AppletViewer Usage Sun JDK contains a tool called AppletViewer, which can find Applets in the HTML file according to tag, then do not display HTML text, run this applet directly. Since AppletViewer ignores all things other than the Applet tag, you can directly mark the applet mark as a note release to Java's source file: // This way you can use "appletViewer myapplet.java" to start Applet, no need to write HTML test files. For example, as long as the HTML tag is added in Applet1.java:

//: c14: applet1b.java// Embedding the applet tag for applet1b width = 100 height = 50> import javax.swing. *; import java.awt. *; public Class Applet1b Extends Japplet {public void init () {getContentPane (). Add ("applet!"));}} ///: ~ You can use this command to start applet.

AppletViewer Applet1b.java This book will use this simple way to test the applet. In addition, you will see another way. It does not use AppletViewer, start the applet directly with the command line.

Applet test If you just want to test it, you don't have to go online. Start the web browser directly, open the HTML file containing the applet tag. When the browser is loaded with HTML, the Applet tag is discovered, and the corresponding .class file is found according to the value of the Code. Of course, it is found in ClassPath. If there is no ClassPath, it gives an error message in the status bar of the browser, telling you that the .class file is not found.

If you want to test Applet on a web site, the problem is somewhat complicated. First, you have to have a website first. For most people, the website is a directory on the ISP (Internet Service Provider) machine. Since Applet is just a few files, ISP does not provide special support, so you have to find a way to pass the HTML file and .class file to the specified ISP machine. This step is usually done by FTP. It's a lot of tools in FTP, some is freeware, some is Shareware. From this point of view, it seems to test the applet on the website, which is used to pass the file to the ISP machine, and then connect to the website, open the page with the browser, wait until the Applet jumps out, it is very good. Is it really?

This is where you will let you plant ahead. If the client's browser cannot find a .class file on the server, it will go to the client's classpath to find it. In this way, it is possible that the browser can't find the .class file on the server, so the applet is started with the file on your machine. So everything is normal, and others can't see anyone. So before testing, you must delete the local .class file (or .jar file), only this can you know that the program is in the correct server directory.

I have planted a very embarrassing head here. Once, when I uploaded HTML and Applet, I made a wrong Package name, so put the applet missed the directory. But my browser can also find the program in the local classpath, so I became the only one that can run this applet. Therefore, when you assign the Code parameter to the Applet, you must give a full name, this is very important. Many public published applets are not packaged, but in actual work, it is best to make a package. Start the applet with the command line Sometimes you will also want the GUI program to do something else. For example, when retaining Java's cross-platform, let it do some "ordinary" procedures. In the previous chapter of this book, we have been writing command line applications, but some operating systems (such as Macintosh) are no command lines. So we have countless reasons, use Java to write some non-applet's GUI program. This is of course a very reasonable requirement.

You can use the SWING class library to write an application that is exactly consistent with the current operating system's appearance. If you want to write the GUI program, first see if Java and related tools can be the most new version, only, that is worth writing. [78] Because only this can we write the program that will not let users feel annoying. If for some reason, you have to write an important GUI program with an old version of Java, then consider it carefully before receiving the task.

You will definitely want to write programs that can be started from the command line and can run when applet. It is very convenient to test the applet. Because typically starting from the command line to start faster than from a web browser and AppletViewer, it is more convenient.

To create an applet that can start with the command line, just add a main () in the class, let it put this Applet's instance to JFrame. [79] We take Applet1b.java as an example to see how to modify us to make it both applications and can run when applets.

//: c14: applet1c.java// An application and an applet.// import javax.swing. *; import java.awt. *; public class Applet1c extends japplet {public void init () {getContentPane (). Add ("applet!"));} // a main () for the application: public static void main (string [] args) {japplet applet = new Applet1c (); JFrame frame = new JFrame ( "Applet1c"); // To close the application: frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); frame.getContentPane () add (applet); frame.setSize (100,. 50); applet.init (); applet.Start (); frame.setvisible (true);}} ///: ~ We only added main (), all anything did not move. Main () creates an instance of the applet and adds it to JFrame so that we can see it.

You will see main () explicitly call the applet's init () and start (). This is because these two steps are originally handed over to the browser. Of course, this does not completely replace the browser because the former will call Stop () and Destroy (), but roughly, this approach is still feasible. If you have any questions, you can call themselves. [80] Note that if there is no line:

Frame.setVisible (TRUE); then you can't see anything.

A framework for displaying Applets is very useful, although the code converts Applets into an application is very useful, but it is a waste of paper and people who are wasting them. So let's use the following frame to display the Swing example.

//: com: bruceeckel: Swing: console.java// Tool for running swing demos from the // console, Both applets and jframes.package.com; import javax.swing. *; import java.awt.event {String t = o.getclass (). Tostring (); // remove the word "class": if (T. IndexOf ("Class")! = -1) T = T.Substring (6); returnit t;} public static void Run (JFrame Frame, Int Width, int Height) {frame.setDefaultcloseOperation (jframe.exit_on_close) ; frame.setSize (width, height); frame.setVisible (true);} public static void run (JApplet applet, int width, int height) {JFrame frame = new JFrame (title (applet)); frame.setDefaultCloseOperation (JFrame .Exit_on_close; frame.getContentPane (). Add (applet); frame.setsize; applet.init (); applet.Start (); frame.setVisible (TRUE);} public static void Run (JPanel Panel, int width, int {j Frame frame = new JFrame (title (panel)); frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);. Frame.getContentPane () add (panel); frame.setSize (width, height); frame.setVisible (true);}} / //: ~ This is a tool that everyone has used, so I put it into com.bruceeckel.swing. Console is a class that is completely composed of static methods. The first method is responsible for extracting the name of the class belonging to the object (using RTTI). Since getClass () usually adds a "class" after the name of the class, use indexof () to determine if there is "class" in the name. If so, use substring () to strip it and return to this string. This name will appear on the title bar of the window displayed by Run (). SetDefaultCloseOperation () The role is to tell the procedure, once JFrame is turned off, the program should also exit. By default, JFrame does not mean to exit the program, so the program will not abort unless you call setDefaultCloseOperation () or write some similar code.

Run () made three overloads for Japplet, JPanel, and JFrame, respectively. Note that INIT () and START () are only required to be a japplet. Now just create a main (), then add the row in this line, you can run on the console:

Console.Run (New Myclass (), 500, 300); Finally, the two parameters represent width and high respectively. Below we use console to modify Applet1c.java:

//: C14: applet1d.java// Console Runs Applets from the command line .// import javax.swing. *; import java.awt. *; Import com.bruceeckel.swing. *; public class applet1d extends japplet {public void init () {getContentPane (). Add ("applet!");} public static void main (string [] args) {Console .Run (New Applet1D (), 100, 50);}} ///: ~ This will not have to knock the same code.

Making the button to make a button is simple: I want to let the button display, take it as a parameter to call the JButton constructor. Below we will do some more exciting things, such as what to put an icon on the button.

The usual button is a field of the class, so you can use it to indicate the button.

JButton is a component - it has its own small window - will be automatically refreshed when the update is updated. That is, you don't have to clearly indicate how the button is displayed or anything else; just put them in the form, they can draw themselves. So you have to put the button on the form:

//: c14: Button1.java/ Putting button on an applet.// import javax.swing. *; import java.awt. *; import com .Bruceeckel.swing. *; public class button1 Extends japplet {private jbutton b1 = new jbutton ("Button 1"), b2 = new jbutton ("Button 2"); public void init () {Container CP = getContentPane (); Cp.setLayout (new flowLayout ()); cp.add (b1); cp.add (b2);} public static void main (string [] args) {console.run (New Button1 (), 200, 50); }} ///: ~ This is a bit new content: Before adding something in Content Pane, we first set its "Layout Manager" to FlowLayout. The role of the layout manager is to tell which location of the panel places the control on the form. Here we can't use the applet default borderLayout, because (in this chapter, you will make a detailed explanation when you talk about the form of the form) If you use it, once you add new controls on your form, the old control will be all covered Living. FlowLayout will make the control uniformly spread on the form, from left to right, from top to bottom. Capturing the event If you compile the on the applet, you will find that the button has not happened. This is your life. You have to write code to tell it what to do. The program-driven program is an important component of GUI programming, and the basic idea of ​​drivers is to link events with the code.

Swing's idea is to interface (graphic components) and implementation (after the component has an event, the code you want to run) clearly. What incidents can happen in the SWING component, and what happened. So if you are not interested in an event, such as the mouse over the button, you can do not pay attention to this event. In this way, you can solve the problem of event-driven, once you understand the basic concepts, you can even go directly from the Swing components that have never seen before. In fact, this model is also applicable to Javabean (discusses later after this chapter).

We still first comply with the main events of this control we want to use. In this example, this control jbutton, and "what we are interested in" is the press button. To indicate that you are interested in the button, you can call AddActionListener (). This method requires an ActionListener parameter. ActionListener is an interface that only has one method, ActionPerformed (). So if you want JButton to perform a task, you have to implement an ActionListener first, then register this class with the addActionListener method to jButton. This method will start when the button is pressed. (This is often referred to as callback)

So after the button is pressed, what should it be? We hope to see changes on the screen, so introducing a new Swing component here: jtextfield. This component can display text. Its text can be either user-entered or a program inserted. Although there are many ways to create JTextField, the simplest is the first to pass the width to the constructor of JtextField. Wait until JtextField is placed on the form, you can use setText () to modify the content (JtextField has many methods, please refer to the JDK document). Below is the modified program: //: c14: Button2.java// responding to button presses.// import javax.swing. *; Import java. AWT.Event. *; import java.awt. *; import com.bruceeckel.swing. *; public class button2 extends japplet {private jbutton b1 = new jbutton ("Button 1"), B2 = New JButton ("Button 2" ); private JTextField txt = new JTextField (10); class ButtonListener implements ActionListener {public void actionPerformed (ActionEvent e) {String name = ((JButton) e.getSource ()) getText ();. txt.setText (name); }} Private buttonListener BL = new buttonListener (); public void init () {b1.addActionListener (BL); b2.addactionListener (BL); Container CP = getContentPane (); cp.setLayout (new flowLayout ()); CP. Add (b1); cp.add (b2); cp.add (txt);} public static void main (string [] args) {console.run (New Button2 (), 200, 75);}} /// : ~ The steps for the creation and placement of JtextField are identical to JButton or other Swing components. The difference is that this program creates a ButtonListener class that implements ActionListener. ActionPerformed () requires an ActionEvent parameter that is the specific information and source of events. Here we want it to show which button you press. I use getSource () to get the text on the button, then put it in JtextField, which can prove that the code is really called when you click the button.

We register the ButtonListener object with addActionListener () in init ().

Considering that each Listener usually requires only one instance, it is more convenient to implement ActionListener with anonymous internal classes. Below we use anonymous internal classes to rewrite Button2.java

//: c14: Button2b.java// using anonymous inner class code = button2b width = 200 height = 75> import javax.swing. *; import java.awt.event. *; import java.awt *;. import com.bruceeckel.swing *;. public class Button2b extends JApplet {private JButton b1 = new JButton ( "Button 1"), b2 = new JButton ( "Button 2"); private JTextField txt = new JtextField (10); private activityListener BL = new actionListener () {public void actionPerformed (ActionEvent E) {string name = ((jbutton) E.GETSOURCE ()). GetText (); txtTTTTTEXT (Name);}}; Public void init () {b1.addactionListener (BL); b2.addactionListener (BL); container cp = getContentPane (); cp.setLayout (new flowLayout ()); cp.add (b1); cp.add (b2) CP.Add (txt);} public static void main (string [] args) {console.run (New Button2b (), 200, 75);}} ///: ~ This book will prefer anonymous internal class Method (unless you have to have you). Jtextarea is compared with Jtextfield, Jtextarea can accommodate multi-line text, providing more features, which are similar. The append () method is useful; you can use it to direct the output of the program to jtextarea so you can use the Swing program to improve our previously written, the command line printed on the standard output (because you can use The scroll bar saw the previous output). The following program uses the Geography generator in Chapter 11, and we use its output to fill Jtextarea:

//: C14: Textarea.java// using the jtextarea control. *; import java.awt.event. *; import java.awt. *; import java.util. *; import com.bruceeckel. swing *;. import com.bruceeckel.util *;. public class TextArea extends JFrame {private JButton b = new JButton ( "Add Data"), c = new JButton ( "Clear Data"); private JTextArea t = new JTextArea ( 20, 40); private Map m = new HashMap (); public TextArea () {// Use up all the data: Collections2.fill (m, Collections2.geography, CountryCapitals.pairs.length); b.addActionListener (new ActionListener () {PUBLIC VOID ACTIONPERFORMED (ActionEvent E) {Iterator IT = M.Entryset (). Iterator (); while (it.hasnext ()) {map.entry me = (map.Entry) (it.next ()) T.Append (me.getKey () ":" me.getValue () "/ n");}}}); c.AddActionListener (new actionListener () {public void actionPerformed (ActionEvent E) {t .SETTEXT ("");}}); Container CP = getContentPane (); CP. SetLayout (New flowLayout ()); cp.add (new JscrollPane (T)); cp.add (b); cp.add (c);} public static void main (string [] args) {console.run (New TextArea (), 475, 425;}} ///: ~ This class should be a JFRAME instead of a japplet because it is an applet to run in the HTML page as an applet. We put the country and the capital into the Map in init (). Note that these two buttons, we don't use intermediate variables during the creation and add ActionListener. This is because the other parts of the program do not need these two listeners (Listener). The "Add Data" button is responsible for the arrangement and adding of the data, and the "Clear Data" button is responsible for using the setText () method, emptying the text in jtextarea.

When jutxtrea joins Applet, we first embed it into JScrollpane, so once the text is more, the scroll bar will automatically appear. The ball roller is so simple. The Simple and Elegance of JScrollPane is really congestion compared to similar controls in other GUI programming environments.

The method of placing the component on the form in the form of the control layout can be different from the other GUI systems you have seen. First of all, it is all code, and there is no "resource" story at all. Second, the position of the component is not controlled by absolute positioning, but is controlled by an object called "layout manager". The role of the layout manager determines the position placed in accordance with the order of component add (). The size, shape, and placed position of the component will be significantly different from the layout manager. In addition, the layout manager automatically adjusts the position of the component according to the window size of the Applet or application, so that once the size of the window changes, the size, shape, and placement position of the component will be adjusted accordingly. JAPPLET, JFRAME, JWINDOW, and JDIALOG, these components have a getContentPane () method. This method can return a Container, and this Container's role is to resettle and display component. Container has a setLayout () method, you are using it to select the layout manager. Other classes, such as JPANEL, can resettle and display components directly, so you have to skip the content panel directly to set its layout manager.

Here, we will use the method of adding a button to the panel to examine various layout managers (so the simplest). We didn't write an event handler because the program here is just used to display the placement position of the button.

The default layout manager for BorderLayoutapplet is BorderLayout (in the first few examples, we change it into flowLayout). If there is no other instruction, BorderLayout puts all controls in the positive and stretched to the maximum.

It is better than these features in BorderLayout. It also has four boundaries and the concept of the central. When you add a controller to the panel of BorderLayout, you can also choose the overloaded add () method. At this time, give it a constant. This constant can be one of the five below:

BorderLayout. North side BorderLayout. South Border BorderLayout. East Right BorderLayout. West Left BorderLayout.center Fills, unless the edge of other components or forms

If you don't specify the area of ​​the object, use the center by default.

Let's take a simple example. Since the Japplet is used by default, we will not have a layout:

//: c14: BorderLayout1.java// Demonstrates BorderLayout.// import javax.swing *; import java.awt *; import com.bruceeckel... swing *;. public class BorderLayout1 extends JApplet {public void init () {Container cp = getContentPane (); cp.add (BorderLayout.NORTH, new JButton ( "North")); cp.add (BorderLayout.SOUTH, new JButton ("South")); cp.add (BorderLayout.east, New JButton ("EAST")); cp.add (BorderLayout.west, New JButton ("West")); cp.add (BorderLayout.center, New JButton ("center"));} public static void main (string [] args) {console.run (New BorderLayout1 (), 300, 250);}} ///: ~ In addition to center, other controls will in one direction The upper compression is minimized, stretched to the maximum in the other direction. Center will stretch in both directions until the entire intermediate area. FlowLayout will allow the component directly to "stream" to the form, from left to right, from top to bottom, one line is full.

Let's take an example of a FlowLayout. You will find that after using FlowLayout, the component will freeze it on its "inherent" size. For example, JButton will arrange the size according to the length of the string.

//: c14: FlowLayout1.java// Demonstrates FlowLayout.// import javax.swing *; import java.awt *; import com.bruceeckel... Swing. *; public class flowLayout1 extends japplet {public void init () {container cp = getContentPane (); cp.setLayout (new flowLayout ()); for (int i = 0; i <20; i ) cp.add ( New JButton ("Button" i));} public static void main (string [] args) {console.run (New flowLayout1 (), 300, 250);}} ///: ~ Due to the control on the FlowLayout panel It will be automatically compressed to the smallest, so some accidents will occur. For example, Jlabel determines the size of the control based on the string, so when you are aligned with the text of the JLABLE control on the FlowLayout panel, the display effect does not change any changes.

GridLayoutGridLayout means that the table is a component's form. When you add something to the left, it will put the components in the order from the top to the right. When you create a layout manager, you have to refer to the number of people and columns in the constructor, so that it can help you divide the form into a lattice. //: c14: GridLayout1.java// Demonstrates GridLayout.// import javax.swing *; import java.awt *; import com.bruceeckel... Swing. *; public class gridLayout1 Extends japplet {public void init () {Container CP = getContentPane (); cp.setLayout (New GridLayout (7,3)); for (int i = 0; i <20; i ) CP .add ("Button" i));} public static void main (string [] args) {console.run (New GridLayout1 (), 300, 250);}} ///: ~ Here we create 20 buttons but prepared 21 slots (slot). Since GridLayout does not have a so-called "balance" mechanism, the last slot will be empty.

GridbagLayoutGridbagLayout is that when the size of the window changes, you can use it to accurately control the reactions of each part of the window. But at the same time, it is also the most difficult and most complex layout manager. It is mainly for the GUI Builder generated code (perhaps the GUI Builder is not absolutely positioned but gridbaglayout). If your design is very complicated, you have to use GridbagLayout, so I suggest you use the GUI Builder. If you think it is necessary to understand the details inside, I suggest you read Horstmann and Cornell's Core Java 2, Volume 1, (Prentice Hall, 2001), or watch Swing monographs.

Absolute positioning can also be absolutely positioned to the graphic components:

Set the container's layout manager to null: setLayout (NULL). When adding components to the panel, first adjust the setbounds () or reshape () method (according to each version), set a rectangle in pixels. This step can be placed in the constructor, or it can be placed inside to see you. Some gui builders are mainly used by this method, but in general, this is not the best way.

Boxlayout is too difficult to learn because GridbagLayout is hard, so Swing introduces a new boxlayout. It retains many advantages of GridbagLayout, but it is not so complicated. So when you want to control the layout of the control, you can give priority to use it (reiterate again, if the design is very complicated, it is best to use the GUI Builder). BoxLayout allows you to control components in both vertical and horizontal directions, which use some things called pillars and glue (glue) to control the distance between components. Let's first try it with the method of experiment other layout manager:

//: C14: BoxLayout1.java// Vertical and horizontal boxlayouts.// import javax.swing. *; import java.awt. *; import COM. Bruceeckel.swing. *; public class boxlayout1 extends japplet {public void init () {jPanel JPV = new jPanel (); jpv.setLayout (new boxlayout (jpv, boxlayout.y_axis); for (int i = 0; i < 5; i ) jpv.add ("JPV" i)); jPanel JPH = new jPanel (); jph.setLayout (new boxlayout (jph, boxlayout.x_axis)); for (int i = 0; i <5; i ) JPH.Add ("JPH" i)); Container CP = getContentPane (); cp.add (borderLayout.east, JPV); cp.add (BorderLayout.South, JPH);} Public static void main (string [] args) {console.run (New BoxLayout1 (), 450, 200);}} ///: ~ BoxLayout constructor is slightly different from other layout managers - it's first The parameter is the container that this BoxLayout will control, the second parameter is the direction of the layout. In order to simplify the approach, Swing also provides a special container for built-in BoxLayout, Box (Translator Note: The container here refers to the Java.awt.Container class). Box has two ways to create a Static's Static, and we use it to arrange components.

//: c14: Box1.java// Vertical and horizontal boxlets.// import javax.swing. *; import java.awt. *; import COM. Bruceeckel.swing. *; public class box1 extends japplet {public void init () {box bv = Box.createVerticalBox (); for (int i = 0; i <5; i ) bv.add (New JButton ("BV" i)); BOX BH = Box.createhoriZontalbox (); for (int i = 0; i <5; i ) Bh.Add (New JButton); Container CP = getContentPane (); CP .add (borderlayout.east, bv); cp.add (borderLayout.South, BH);} public static void main (string [] args) {console.run (New Box1 (), 450, 200);}} / //: After you have Box, you can make it the second parameter when you want to add components to the Content Pane. Struts will separate the components, it is the size of the size is calculated. When using it, just take it as a space in the middle of the two components.

//: C14: Box2.java// adding struts.// import javax.swing. *; import java.awt. *; import com.bruceeckel. Swing. *; public class box2 extends japplet {public void init () {box bv = Box.createVerticalBox (); for (int i = 0; i <5; i ) {bv.add (New JButton ("BV" I))); bv.add (Box.createVerticalStrut (i * 10));} box bh = Box.createhorizontalbox (); for (int i = 0; i <5; i ) {bh.add (new jbutton (" BH " i)); BH.ADD (Box.Createhorizontalstrut (i * 10));} Container CP = getContentPane (); cp.add (borderLayout.EAST, BV); cp.add (BorderLayout.South, BH) Public static void main (String [] args) {console.run (new box2 (), 450, 300);}} ///: ~ Unlike fixed spacing Struts, Glue (glue) will be as will Components are separated. So more accurately, it should be "spring" rather than "glue" (plus this design is based on the idea called "Springs and Struts", so this term is somewhat strange) .

//: c14: Box3.java// using glue.// import javax.swing. *; import java.awt. *; import com.bruceeckel. Swing. *; public class box3 extends japplet {public void init () {box bv = Box.createVerticalBox (); bv.add ("Hello"); bv.add (box.createvertagevert); bv .add ("applet")); bv.add (Box.createVerticalGlue ()); bv.add (New Jlabel ("World")); box bh = box.createhorizontalbox (); bh.add (new Jlabel ("Hello"); BH.Add (Box.createhorizontalglue ()); BH.Add ("applet")); Bh.Add (Box.createhorizontalglue ()); Bh.Add (New Jlabel "World"); bv.add (Box.createVerticalGlue ()); bv.add (bh); bv.add (Box.createVerticalGlue ()); getContentPane (). Add (bv);} public static void main String [] args) {console.run (New Box3 (), 450, 300);}} ///: ~ Strut only controls the distance in one direction, while Rigid Area is fixed in both directions Distance between components.

//: C14: Box4.java// Rigid Areas Are Like Pairs of struts.// import javax.swing. *; import java.awt. *; Import com.bruceeckel.swing. *; public class box4 extends japplet {public void init () {box bv = Box.createVerticalBox (); bv.add (new jButton ("top")); bv.createrigidarea (New Dimension (120, 90)); bv.add ("Bottom")); Box Bh = Box.createhoriZontalBox (); Bh.Add (New JButton ("Left")); BH.ADD ( Box.Createrigidarea (New Dimension (160, 80))); BH.Add ("Right"); bv.add (bh); getContentPane (). Add (bv);} public static void main (String [] args) {console.run (New Box4 (), 450, 300);}} ///: ~ Should tell you that the evaluation of Rigid Area is not so unified. In fact it is absolutely positioning, so some people think that it is excessive. Best solution? Swing features are very powerful, just a few lines of code can do a lot. The code of this book is simple, and for teaching purposes, they are all written. In fact, you can combine these layouts, complete some of the more complex tasks. However, sometimes it is not so wise to create a GUI form with a handwritten code; the first is too complicated, and it is not worth it. Java and Swing designers want to use language and class libraries to support the GUI Builder tool, then let you simplify programming. In fact, just know what is the layout, and how to deal with (hereinafter), you don't understand the placement of handwriting code control controls, is not important. You can choose a tool (after all, the original intention of Java is to allow you to improve the efficiency of the programming).

Swing Event Model In Swing's event model, the component can initiate (or "shooting") event [translation 1]. Various events are classes. When there is an event occurs, one or more listeners will be notified and respond. Such an event's source is separated from its handler. Generally speaking, the programmer does not modify the Swing component, and they write some event handles. When the component receives the event [translation 1], the code is automatically called, so the Swing event model can be called The absolute example is separated by the interface and the implementation.

[Translation 1] This language previously lecture component issued an event, and the components received events later. As far as I understand, the previous event is that the component passed to the parameters that the component is called when the Listener method is called, and the latter event refers to the user's operation. Take the previous Button2.java example, the previous component is passed to its ActionEvent E when calling buttonListener's action, the next ActionEvent E, which means that the user presses the button.

In fact, event listener is an object that implements the Listener interface. So, the programmer is to create a Listener object and then register this object to the components of the initiating event. The process of registration is to call the AddXxxListener () method of the component, where "XXX" indicates the type of event initiated by the component. Just look at the name of the "AddListener" method, you can know which event can handle, so if you let it get wrong, then compile. Behind you will see that JavaBean will follow "AddListener" naming specification when deciding which events can handle. The transaction logic should be encapsulated into Listener. The only condition for creating Listener is that it must implement the interface. You can create a "global listner", but internal classes may be more appropriate. This is not only because of the logical grouping of Listener based on the UI or transaction logic (you will see), you can use the internal class to reference the characteristics of the host class, so you can cross the class or sub- The boundary of the system is called.

We have already involved Swing event model in the example, and we have completed the details of this model.

All Swing components in the event and the listener have the addXxxListener () and REMOVEXXXLISTENER () methods, so the components can add and delete the listener. You will find that "xxx" here is also the parameters of the method, such as AddMylistener (MyListener M). The following table lists the basic events, listeners, and methods, and corresponding to the ADDXXXLISTENER (), and components of the REMOVEXXXLISTENER () method. To know, this event model emphasizes scalability when designing, so you are likely to meet the events and listeners that have not been mentioned in this table.

Event, listener interface and add and remove methods support components ActionEventActionListeneraddActionListener this event () removeActionListener () JButton, JList, JTextField, JMenuItem and their derived classes JCheckBoxMenuItem, JMenu, and JpopupMenu AdjustmentEventAdjustmentListeneraddAdjustmentListener () removeAdjustmentListener () JScrollbar and implement interfaces Adjustable the assembly ComponentEventComponentListeneraddComponentListener () removeComponentListener () * component and its derived classes JButton, JCheckBox, JComboBox, Container, JPanel, JApplet, JScrollPane, Window, JDialog, JFileDialog, JFrame, JLabel, JList, JScrollbar, JTextArea, and JTextField ContainerEventContainerListeneraddContainerListener () removeContainerListener () Container and its derived class JPanel, JApplet, JScrollPane, Window, JDialog, JFileDialog, and JFrame FocusEventFocusListeneraddFocusListener () removeFocusListener () Component and "derived classes (derivatives *)" KeyEventKeyListeneraddKeyListener () removeKeyListener () Component and "derived class (DeriVative *) "MouseEvent (including click and mobile) MouselisteneraddMouseListener () RemoveMouseListener () Component and its derived class (DER) ivatives *) "MouseEvent [81] (including clicks and movement) MouseMotionListeneraddMouseMotionListener () removeMouseMotionListener () Component and" derived classes (derivatives *) "WindowEventWindowListeneraddWindowListener () removeWindowListener () Window its derived classes JDialog, JFileDialog, and JFrame ItemEventItemListeneraddItemListener ( ) removeItemListener () JCheckBox, JCheckBoxMenuItem, JComboBox, JList, and realized ItemSelectableinterface components TextEventTextListeneraddTextListener () removeTextListener () JTextComponent derived class, including JTextArea and JTextField you'll find a component supports only a few events. So I have to figure out that all components are very difficult. There is a simple way to modify the showMethods.java in Chapter 10, let it tell you which events support.

Chapter 10, we introduced the reflection, and give a program for displaying methods - or all methods, or by parameters, one of them can be listed. The magic of Reflection is that there is no way to traverse the inheritance system, it can get all methods of class. So for programming, this is a very valuable tool that saves time. Since most Java methods are very intuitive, you can choose a word you interested, let it go, then find the JDK documentation. But when I was 10, we haven't told Swing, so we wrote a procedure for a command line. Here we have to write a more practical GUI program, just it is specifically used to find the "addListener" method for the SWING component.

//: c14:. ShowAddListeners.java// Display the "addXXXListener" methods of any Swing class.// import javax.swing *; import javax .swing.event. *; import java.awt. *; import java.awt.event. *; import java.lang.reflect. *; import java.util.Regex. *; import com.bruceeckel.swing. *; public class ShowAddListeners extends JApplet {private JTextField name = new JTextField (25); private JTextArea results = new JTextArea (40, 65);? private static Pattern addListener = Pattern.compile ( "(add // w Listener //(.* ? //) ")") "); private static pattern qualifier = pattern.compile (" // w //. "); Class Namel Implements ActionListener {Public Void ActionPerformed (ActionEvent E) {String NM = Name.getText (). Trim (); If (nm.length () == 0) {results.Settext ("no match"); return;} class klass; try {klass = class.forname ("javax.swing." Nm);} Catch (classnotfoundexception ex) {results.settext ("no match"); Return;} method [] methods = klass.getMethods (); results.setText (""); for (int i = 0; i

Container CP = getContentPane (); cp.add (borderLayout.North, TOP); cp.add (new jscrollpane (results)); // initial data and test: name.settext ("jtextarea"); Namelistener.ActionPerformed (New) ActionEvent ("0,"));} public static void main (string [] args) {console.run (new showaddlisteners (), 500, 400);}} ///: ~ Just in jtextfield into you want The name of the Swing component of the query, it will extract the result with the regular expression and then hand it over to Jtextarea display. You will find that there are no similar buttons on your form, allowing you to indicate the control of the query. This is because JtextField already has an ActionListener. This list will be updated immediately when you finish the ENTER. (Process is this,) If jtextfield is not empty, ActionListener finds class.Forname () based on this string. If the name is incorrect, class.Forname () will throw an exception and let the exception handler displays "No Match" in Jtextarea. If the name is correct (note is sensitive), class.Forname () will return normally, then getMethods () will return the array of Method objects.

There are two regular expressions here. The first, that is, AddListener, responsible for matching "add" plus a number of words characters (translator Note: Original is Word Character, represents letters, numbers, and underline) plus "listener", plus any character enclosed in parentheses . Note that we put the entire regular expression in parentheses, that is, if the match is successful, we will use it as a group. Namel.ActionPerformed () method will pass the Method object one by one to Pattern.matcher (), and create a Matcher object by the latter. If the match is successful, Find () will return True so you can use Group (1) to select the first BROP of the entire expression. At this time, there is a definite word in front of the string. So we have to use Qualifier as a C09: showMethods.java.

Finally, we set up the initial value of Name and run the event in the init () method.

Use this program to see the Swing component is really too simple. Once you know the events supported by the components, you don't have to check the documentation. You just:

Remove "Event" in the name of the Event class, plus "listener", which is the name of the interface you want to implement. Implement the above interface and want to capture which event implements its interface. For example, if you are interested in mouse movement, you can go to realize the mousemotionlistener interface mousemoved () method. (You must implement the full range of methods of this interface, but in this case, there will be shortcuts, and you will see it for a while.) Create an object of a Listener. Add an "add" in front of the name of the interface, and then register with the component with this method. For example, addMouseMotionListener (). Here are some methods listener interface: Method ActionListener Listener Interface / Adapter interface defined actionPerformed (ActionEvent) AdjustmentListener adjustmentValueChanged (AdjustmentEvent) ComponentListenerComponentAdapter componentHidden (ComponentEvent) componentShown (ComponentEvent) componentMoved (ComponentEvent) componentResized (ComponentEvent) ContainerListenerContainerAdapter componentAdded (ContainerEvent) componentRemoved (ContainerEvent) FocusListenerFocusAdapter focusGained (FocusEvent) focusLost (FocusEvent) KeyListenerKeyAdapter keyPressed (KeyEvent) keyReleased (KeyEvent) keyTyped (KeyEvent) MouseListenerMouseAdapter mouseClicked (MouseEvent) mouseEntered (MouseEvent) mouseExited (MouseEvent) mousePressed (MouseEvent) mouseReleased (MouseEvent) MouseMotionListenerMouseMotionAdapter mouseDragged (MouseEvent ) mouseMoved (MouseEvent) WindowListenerWindowAdapter windowOpened (WindowEvent) windowClosing (WindowEvent) windowClosed (WindowEvent) windowActivated (WindowEvent) windowDeactivated (WindowEvent) windowIconified (WindowEvent) windowDeiconified (Wi NDOWEVENT) ITEMLISTENER ITEMSTATECHANGED (ITEMEVENT)

The reason why this table is not very complete, part is because the event model allows you to create your own events and related Listener. So you often encounter some class libraries in an event type, and your knowledge you have learned in this chapter will help you learn to use these events.

Simplified programming with Listener's Adapter can see some of the listener in the table above only one way. The workload of this interface is not big, because the method is completed, the interface is also realized. But if you want to use a number of Listener, things are not so happy. For example, if you want to capture the mouse click (Button will not capture this event for you), you must write a mouseclicked () method. But because MouseListener is an Interface, even if not, you have to implement all of its methods. This is really annoying. In order to solve this problem, some (but not all) multi-method Listener interface provides an adapter. From the above table already lists their names. The adapter provides the default null method for the interface. In this way, you can inherit the adapter, you can override the method according to the needs. For example, this is the most common mouselistener:

Class mymouselistener extends mouseadapter {public void mouseclicked (MouseEvent E) {// respond to mouse click ...}} Adapter is used to simplify the creation of Listener.

But there is also a shortcoming of this thing of the adapter. Suppose you write a mouseadapter as above:

Class mymouselistener extends mouseadapter {public void mouseclicked (mouseEvent e) {// respond to mouse click ...}} It not only doesn't work, but will give you crazy. It can be compiled normally, running does not report an error, but pressing the mouse that is no response. Can you see the problem? The answer is in the name of the method: You write mouseclicked () into mouseclicked (). It is just a little bit of case, it is a new method. Fortunately, this is not a method that will call when the window is turned off, so the worst result is just the expected results. Although there is a variety of inconvenience, the interface ensures that all the methods that should be implemented.

Tracking multiple events To prove that event is really excited, as a very interesting experiment, we are ready to create other behaviors that can track JButton (that is, other events except for other events) Applet. Also demonstrate how to use inheritance to customize your own buttons, because the events you are interested in doing this object. To do this, just inherited JButton directly. [82]

MyButton is the internal class of Trackevent, so MyButton can access its host window and control the Text Field in the host window. This ability is necessary if you want to make status information into a field of host class. Of course, this solution also has its limitations, MyButton can only be used with Trackevent. Such code is often referred to as "highly coupled":

//: C14: Tracnt.java// show events as the happen.// import javax.swing. *; import java.awt. *; import java .awt.event *;. import java.util *;. import com.bruceeckel.swing *;. public class trackEvent extends JApplet {private HashMap h = new HashMap (); private String [] event = { "focusGained", " focusLost "," keyPressed "," keyReleased "," keyTyped "," mouseClicked "," mouseEntered "," mouseExited "," mousePressed "," mouseReleased "," mouseDragged "," mouseMoved "}; private MyButton b1 = new MyButton (Color.Blue, "Test1"), B2 = New MyButton (Color.Red, "Test2"); Class MyButton Extends JButton {Void Report (String Field, String MSG) {(JTextField) H.Get (Field) .setText (msg);} FocusListener fl = new FocusListener () {public void focusGained (FocusEvent e) {report ( "focusGained", e.paramString ());} public void focusLost (FocusEvent e) {report ( "focusLost" , E.ParamString ());}}; KeyListener kl = new KeyListener () {public void keyPressed (KeyEvent e) {report ( "keyPressed", e.paramString ());} public void keyReleased (KeyEvent e) {report ( "keyReleased", e.paramString ()) Public void keytyped (keyevent e) {report ("keytyped", E.ParamString ());}}; mouselistener ml = new mouselistener () {public void mouseclicked (MouseEvent E) {Report ("mouseclicked", e. Paramstring ());} public void mouseentered (mouseevent e) {report ("

mouseEntered ", e.paramString ());} public void mouseExited (MouseEvent e) {report (" mouseExited ", e.paramString ());} public void mousePressed (MouseEvent e) {report (" mousePressed ", e.paramString ());} public void mouseReleased (MouseEvent e) {report ( "mouseReleased", e.paramString ());}}; MouseMotionListener mml = new MouseMotionListener () {public void mouseDragged (MouseEvent e) {report ( "mouseDragged" , E.ParamString ());} public void mousemoved (MouseEvent E) {report ("mousemoved", E.ParamString ());}}; public mybutton (color color, string label) {super (label); setBackground color); addFocusListener (fl); addKeyListener (kl); addMouseListener (ml); addMouseMotionListener (mml);}} public void init () {Container c = getContentPane (); c.setLayout (new GridLayout (event.length 1 , 2)); for (int i = 0; i

Report () requires the name of the event and the parameter string of the event, and then finds JTextField in Hashmap H based on the name of the event, and write the parameter string.

This program is very interesting because it makes you intuitive see how the program handles events. The list of Swing Components is in your list of layout managers and event models. Next, learn how to use Swing components. This part is just a general introduction, we are talking about the common SWING components and their characteristics. We intend to make the routines relatively small, so you can move these code to your own program.

remember:

It is easy to run the routine, as long as you open the HTML page in the source code. (To www.bruceeckel.com) Downloaded with all Swing Components in the JDK document (only a small part here). The naming specification for Swing events is relatively reasonable, so you have to guess how to write and install the event handler is also relatively simple. Use our previous showaddlisteners.java to check the component. If things begin to become complex, congratulations, you have graduated, and you should use the Gui Builder. Buttonswing has included a lot of buttton, including various buttons, CHECK BOX, RADIO Button, and even Menu items (menu item) inherited AbstractButton (given the menu item also involved, (AbstractButton) may still be called "abstractselector" or other What name is better). We will soon see the usage of the menu item, but first let's take a look at Swing buttons:

//: C14: Buttons.java// Various Swing Buttons Width = 350 Height = 100> import javax.swing. *; import java.awt. *; import java.aw .event *;. import javax.swing.plaf.basic *;. import javax.swing.border *;. import com.bruceeckel.swing *;. public class Buttons extends JApplet {private JButton jb = new JButton ( "JButton" ); private BasicArrowButton up = new BasicArrowButton (BasicArrowButton.NORTH), down = new BasicArrowButton (BasicArrowButton.SOUTH), right = new BasicArrowButton (BasicArrowButton.EAST), left = new BasicArrowButton (BasicArrowButton.WEST); public void init () { Container CP = getContentPane (); cp.setLayout (new flowLayout ()); cp.add (jb); cp.add (New JToggleButton); cp.add (New JCheckbox ("jcheckbox"); Cp.Add ("jradiobutton"); jPanel JP = new jPanel (); jp.setborder (new title)); jp.add (up); JP.Add (down); JP. Add (left); jp.add (right); cp.add (jp);} public static Void main (String [] args) {console.run (New Buttons (), 350, 100);}} ///: ~ This program first demonstrates the BasicarrowButton of javax.swing.plaf.basic, followed by other shapes Button. When the program is running, you will find that Toggle Button can save whether the state is pressed. The CHECK BOX and RADIO Button behave are identical, as long as you click, you can turn it on or off (they are the derived class of JTogglebutton). BUTTON group If you want Radio Button to run in a "choice one" mode (Translator Note: Original is Exclusive or, the literal means "exclusive logic and"), you must add them to a "Button group ( Button group). But as shown in the following programs, but you can add ButtonGroup as long as it is AbstractButton.

In order to avoid the duplication of code, we use reflection to generate a variety of Button groups. Creating a Button group and the JPanel task is done by makebpanel (). It has two parameters, the second is an array of String. MakebPanel () creates the Button determined by the first parameter according to the string in the array, then add it to JPanel:

//: c14:. ButtonGroups.java// Uses reflection to create groups // of different types of AbstractButton.// import javax.swing *; import java .awt *;. import java.awt.event *;. import javax.swing.border *;. import java.lang.reflect *;. import com.bruceeckel.swing *;. public class ButtonGroups extends JApplet {private static String [] IDS = {"June", "Ward", "Beaver", "Wally", "EDDIE", "LUMPY",}; Static JPanel MakebPanel (Class Klass, String [] IDS) {ButtongRoup BG = New ButtonGroup JPanel JP = new jPanel (); string title = klass.getName (); title = title.substring (title.lastIndexof (') 1); jp.setBorder (new title); for (Title); int i = 0; i

} Public static void main (string [] args) {console.run (new buttonroups (), 500, 300);}} ///: ~ Border head is taken from class, put the path information before putting it up. . We first started AbstractButton with JButton marked with "failed", so that even if you ignore the abnormal information, (once you have a problem,) there will be reactions on the screen. The getConstructor () method returns a constructor object according to the Class array, which is determined by this Class array. Next, the newInstance () method is called. The parameters of this method are an Object array, that is, the parameters that constructor really needed - here is the string in the IDS array. These steps have added difficulties to the original simple task. To make Button to "choose a few choices", you must first create a Button group, then add the button you want to add. When running the program, you will find that all Button has shown the "choice one" effect in addition to jbutton.

Iconicon can be used in Jlabel and AbstractButton, including JButton, JCheckbox, JraDiobutton, and JMenuItem. It is very simple to use the syntax for Jlabel (you will be demonstrated immediately). Below this program will use the icon in turn to Button and its school.

You can also use your own GIF file, but here is still available on www.bruceeckel.com. If you want to open a file read image, just create an imageicon and pass the name of the file to it. Next, you can use this icon in the program.

//: C14: Faces.java// iCon Behavior in jbuttons.// import javax.swing. *; import java.awt. *; import java. AWT.Event. *; import java.io. *; import com.bruceeckel.swing. *; public class foots extends japplet {private static icon [] Faces; Private JButton JB, JB2 = New jbutton ("disable"); private Boolean Mad = false; public void init () {faces = new icon [] {new imageicon ("Face0.gif"), new imageicon (GetClass (). getResource ("face1.gif") New ImageCon ("face2.gif"), new imageicon ("face3.gif"), new imageicon ("face3.gif"), new imageicon (GetClass (). Getresource ("face4.gif" )),}; Jb = new jbutton ("jButton", Faces [3]); Container CP = getContentPane (); cp.setLayout; jb.addactionListener (new activityListener () {public void actionPerformed ActionEvent E) {IF (MAD) {JB.Seticon (Faces [3]); MAD = false;} else {j B.Seticon (Faces [0]); MAD = true;} jb.setVertical_; jb.sethorizontalalignment (JButton.Left);}}); jb.setrollovereNabled (TRUE); JB.serollovericon (Faces [ 1]); JB.SetPressed Indon (Faces [2]); jb.setdisabledicon (Faces [4]); JB.SetTooltiptext ("YOW!"); Cp.add (jb); jb2.addactionListener (new activityListener () { Public void actionperformed (jb.isenabled ()) {jb.setenabled (false); jb2.settext ("enable");} else {jb.setenabled (TRUE); jb2.settext ("disable" );

}}}); Cp.add (jb2); public static void main (string [] args) {console.run (New Faces (), 400, 200);}} ///: ~ Many SWING Component Construction Functions You can use icon to make parameters, but you can also add or modify the icon with the seticon () method. In addition, this program also demonstrates that when the button is listened to the event, it is when you press the button, the button, or (without pressing "button (but does not press). JButton (or other AbstractButton) makes it display different icons. You will find that you can use this technique to make a button with animation effect. Tool Tips We added a "Tool Tip" to the button above the program. Almost all classes related to the GUI are inheritance from JComponent, and JComponent also includes a settooltext (String) method. So no matter which component, you can almost use (assuming this is a JComponent's derived class object JC)

JC.SetTooltiptext ("My TIP"); to set Tool TIP. As long as the mouse stops on the JComponent for a while, you will jump out of a prompt box, which is the text you set.

TEXT FIELDS Let's take a look at what JtextField can do:

//: C14: Textfields.java// text Fields and java events .// import javax.swing. *; import javax.swing.event. *; import javax.swing.text *;. import java.awt *;. import java.awt.event *;. import com.bruceeckel.swing *;. public class TextFields extends JApplet {private JButton b1 = new JButton ( "Get Text "), B2 = new jbutton (" set text "); private jtextfield t1 = new jtextfield (30), t2 = new jtextfield (30), t3 = new jtextfield (30); private string s = new string (); private Uppercasedocument ucd = new uppercumentocument (); public void init () {t1.setdocument (ucd.adddocumentListener (new t1 ()); b1.addactionListener (new b2 ()); b2.addactionListener (new b2 ()) DocumentListener DL = New T1 (); T1.AddActionListener (New T1a ()); Container CP = getContentPane (); cp.setLayout (new flowLayout ()); cp.add (b1); cp.add (b2); Cp.Add (T1); CP.Add (T2); CP.Add (T3);} Class T1 Implements DocumentListener {Publi c void changedUpdate (DocumentEvent e) {} public void insertUpdate (DocumentEvent e) {t2.setText (t1.getText ()); t3.setText ( "Text:" t1.getText ());} public void removeUpdate (DocumentEvent e) {t2.setText (t1.gettext ());}} Class T1A Implements ActionListener {Private INT Count = 0; Public Void ActionPerformed (ActionEvent E) {T3.SETTEXT ("T1 Action Event" COUNT );}} Class B1 Implements ActionListener {Public Void ActionPerformed (ActionEvent E) {IF (T1.GetSelectedText () == NULL) S = T1.Gettext (); Else S = T1.GetSelectedText ();

t1.setEditable (true);}} class B2 implements ActionListener {public void actionPerformed (ActionEvent e) {ucd.setUpperCase (false); t1.setText ( "Inserted by Button 2:" s); ucd.setUpperCase (true) ; t1.setEditable (false);}} public static void main (String [] args) {Console.run (new TextFields (), 375, 125);}} class UpperCaseDocument extends PlainDocument {private boolean upperCase = true; public void setUpperCase (boolean flag) {upperCase = flag;} public void insertString (int offset, String str, AttributeSet attSet) throws BadLocationException {if (upperCase) str = str.toUpperCase (); super.insertString (offset, str, attSet); }}} ///: ~ The reason why JtextField T3 is to prepare a reporting event to JTextField T1 listeners. You will find that only after pressing the "Enter" key, JtextField's listener will react. JtextField T1 has a few Listener. T1 is DocumentListener, which reacts the change of "Document" (here is the content of JtextField). It (t1) copies the text in T1 to T2. In addition, since the Document T1 is the derived type UppercaSedocument type of Plationocument, it will force all characters in the document to capitalize. In addition, it can also detect the backup key, which can automatically delete the operation, adjust the cursor (CARET), which handles the event is exactly the same as your expectations.

There is a setBorder () method in Bordersjcomponent, which allows you to enjoy a funny border for a variety of visual components. Below we write a showborder () method to see these borders. This method creates a JPANEL and then put it on the border. We still get the name of the border by RTTI (remove path information), then put it in Jlabel in JPANel:

//: c14: borders.java// Different Swing Borders.// import javax.swing. *; import java.awt. *; import java.awt . Event javax.swing.border. *; import com.bruceeckel.swing. *; public class borders Extends japplet {static jpanel showborder (border b) {jPanel jp = new jPanel (); jp.setlayout (new BorderLayout (); string nm = B.GetClass (). TOSTRING (); nm = nm.substring (nm.lastIndexof ('.') 1); jp.add (new Jlabel (NM, Jlabel.center), BorderLayout.center; jp.setborder (b); returni} public void init () {Container CP = getContentPane (); cp.setLayout (new gridLayout (2, 4)); cp.add (showborder (New Titleder) ("Title"))); CP.Add (New etchedborder ()); cp.add (new lineborder (color.blue)); cp.add (new matteborder (5, 5, 30, 30, color.green))))); cp.add (new bevelborder.raised)); cp.add (showborder (new software) ); Cp.add (New CompoundBorder (New etchedborder (), new lineborder (fold.red))))));} public static void main (string [] args) {console.run (New Borders (), 500, 300);}} ///: ~ You can also create your own border, then put it in the button (Button), label (label) or other controls, - as long as it is inheriting JComponent. Jscrollpanes Most of you only need JscrollPane to do its job, but you can also control it, tell it which scroll bar - vertical, horizontal, or both display or two do not display .

//: c14:.. JScrollPanes.java// Controlling the scrollbars in a JScrollPane.// import javax.swing *; import java.awt *; import java.awt.event *;. import javax.swing.border *;. import com.bruceeckel.swing *;. public class JScrollPanes extends JApplet {private JButton b1 = new JButton ( "Text Area 1"), b2 = new JButton ("Text Area 2"), B3 = New JButton ("Replace Text"), B4 = New JButton ("Insert Text"); Private Jtextarea T1 = New Jtextarea ("T1", 1, 20), T2 = New Jtextarea ("T2", 4, 20), T3 = New Jtextarea ("T3", 1, 20), T4 = New Jtextarea ("T4", 10, 10), T5 = New Jtextarea ("T5", 4, 20 ), t6 = new JTextArea ( "t6", 10, 10); private JScrollPane sp3 = new JScrollPane (t3, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), sp4 = new JScrollPane (t4, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), SP5 = New JScrollpane (T5, JScrollpane.v ERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS), sp6 = new JScrollPane (t6, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); class B1L implements ActionListener {public void actionPerformed (ActionEvent e) {t5.append (t1.getText () "/ n" }}}} Class b2l imports actionListener {public void actionperformed (ActionEvent E) {T2.Settext ("Inserted by Button 2"); t2.append (":" t1.getText ()); t5.append (t2. GetText () "/ n");

}} Class B3L implements ActionListener {public void actionPerformed (ActionEvent e) {String s = "Replacement"; t2.replaceRange (s, 3, 3 s.length ());}} class B4L implements ActionListener {public void actionPerformed ( ActionEvent E) {t2.insert ("inserted", 10);}} public void init ()} public void init () {Container CP = getContentPane (); cp.setLayout (new flowLayout ()); // Create Borders for Components: border brd = BorderFactory.createMatteborder (1, 1, 1, 1, color.black); t1.setborder (brd); t2.setborder (brd); sp3.setborder (brd); sp4.setborder (BRD); sp5.setborder (BRD) ); Sp6.setBorder (brd); // initialize listener and add components: b1.addactionListener (new b1l ()); cp.add (b1); cp.add (t1); b2.addactionListener (new b2l ()) CP.Add (b2); cp.add (t2); b3.addActionListener (new b3L ()); cp.add (b3); b4.addActionListener (New B4L ()); cp.add (b4); CP .add (sp3); cp.add (sp4); cp.add (sp5); cp.add (sp6); Public static void main (string [] args) {console.run (New Jscrollpanes (), 300, 725);}} ///: ~ Pass different parameters by means of a constructor of Jscrollpane, you can control its scroll bar. Here we also do decoration with a border. A pocket editor does not have much effort, JtextPane has provided a lot of editing features. Below we simply demonstrate this component, pay attention to we ignore the vast majority of its features:

//: C14: TextPane.java// The jtextpane control is a little editor.import javax.swing. *; import java.awt. *; import java.awt.event. *; import com.bruceeckel.swing. *; import com.bruceeckel.util *;. public class TextPane extends JFrame {private JButton b = new JButton ( "Add Text"); private JTextPane tp = new JTextPane (); private static Generator sg = new Arrays2.RandStringGenerator (7); Public textpane () {b.addActionListener (new actionListener () {public void actionPerformed (INT i = 1; i <10; i ) tp.setText (tp.gettext () sg.next () "/ n");}}); container cp = getContentPane (); cp.add (new jscrollpane (tp)); cp.add (borderLayout.South, b);} public static void main (String [] args ) {Console.run (New TextPane (), 475, 425);}} ///: ~ The role of the button is randomly generated for some text, then add it to JtextPane. JtextPane means providing a place that allows you to edit text, so you will find it no append () method. Here (frankly, we don't use the feet of JtextPane ". We can only use setText () to get text, modify it, and then put back into JtextPane. As we mentioned earlier, the default layout of Applet is BorderLayout. So if you don't say anything, add components directly to the panel, then it will fill the entire panel. But if you specify its location (North, South, EAST, or West), the control will be stained in this area. Here the button will be placed below the screen.

Note that JTextPane's built-in features, such as automatic wrap. In addition, it still has many other features. For details, please refer to the JDK documentation.

Check Boxescheck Box allows you to do item-by-item. It consists of a small frame and a label. In general, there will be one 'x' (or any other indicator in the box), otherwise it is empty.

In general, when you create JCHECKBOX with a constructor, it is passed to a parameter used as a label. After JCHeckbox is created, you can also read or set it at any time, or read or reset it.

No matter whether it is selected or cleared, JCheckbox will trigger an event. The capture method is exactly the same as the button event: uses ActionListener. Let's take an example below. JtexTarea here will record all Check Box events:

//: c14: checkboxes.java// using jcheckboxes.// import javax.swing. *; import java.awt.event. *; import java. awt *;. import com.bruceeckel.swing *;. public class CheckBoxes extends JApplet {private JTextArea t = new JTextArea (6, 15); private JCheckBox cb1 = new JCheckBox ( "Check Box 1"), cb2 = new JCheckBox ( "Check Box 2"), CB3 = New Jcheckbox ("Check Box 3"); public void init () {cb1.addActionListener (new actionListener () {public void actionPerformed (ActionEvent E) {trace ("1", CB1) ;}}); cb2.addActionListener (new ActionListener () {public void actionPerformed (ActionEvent e) {trace ( "2", cb2);}}); cb3.addActionListener (new ActionListener () {public void actionPerformed (ActionEvent e ) {Trace ("3", cb3);}}; container cp = getContentPane (); cp.setLayout (new flowLayout ()); cp.add (new jscrollpane (t)); cp.add (CB1); Cp.Add (CB2); cp.add (cb3); Private Void Trace (String B, JCheckbox CB) {if ("Box" B "SET / N"); Else T.Append ("Box" B "Clead / n ");} public static void main (string [] args) {console.run (New Checkboxes (), 200, 200);}} ////: ~ trace () uses the append () method to put JCheckbox The name and the information that are not selected to the JTextField. So you will see the list of Checkbox selection records and its current state. The concept of Radio Button in Radio button is from the mechanical button in the vintage car radio; when you press a button, the other will pop up. So you can only choose one.

To create a group of associated JRADiobutton, you can add them to ButtonGroup (any number of ButtonGroups are allowed in a form). If you (the second parameter of the constructor), set multiple radio button to true, then only the last one is valid.

Let's take a simple example. Note that the method of capturing the Radio Button event is identical to capture other events: //: C14: Radiobuttons.java// using jradiobuttons./ import javax. swing *;. import java.awt.event *;. import java.awt *;. import com.bruceeckel.swing *;. public class RadioButtons extends JApplet {private JTextField t = new JTextField (15); private ButtonGroup g = new ButtonGroup (); private JRadioButton rb1 = new JRadioButton ( "one", false), rb2 = new JRadioButton ( "two", false), rb3 = new JRadioButton ( "three", false); private ActionListener al = new ActionListener () {Public Void ActionPerformed (ActionEvent E) {T.Settext ("Radio Button" E.GETSource ()). GetText ());}}; public void init () {RB1.AddActionListener (al); Rb2.addActionListener (Al); RB3.AddActionListener (al); g.Add (RB1); G.Add (RB2); G.Add (RB3); T.setedItable (false); Container CP = getContentPane (); CP .setLayout (New flowLayout ()); cp.add (t); cp.add (rb1); cp.add (rb2); Cp.Add (RB3); public static void main (String [] args) {console.run (New Radiobuttons (), 200, 100);}} ///: ~ For observation, we use a Text Field . We set it into an invigible, because it is not used to collect data, but only to display data. It can also be seen that it can replace JLabel.

Combo Boxes, like the Radio button, the drop-down list only allows the user to select an element in a set of options. But this approach is more concise, but it can modify the elements in the list without disturbing the customer. (You can also dynamically modify the Radio Button, but this visual effect is too strange).

JCOMBOBOX's default behavior is not the same as Windows Combo Box. In Windows, you can choose one from the list of Combo Box, you can also enter it yourself, but in JCOMBOBOX, you must call setITable (). In addition, you can only select one from the list. Let's take an example. Let's add a few options to JCOMBOBOX, and then add an option every button.

//: C14: ComboBoxes.java// using drop-down lists .// import javax.swing. *; import java.awt.event. *; import java.awt *;. import com.bruceeckel.swing *;. public class ComboBoxes extends JApplet {private String [] description = { "ebullient", "Obtuse", "Recalcitrant", "Brilliant", "Somnescent", " Timorous "," Florid "," Putrescent "}; private jtextfield t = new jtextfield (15); private jcomboBox c = new jcomboBox (); private jbutton b = new jbutton (" add items "); private int count = 0; Public void init () {for (int i = 0; i <4; i ) C.Additem (Description [count ]); t.seteditable (false); B.AddActionListener (new actionListener () {public void ActionPerformed (ActionEvent) e) {IF (count

Jlist can do a number of options; if you have more than more than one option (when you choose to use the mouse, press the "Control" button), then the selected option will always be "highlightted) ", So you can choose any more. If you choose one, then then Shift-Click another, then all options between the two options are selected. To cancel a option, as long as the control-click is OK.

//: C14: list.java// import javax.swing. *; import javax.swing.event. *; import java.awt. *; import java.awt.event *;. import javax.swing.border *;. import com.bruceeckel.swing *;. public class List extends JApplet {private String [] flavors = { "Chocolate", "Strawberry", "Vanilla Fudge Swirl "," Mint Chip "," Mocha Almond Fudge "," Rum Raisin "," Praline Cream "," Mud Pie "}; private DefaultListModel lItems = new DefaultListModel (); private JList lst = new JList (lItems); private JTextArea t = new JTextArea (flavors.length, 20); private JButton b = new JButton ( "Add Item"); private ActionListener bl = new ActionListener () {public void actionPerformed (ActionEvent e) {if (count

T.SetBorder (BRD); // add the first four items to the list for (INT i = 0; i <4; i ) LITEMS.ADDELEMENT (Flavors [Count ]); // add items to the content Pane for Display Cp.Add (T); cp.add (LST); cp.add (b); // register event listener Lst.AddListSelectionListener (LL); B.AddActionListener (BL);} public static void main (String [] args ) {Console.Run (New List (), 250, 375);}} ///: ~ You will find that we give a list of borders. If you just want to put the String array into Jlist, there is a simpler way; that is, the array is transmitted to the JList's constructor as a parameter so that it will automatically create a list. In the above routine, the only reason to use the list model is that the list is manipulated when the program is running.

JLIST does not automatically provide a scroll shaft. Of course, as long as it is embedded in jscrollpane, it will automatically set up the scroll axes, and the specific details are taken to care.

Tabbed panesjtabbedpane can create a "Tabbed Dialog" with a tab, that is, there is a pair of tabs on the dialog box, you just click on this tab, the dialog box will put this page. display.

//: C14: Tabbedpane1.java// DemonStrates the Tabbed Pane.// import javax.swing. *; import javax.swing.event. *; import java.awt *;. import com.bruceeckel.swing *;. public class TabbedPane1 extends JApplet {private String [] flavors = { "Chocolate", "Strawberry", "Vanilla Fudge Swirl", "Mint Chip", "Mocha Almond Fudge "," Rum Raisin "," Praline Cream "," Mud Pie "}; private jtabbedpane tabs = new jtabbedpane (); private jtextfield txt = new jtextfield (20); public void init () {for (int i = 0 i

The Message Boxes graphics interface system usually contains a set of standards that allow you to quickly pass messages to users, or get information from users. For Swing, these message boxes are included in JOPANE. You have a lot of choices (some are quite complicated), but the most commonly used "confirmation dialog", which is started with Static Joptionpane.showMessageDialog () and JOptionpane.showConfirmDialog (). Let's demonstrate some dialog boxes in JOPANE.

//: C14: MessageBoxes.java// import javax.swing. *; import java.awt.event. *; import java. AWT. *; import com.bruceeckel.swing. *; public class message.com {private jbutton [] b = {new jbutton ("alert"), New JButton ("Yes / no"), New JButton ("Color" ), new JButton ( "Input"), new JButton ( "3 Vals")}; private JTextField txt = new JTextField (15); private ActionListener al = new ActionListener () {public void actionPerformed (ActionEvent e) {String id = (Jbutton) E.GetSource ()). GetText (); IF (id.equals ("alert")) JOPTIONPANE.SHOWMESSAGEDIALOG (NULL, "There's a bug on you!", "Hey!", Joptionpane.Error_Message) ELSE IF (ID.Equals ("YES / NO")) JOPTIONPANE.SHOWCONFIRMDIALOG (NULL, "OR no", "choose yes", joptionpane.yes_no_option; else if (id.equals ("color")) {Object [] options = {"red", "green"}; int SEL = JOPA ne.showOptionDialog (null, "! Choose a Color", "Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options [0]); if (! sel = JOptionPane.CLOSED_OPTION) txt.setText ( "Color SELECTED: " Options [SEL]);} else if (id.equals (" input ")) {string val = joptionpane.showinputdialog (" How Many Fingers Do you see? "); Txt.setText (VAL);} Else IF (id.equals)) {object [] selects = {"first"

, "SECOND", "third"}; object val = joptionpane.showinputdialog (Null, "Choose One", "Input", JOPTIONPANE.INFORMATION_MESSAGE, NULL, Selections, Selections [0]); if (Val! = Null) TXT .SETTEXT (VAL.TOSTRING ());}}}; public void init () {Container CP = getContentPane (); cp.setLayout (new flowLayout ()); for (int i = 0; i

Menu All components that can contain menus, including Japplets, JFrame, JDialog, and components they are derived, have a setjmenubar () method that requires JMenubar as a parameter (a component can only have a jMenubar). You can join JMenu to jMenubar and join JMenuItem to JMenu. Each JMenuitem can be connected to an ActionListener, when you select the menu item, the event is issued.

Different from the system of using resources, Java and Swing require you to assemble the menu with source code. Here is a very simple menu routine:

//: c14: Simplemenus.java// import javax.swing. *; import java.awt.event. *; import java.awt. *; import com.bruceeckel.swing *;. public class SimpleMenus extends JApplet {private JTextField t = new JTextField (15); private ActionListener al = new ActionListener () {public void actionPerformed (ActionEvent e) {t.setText (((JMenuItem) e .GetSource ()). GetText ());}}; private jmenu [] Menus = {New JMenu ("Winken"), New Jmenu ("BLINKEN"), New Jmenu ("NOD")}; private jmenuitem [] Items = {New Jmenuitem ("Fee"), New Jmenuitem ("Fi"), New Jmenuitem ("FO"), New Jmenuitem ("Zip"), New Jmenuitem ("ZAP"), New Jmenuitem ("Zot") New Jmenuitem ("OLLY"), New Jmenuitem ("OXen"), New Jmenuitem ("Free")}}}}}}}; public void init () {for (int i = 0; i

JMenuItem is the derived class of AbstractButton, so it has some similar buttons. JMenuItem itself is a menu option that can be placed in a drop-down menu. In addition, JMenuItem has three derived classes: JMenu to hold other JMenuitem (so you can do laminated menus); there is a JCheckBoxMenuItem that can indicate whether the candidate mark (Checkmark) "; and contains a Radio Button's JRADIOBUTTONMENUITEM. Let's take a more complex example, this time we have to use ice cream taste. This example also demonstrates a laminated menu, shortcut, JCheckBoxMenuItem, and other methods that can dynamically change menu:

//: C14: Menus.java// Submenus, CheckBox Menu Items, Swapping Menus, //mnemonics (shortcuts) and action commands.// import javax. Swing. *; import java.awt. *; import java.awt.event. *; import com.bruceeckel.swing. *; public class menus extends japplet {private string [] flavors = {"chocolate", "strawberry", "Vanilla Fudge Swirl", "Mint Chip", "Mocha Almond Fudge", "Rum Raisin", "Mud Pie", "Mud Pie"}; Private JtextField T = New Jtextfield ("NO Flavor", 30); Private Jmenubar MB1 = new jmenubar (); private jmenu f = new jMenu ("file"), m = new jmenu ("flavors"), s = new jmenu ("safty"); // alternative approach: private jcheckboxMenuItem [] saFety = {New JCHECKBOXMENUITEM ("Guard"), New JCheckBoxMenuItem ("HIDE")}}; private jmenuitem [] file = {new jmenuitem ("open")}; // a second menu bar to swap to: private jmenuBar MB2 = New jMenubar (); Private jmenu foobar = new jmenu ("foobar"); private jmenuitem [] other = { // adding a menu shortcut (mnemonic) IS VERY // SIMPLE, But Only Jmenuitems Can Have The // In Their Constructionors: New Jmenuitem ("Foo", Keyevent.vk_f), New Jmenuitem ("Bar", Keyevent.vk_a) , // No shortcut: new JMenuItem ( "Baz"),}; private JButton b = new JButton ( "Swap Menus"); class BL implements ActionListener {public void actionPerformed (ActionEvent e) {JMenuBar m = getJMenuBar (); setJMenuBar (m == MB1? MB2: MB1); validate ();

// Refresh the frame}} class ML implements ActionListener {public void actionPerformed (ActionEvent e) {JMenuItem target = (JMenuItem) e.getSource (); String actionCommand = target.getActionCommand (); if (actionCommand.equals ( "Open" )) {String s = t.getText (); boolean chosen = false; for (int i = 0; i

Else if ("hide")) T.SetText ("Hide the ice cream!" "is it hidden?" target.getState ());}} public void init () {ml ml = new Ml (); cmil cmil = new cmil (); safty [0] .SetActionCommand ("Guard"); Safety [0] .SETMNEMONIC (KeyEvent.vk_g); Safety [0] .additemlistener (cmil); safty [1] .SetActionCommand ("hide"); Safety [1] .SETMNEMONIC (KeyEvent.vk_h); Safety [1] .additemlistener (cmil); Other [0] .addactionListener (new fool ()); other [1] .addactionListener NEW BARL ()); other [2] .addactionListener (new bazl ()); FL FL = New fl (); for (int i = 0; i

Then traverse this array and call the JMenuItem's Add () method one by one. This makes the task that adds and deletes menu items to be less annoying. To demonstrate the dynamically exchanged menu bar during operation, we have created two JMenubar. You will find that JMenuBar is composed of JMenu, while JMenu is composed of JMenuItem, JCHECKBOXMENUITEM, JMENU (it creates submenu). When JMenuBar is assembled, you can use the setjmenubar () method to install it into the current program. Note When you press the button, it uses getjmenubar () to determine the current menu and then replace another menu.

Test "Open" should pay attention to spelling and uppercase, but if the "open" does not match, Java does not report. This comparison of such a string is a major cause of initiating programming errors.

The program will automatically check or restore the menu item. JCHECKBOXMENUITEM code demonstrates how two methods that determine which menu item that should be ticked. One is a matching string (although it is also used, it is like the above, it is not very safe), the other is the matching event target object. As you can see, the getState () method can return the status of JCheckBoxMenuItem, and setState () can set it.

The menu event is not very consistent, which may cause confusion. JMenuitem uses an ActionListener event, while JCheckBoxMenuItem uses the itemListener event. JMenu also supports ActionListener, but usually nothing. In short, you have to prepare a listener for each JMenuitem, JCheckBoxMenuItem or JraDiobuttonMenuItem, but we have stole it to you, connect an itemListener and ActionListener to multiple menu components.

Swing supports a mission, or says "shortcut" so you can throw away the mouse with keyboard to select AbstractButton (button, menu item, etc.). To do this, take the JMenuitem for example, you can use it to overload the constructor to pass the identifier of the shortcut as the second parameter to it. However, most AbstractButton did not provide similar constructor, so a relatively general method is to use the setmnemonic () method. In the above routine, we add shortcuts for buttons and multiple menu items, which are automatically displayed on the component.

In addition, we also demonstrate usage of setArtionCommand (). It may be somewhat weird, because "action command" is the label on the menu. Why not use the label directly, but use the string to replace it? The problem is international. If you want to modify the source code, let the program run in another locale (modify the source code, there is no doubt that you will bring new errors), just change the label on the menu. So in order to simplify the code for the menu string, you can let "Action command" remain unchanged, so that the label on the menu is not tight. Note that we don't have an action command that checks the menu one by one, so those who don't check, we don't have an action command.

Most things are done in the listener. BL is responsible for the switch of JMenubar. ML first finds "Who is in the bell", the idea is to find the source of ActionEvent, then convert it into JMenuItem, then transfer the action command to a cascade IF statement.

Although FL wants to handle all the tastes in the Flavor menu, it is still very simple. If your idea is clear enough, this method is still very useful, but usually, you have to prepare a listener for each menu item, just like Fool, Barl and Bazl, so you don't need to write the probe code. And you can also know who is calling that Listener. Although this will increase the number of classes, the code of each class is reduced, and the process of the program is also "anti-staying". You will find that the menu code will become growing and chaotic. Here is the GUI Builder that can make a big manner. Good tools should help you maintain your menu.

Pop-up menu To implement JPopupMenu, the most straightforward way is to create an internal class that inherits the MouseAdapter, then add the instance of this internal class to the component to provide pop-up menu:

//: C14: Popup.java// Creating popup menus with swing.// import javax.swing. *; import java.awt. *; import java .awt.event *;. import com.bruceeckel.swing *;. public class popup extends JApplet {private JPopupMenu popup = new JPopupMenu (); private JTextField t = new JTextField (10); public void init () {Container cp = GetContentPane (); cp.setLayout (new flowLayout ()); cp.add (t); actionListener al = new actionListener () {public void actionPerformed (ActionEvent E) {T.SETTEXT ((jMenuitem) E.Getsource () ) .getText ());}}; jMenuitem m = new jmenuitem ("hither"); M.AddActionListener (al); popup.add (m); m = new jmenuitem ("yon"); M.AddActionListener (al ); Popup.add (m); m = new jmenuitem ("afar"); M.AddActionListener (AL); popup.add (m); popup.addseParetor (); m = new jmenuitem ("stay here"; M.AddActionListener (al); popup.add (m); popuplistener pl = new popuplistener (); addmouseristener (Pl); t.addMouseListener (pl);} class PopupListener extends MouseAdapter {public void mousePressed (MouseEvent e) {maybeShowPopup (e);} public void mouseReleased (MouseEvent e) {maybeShowPopup (e);} private void maybeShowPopup (MouseEvent e) {IF (E.Ispopuptrigger ()) popup.show ((japplet) E.GetComponent ()) .getContentPane (), E.GETX (), E.GETY ());}} public static void main String [] args) {console.run (New popup (), 300, 200);}} ///: ~ JMenuitem is used by the same ActionListener, which is responsible for submitting text from the menu tab and insert it into JtextField.

Painting a good GUI framework makes a relatively simpler - indeed, Swing is done. All mapping problems face the same difficult point, that is, compared to the drawing function, calculate where to paint things will usually be more difficult, but unfortunately, this calculation is often mixed with the call of the mapping function, so The actual complexity of the function of the function is likely to be simpler than what you think. Long-term short talk, think about how to draw data on the screen. Assuming that we use the Java's built-in Math.sin () function, it is the sinusoidal function to provide data. In order to improve your interest, it also demonstrates the ease of use of the Swing component, and we put a slider at the bottom of the form, use it to dynamically control the number of cycles of the sine wave. Also you will find that if the size of the window changes, the sine wave will automatically adjust its shape according to the size of the new window.

Although you can paint on any JComponent, that is, they can act as canvas, but if you want a whiteboard that you can paint, it is best to create a class inherited JPanel. This way you only need to overwrite a method, that is, PaintComponent () is OK. This method is automatically called when the system needs to redraw components (usually, you don't have to worry about this because this is controlled by swing). When calling, swing will pass a Graphics object to this method so you can use this object.

In the following example, all information related to mapping is included in the SINDRAW class; SINEWAVE is only responsible for configuring programs and Slider. SINDRAW's setCyCles () method is a hook that allows other objects - here is the number of Slider - control cycles.

//: C14: Sinewave.java// Drawing with swing, using a jslider.// import javax.swing. *; import javax.swing.event. *; import java.awt *;. import com.bruceeckel.swing *;. class SineDraw extends JPanel {private static final int SCALEFACTOR = 200; private int cycles; private int points; private double [] sines; private int [] pts Public SINDRAW () {setcycles (5);} public void setcycles (int newcycles) {cycles = newcycles; points = scalefactor * cycles * 2; sines = new double [Points]; for (int i = 0; i

adjustCycles.addChangeListener (new ChangeListener () {public void stateChanged (ChangeEvent e) {sines.setCycles (((JSlider) e.getSource ()) getValue ());.}}); cp.add (BorderLayout.SOUTH, adjustCycles } Public static void main (String [] args) {console.run (New Sinewave (), 700, 400);}} ///: All fields and arrays are The use field is sent; Cycles means that the sine wave to display a few cycles, Points means that you want to draw a few points, Sines store the value of the strings, and PTS stores the Y coabs on each point on the JPanel. SetCyCles () method will create an array as needed, then calculate the value of the SINES array item by item. SetCycles () can force call PaintComponent () through the repaint () method, so that the rest of the work will be accepted. When overwriting PaintComponent (), you must first call the same name method of the base class. The next thing to do will be determined by you; usually the way to call Graphics is painted on the JPANel or colored on its pixels. To see how to use these methods, you can check the Java.awt.graphics document (you can go to Java.sun.com to find a JDK document). You will find that most of the code here is doing the calculation; the code that the real control screen output is actually only two lines, setColor () and Drawline (). There will be similar feelings when you write this procedure in the future. Most of the time is to make what the painting is determined, and the real mapping process is very simple.

When I wrote this program, most of the time spent on how to display sine waves. After you finish, I found that if you can dynamically change the number of cycles, it should be very good. I know that if you use other programming languages, this difficulty is quite big, so I have some hesitation. But what I can't think of this is the simplest part of this project. I created a JSLider (parameter is the value of Jslider moves to the left side, what is the value, what is the value of the right side, and what is the initial position, but there are other constructor, then put it The bottom side of the japplet. Then I turned over the JDK document and found that it only had a listener AddChangeListener. When the slider changes, it is triggered when it is enough to generate a new value. It has only one way, the name is also very good, called StateChanged (). This method requires a ChangeEvent object so that I can find the source of the event and find that the new value is. Next, as long as the setcycles () with sines can be called into JPanel and redraw graphics.

In short, you will find that most swing issues can be solved by similar steps, and usually this step is quite simple, even if you never have used this component.

If the problem is very complicated, there are some more complex solutions such as the third party JavaBean or Java 2D API. These contents have exceeded the scope of this book, but if your mapping code is very complicated, it should be checked.

The dialog said that the dialog box refers to the window that can be played from other windows. Its role is that the details of the details are dealt with if they do not engage in the original window. The use of the dialog in the GUI programming is wide, but there is not much used in the applet. To create a dialog, you have to inherit JDIALOG first. Like JFrame, JDialog is another Window, which also has a layout manager (BorderLayout by default) or event listener can also be used. It has an important difference with JFrame, which is to close the program when the dialog is closed. On the contrary, you have to use the Dispose () method to release the resources occupied by the dialog window all. Let's take a simple example:

//: C14: Dialogs.java// Creating and use Dialog Boxes.// import javax.swing. *; import java.awt.event. *; import java.awt *;. import com.bruceeckel.swing *;. class MyDialog extends JDialog {public MyDialog (JFrame parent) {super (parent, "My dialog", true); Container cp = getContentPane (); cp.setLayout (New flowLayout ()); cp.add ("Here is my dialog"); jButton ok = new jbutton ("ok"); ok.addActionListener (new actionListener () {public void ActionPerformed (ActionEvent E) {Dispose (); // closs (ok); setsize (150, 125);}} public class dialogs extends japplet {private jbutton b1 = new jbutton ("Dialog Box"); private mydialog DLG = New MyDialog (NULL); public void init () {b1.addactionListener (new actionListener () {public void actionPerformed (ActionEvent E) {dlg.show ();}}); getContentPane (). Add (b1);} Public static void main (string [] args) {Console.Run (New Dialogs (), 125, 75);}} ///: ~ Once you have created JDialog, you have to use show () to display and activate it. When you close the dialog, you have to remember to dispose ().

You will find that all pop-ups, including dialogs, including dialog boxes, including "invisible". That is to say, there is a warning in the pop-up window. This is because theoretical malicious code can use this feature to fool the user, let them feel that they are running a local app, then misleading them into their own credit card number, and then passing the web. Applets are always connected to the webpage, so you can only use the browser, but the dialog can be separated from the web page, so it is theoretically this deceptive means is established. So in this way, Applet will not use the dialog box. Let's take a complicated example; first define a special button called TOEBUTTON, then create a dialog (with GridLayout) with the lattice it consists. This button draws a frame at its edge, and displays blank, "x" or "o" according to the status of its situation. When I started, the plaid was blank. When you click on it, it will modify its status according to the "x" or "O" now. However, when you press the button, it will switch between "X" and "O". (This is more step more than Tie-Tac-ToE concept.) In addition, the number of rows and columns of the lattice in this dialog can also be adjusted according to the parameters of the main window.

//: C14: Tictactoe.java// Dialog Boxes and create your = TictactoE width = 200 height = 100> import javax.swing. *; import java.awt. *; import java.awt.event *;. import com.bruceeckel.swing *;. public class TicTacToe extends JApplet {private JTextField rows = new JTextField ( "3"), cols = new JTextField ( "3"); private static final int Blank = 0, XX = 1, OO = 2; Class Toedialog Extends JDialog {Private Int Turn = XX; // Start with x's Turn TOEDIALOG (INT CELLSWIDE, INT CELLSHIGH) {setTitle ("The Game Itself"); Container CP = GetContentPane (); cp.setLayout (New GridLayout (Cellswide, CellShigh); for (int i = 0; i

} Class ML Extends Mouseadapter {public void mousepressed (mouseEvent E) {if (state == blank) {state = TURN; TURN = (TURN == xx? Oo: xx);} else state = (state == xx? Oo : XX); repaint ();}}}} class BL implements ActionListener {public void actionPerformed (ActionEvent e) {JDialog d = new ToeDialog (Integer.parseInt (rows.getText ()), Integer.parseInt (cols.getText ( )))); D.Setvisible (TRUE);}} public void init () {JPANEL P = new jPanel (); p.setLayout (New GridLayout (2, 2)); P.Add (New Jlabel ("Rows" , Jlabel.center); P.Add (rows); P.Add ("Column", JLabel.center); P.Add (cols); container cp = getContentPane (); cp.add (p) BorderLayout.North; JButton B = New JButton ("Go"); B.AddActionListener (New BL ()); cp.add (b, borderLayout.South);} public static void main (String [] args) { Console.run (New Tictactoe (), 200, 100 );}} ///: ~ Since STATIC can only be used for host classes, there is no more static data or nested classes in the internal class. PainTComponent () is responsible for drawing the boxes around the Panel and "X" or "O". Although it is full of monotonic calculations, it is still concise.

MouseListener is responsible for capturing clicks, which first looks at the Panel. If not, it will look at the status of TOEBUTTON, which is to ask where to ask the father window. Based on internal classes, ToeButton can access and modify the TURN of the host class. If the button has already displayed "x" or "o", then switch status. From this code, you can experience the benefits of the IF-Else's ternary expressions in our third chapter. After the state is finished, then refresh Toebutton.

TOEDIALOG's constructor is quite simple; add the button to GridLayout according to the parameters you give, and then set each button to 50 pixels.

Finally, TictactoE creates two jtextfield (to enter a button and column) and a "Go" button and use this button's ActionListener to complete the entire program. When you press the button, the listener reads the data in JtextField. Since it is a String type, you have to convert them in ints with static integer.parseint () first. File dialogs Some operating systems have built some special dialogs, such as dialog boxes such as font, colors, printers. In fact, all graphics operating systems provide dialogments to open and store files, so in order to simplify the approach, Java packages them into Jfilechooser.

Below this program demonstrates two JFilechooser dialogs, one for opening the file, another is used to store files. The vast majority of code is already an old acquaintance, the real interesting thing is concentrated on the two button event listeners:

//: c14: filechoosertest.java// Demonstration of File Dialog boxes.import javax.swing. *; import java.awt. *; import java.awt.event. *; import com.bruceeckel.swing. *; public class FileChooserTest extends JFrame {private JTextField filename = new JTextField (), dir = new JTextField (); private JButton open = new JButton ( "Open"), save = new JButton ( "Save"); public FileChooserTest () {JPanel p = NEW JPANEL (); Open.AddActionListener (New OpenL ()); P.Add (Open); Save.AddActionListener (new savel ()); P.ADD (SAVE); Container CP = getContentPane (); cp.add p, borderlayout.south; dir.setedItable (false); filename.setedItable (false); p = new jPanel (); p.setLayout (2, 1)); P.Add (filename); p. add (dir); cp.add (p, BorderLayout.NORTH);} class OpenL implements ActionListener {public void actionPerformed (ActionEvent e) {JFileChooser c = new JFileChooser (); // Demonstrate "Open" dialog: int rVal = c .Showopendialog (Filechooser Test.this); if (rval == jfilechooser.Approve_option) {filename.setText (c.getSelectedFile (). GetName ()); dir.setText (C.GetCurrentDirectory (). Tostring ());} if (rval = = JFileChooser.CANCEL_OPTION) {filename.setText ( "You pressed cancel"); dir.setText ( "");}}} class SaveL implements ActionListener {public void actionPerformed (ActionEvent e) {JFileChooser c = new JFileChooser (); / / DemonStrate "Save" Dialog: int RVAL = C.Showsavedialog (filechoosertest.this); if (rval == jfilechooser.Approve_option) {filename.settext (c.getSelectedFile (). Getname ());

Dir.Settext (C.GetcurrentDirectory (). toString ());} if (rval == jfilechooser.cancel_option) {filename.Settext ("You Pressed Cancel"); Dir.SetText ("");}}} public static Void main (String [] args) {console.run (New Filechoosrtest (), 250, 110);}} ///: Note JFilechooser has many modulations available, more than one filter filter file name Category. To call ShowOpendialog () with the "Open File" dialog box, use the "Save File" dialog box to call showsavedialog (). These two functions will not return before the dialog is turned off. Even if the dialog is closed, the JFilechooser object is still still, so you still read its data. To know the results of the operation, you can use getSelectedFile () and getCurrentDirectory (). If the NULL is returned, the user presses Cancel.

The HTML all of the SWING components All components that display files can be displayed in accordance with HTML rules to display HTML text. That is to say, you can easily let Swing components show a very dazzling text. such as:

//: c14: htmlbutton.java // putting html text on swing components.// import javax.swing. *; import java.awt.event. * Import java.awt. *; import com.bruceeckel.swing. *; public class htmlbutton extends japplet {private jbutton b = new jbutton (" " "
Hello!
Press Me Now! "); Public void init () {b.addActionListener (new activityListener () {public void actionPerformed (ActionEvent E) {getContentPane (). Add (new Jlabel (" " " kapow! ")); // force a re-layout to include the new label: validate ();}}); container cp = getContentPane (); CP. SetLayout (New flowLayout ()); cp.add (b);} public static void main (string [] args) {console.run (New HTMLButton (), 200, 500);}} ///: ~ Text must The beginning of "", you can mark with ordinary HTML. Note that it doesn't force you to turn off the tag. ActionListener adds a new one to the form and also shows the JLabel for HTML text. But this Label is not added in init (), so you must call ContaLidate () methods, forced it to re-print it for the component (so the new label is displayed).

JTabbedpane, JMenuItem, JTooltip, JRADIOBUTTON, and JCHECKBOX support HTML text.

Slider and Process Bar Slider (we have been used in SINEWAVE.JAVA) allows users to enter data by moving back and forth, sometimes this approach is still very intuitive (forced to adjust the volume). ProGress Bar displays data in a class ratio, it indicates that the data is "all" or "empty", so the user can have a more comprehensive understanding. To give these two things, my favorite practice is to combat the slider and processes, so when you move Slider, the process strip has changed accordingly:

//: c14: progress.java//// import javax.swing. *; import java.awt. *; import java .awt.event *;. import javax.swing.event *;. import javax.swing.border *;. import com.bruceeckel.swing *;. public class Progress extends JApplet {private JProgressBar pb = new JProgressBar (); private JSLIDER SB = New Jslider (Jslider.horizontal, 0, 100, 60); public void init () {Container CP = getContentPane (); cp.setLayout (New GridLayout (2, 1)); cp.add (PB); Sb.SetValue (0); sb.setPainTicks (True); sb.setmajortickspacing (20); sb.setminortickspacing (5); sb.setBorder (New Titly); Pb.SetModel (Sb.GetModel )))); // share model cp.add (sb);} public static void main (string [] args) {console.run (New Progress (), 300, 200);}} ///: ~ To take this Two things together, let them express the same data, the key is the following line: Pb.SetModel (sb.getmodel ()); Of course, you can also use Listener to control these two components, but for some simple questions The above practice is more straightforward.

JProgressBar is relatively simple, and Jslider's option is more, such as the direction, size scale, etc. of placed. Pay attention to the line of code of the Slider to take a head frame, more simple.

Tree JTree usage can be simply below the following line code:

Add (New Object [] {"this", "That", "Other"); which shows a most basic tree. JTree's API is very large, it should be one of the Swing Class libraries. Although you can use it to do anything, but if you want to complete the complicated task, you need a certain research and experiment.

Fortunately, this class is also provided, that is, a "default" tree component that meets general needs. So most cases you can use this component, only in special circumstances, you need to go deep into the tree.

Next examples we use the "default" tree to display a tree in the applet. When you press the button, the currently selected node will give birth to a new subtree (if no node is selected, then the new sub-tree will be added to the root node):

//: C14: Trees.java// Simple Swing Tree. Trees Can Be Vastly More Complex.// import javax.swing. *; import java.awt IMPORT JAVA.AWT.EVENT. *; Import Javax.swing.Tree. *; Import com.bruceeckel.swing. *; // Takes an array of strings and makes the first // Element a Node and the rest Leaves : class Branch {private DefaultMutableTreeNode r; public Branch (String [] data) {r = new DefaultMutableTreeNode (data [0]); for (int i = 1; i

Test.addActionListener (New ActionListener () {public void actionPerformed (i

Controls for JTree are implemented via its model. When MODEL changes, it produces an event that makes JTREE to make the necessary updates to the display of the tree. INIT () extracts this Model with getModel (). When you press the button, it creates a new new "BRANCH". After it finds the node currently selected (if nothing is not selected, use root node), model's InsertNodeInto () method takes over all tasks, including modifying the tree, refresh display, and more.

Perhaps the above routine can meet your needs. But the function of the tree is powerful until you think that it can do, you can replace all "default" in the above routines into your own class to achieve new features. But you have to know: Almost every class has a very large interface, so you have to spend a lot of time and energy to understand its internal structure. But the words, its design is still very excellent, and its competitors are often worse.

Like the table, Swing's table control is also very complex. When I started, they wanted to use JDBC (JDBC's "Grid" interface that is often used when connecting the database in Thinking In Enterprise Java), so it has extremely flexible, but the cost is complexity. . It allows you to easily create a full-featured spreadsheet program, but this will spend a whole book. But if you understand the basic principle, you can use it to create a relatively simple JTABLE. JTABLE is only responsible for displaying data, and the data itself is controlled by TableModel. So before you create JTABLE, you usually have to create a TableModel first. You can start to implement the TableModel interface from the beginning, but Java provides an AbstractTableModel helping class, inheriting it is relatively simple.

//: c14: jtableDemo.java// // import javax.swing. *; import java.awt. *; import java. awt.event *;. import javax.swing.table *;. import javax.swing.event *;. import com.bruceeckel.swing *;. public class JTableDemo extends JApplet {private JTextArea txt = new JTextArea (4, 20) ; // The TableModel Controls All The Data: Class DataModel Extends AbstractTableModel {Object [] Data = {{"One", "Two", "Three", "Four"}, {"FIVE", "Six", "Seven", "EIGHT"}, {"nine", "ten", "eleven", "twelve"},}; //prints Data When TableModellistener {public void TableChanged (TableModeEvent E) { TXT.SETTEXT (""); // Clear it for (INT i = 0; i

Cp.Add (new JScrollpane (Table)); cp.add (borderLayout.South, txt);} public static void main (String [] args) {console.run (New JtableDemo (), 350, 200);}} / //: ~ DataModel's data has an array, but you can also get data from it elsewhere, such as a database. The constructor adds a TableModellListener to DataModel, allowing it to print the array when the table changes. Other methods follow the BEAN's naming norm (use GET and SET, we will say later). These methods need to be used when JTABLE wants to display the data in DataModel. AbstractTableModel provides the default setValueat () and iScelleDitable () method, so you can no longer modify the data. If you want to modify the data, you must override these two methods. Waiting for TableModel, you can handle it to the JTable constructor. It automatically takes over the details of all display refreshes. We still as usual to embide the JTABLE to JScrollPane.

Choose Look & Feel so-called "Look & Feel" means that you can simulate the appearance of other operating environment. You can even do something more dazzling, such as dynamically change its appearance during program operation. However, in general, you will only choose one of the following: Select the "cross-platform" appearance (that is, Swing "Metal"), or select the appearance of the current operating system, let the Java program look like this The operating system is customized (most cases, this is almost no choice, so the user is not confused). No matter which one you do, the code is very simple, but you must first execute the code and create a component, because the component is created according to the current Look and Feel, and when the program is running to half, you will change your Look and Feel, it Will not follow you. (This process is very complicated, and it is not practical, so we leave it to swing monograph).

In fact, if you think the appearance of the cross-platform ("Metal") is a Swing program, and you want to use it, then you can not do anything - it is the default Look and Feel. But if you choose the current operating system's appearance style, then you can insert the following code. Generally, it is placed in main (), but the latest before adding the first component:

try {UIManager.setLookAndFeel (UIManager getSystemLookAndFeelClassName ().);} catch (Exception e) {throw new RuntimeException (e);} You do not have to do anything in the catch inside, because if you choose other look and feel fails, UIManager will Back to the default cross-platform Look and Feel. But this exception is still active when debugging, and at least you can see what it will be seen from catch.

Below is a program that uses the command line parameters to select the look and feel, and also see what these components look at different Look and Feels:

//: C14: LookandFeel.java// selecting diffreent looks & folds.import javax.swing. *; import java.awt. *; import java.awt.event. *; import java.util. *; import com.bruceeckel .swing. *; public class lookandfeel extends jframe {private string [] choices = {"Eny", "Meeny", "Minnie", "MICKEY", "MOE", "Larry", "Curly"}; private component [ ] Samples = {New JButton ("jbutton"), New Jtextfield ("JTextfield"), New Jlabel ("Jlabel"), New Jcheckbox ("JCheckbox"), New Jradiobutton ("Radio"), New JComboBox (Choices), NEW New jlist (choices),}; public lookandfeel () {super ("Look and Feel"); Container CP = getContentPane (); cp.setLayout (new flowLayout ()); for (int i = 0; i

}} Else usagerror (); // Note The Look & FEEL MUST Be set Before // Any Components Are Created. Console.run (New Lookandfeel (), 300, 200);}} ///: ~ You can clearly Use a string to specify the Look and Feel, just like MotiflookandFeel. But only it and "Metal" can be truly used on all platforms; although Java also provides strings for Windows and Macintosh's Look and Feel, these two appearance can only be used on their own platform (when you are here This Look and Feel can be obtained when calling getSystemLookAndfeelclassname on both platforms. If you make a Framework for companies with special requirements for the procedure, you can even create a look and feel. However, this can be a big project, which is difficult to exceed the scope of this book (in fact it even exceeds many Swing exclusive range!).

The interaction between the clipboard JFC and the system clipboard is very limited (in java.awt.datatransfer package). You can copy the String object as a text into the clipboard, or you can paste the text in the clipboard into the String object. Of course, the clipboard supports any type of data, as for the data in the clipboard, it is a program that pastes the data. Java enhances the scales of the clipboard API through "Flavor" concept. When the data is added to the clipboard, the Flavor that is associated with this data can be converted to this data (more than one picture can be represented as a string or an image that all have a digital composition, so you will Can know if the data in the clipboard supports the Flavor you are interested in.

Let's take an example of cutting, copying, and paste String in Jtextarea. You will find the cut, copy, and paste the shortcuts that we can use. However, if you tried JtextField and Jtextarea in other programs, you will find that they have already supported clipboard. We just wrote the code here. If you want to post the text in the clipboard to components other than JtextComponet, you can borrow the skills.

//: c14: cutandpaste.java// using the clipboard.import javax.swing. *; import java.awt. *; import java.awt.event. *; import java.awt.datatransfer. *; import com.bruceeckel .swing *;. public class CutAndPaste extends JFrame {private JMenuBar mb = new JMenuBar (); private JMenu edit = new JMenu ( "Edit"); private JMenuItem cut = new JMenuItem ( "Cut"), copy = new JMenuItem ( " Copy "), paste = new JMenuItem (" Paste "); private JTextArea text = new JTextArea (20, 20); private Clipboard clipbd = getToolkit () getSystemClipboard ();. public CutAndPaste () {cut.addActionListener (new CutL ( )); Copy.addactionListener (new copyl ()); Edit.Add (CUT); edit.add (copy); edd (paSte); Mb.Add (Edit) ; setJMenuBar (mb);. getContentPane () add (text);} class CopyL implements ActionListener {public void actionPerformed (ActionEvent e) {String selection = text.getSelectedText (); if (selection == null) return; StringSelection clipString = new StringSelection (selection); clipbd.setContents (clipString, clipString);}} class CutL implements ActionListener {public void actionPerformed (ActionEvent e) {String selection = text.getSelectedText (); if (selection == null) return; StringSelection clipString = new StringSelection (selection); clipbd.setContents (clipString, clipString); text.replaceRange ( "", text.getSelectionStart (), text.getSelectionEnd ());}} class PasteL implements ActionListener {public void actionPerformed (ActionEvent e) {Transferable Clipdata =

clipbd.getContents (CutAndPaste.this); try {. String clipString = (String) clipData getTransferData (DataFlavor.stringFlavor); text.replaceRange (clipString, text.getSelectionStart (), text.getSelectionEnd ());} catch (Exception ex ) {System.err.println ("not string flavor");}}} public static void main (string [] args) {console.run (new cutandpaste (), 300, 200);}} ///: ~ Now create menus and jtextarea should be very easy. Different, here we create a ClipBoard type CLIPBD field with Toolkit. All important things are placed inside Listener. In addition to the last line, CUTL and COPYL are identical. There are two lines here, which is to create StringSerection with String, and call the two lines of setContents () with StringSerection. Just these, String has been put in the clipboard.

Pastel uses getContents () to take the data from the clipboard. It returns a relatively unfamiliar Transferable object, in fact, you don't know what it is. There is a way to know what is there, just use the getTransferDataFlavors () method. It will return a DataFlavor array, and these Flavors will tell you which of this object does. You can also pass a Flavor you interested to ask IsDataFlavorsupported () asked it. However, here we have used a very bold solution: assume this object to support String Flavor, directly call GetTransferData (), if it is wrong, abnormally handling self-service.

You can expect that future Java will provide more Flavor. You can get more data Flavor support.

One of the main purposes of making applets into JAR volume JAR is to optimize the loading of the applet. In the Java 1.0 era, the programmers try to put the applet's code into a class so that when the user downloads Applet, just send a request to the server once. But don't just make the code very hard to read (also difficult to maintain), and .class files are not compressed, so the download speed still has improved potential.

JAR solves this problem, which compresses all the .class files in a file for the browser download. Now you can use the correct design and don't worry about it. Class file, and the user's download speed is faster.

Tell Tictactoe.java. It looks only one class, but in fact, it contains five internal classes, so there are six categories. Once the compilation is successful, you can use the following command to compress it into a JAR file:

JAR CF Tictactoe.jar * .class This assumes that all .class files in the current directory are compiled by Tictactoe.java (otherwise there will be more things in the volume).

Next you have to create an HTML page, here you want to mark the JAR file with the Archive tag. Here is the most basic applet mark:

Tictactoe Example Applet </ Title> </ head> <body> <applet code = Tictactoe.class archive = Tictactoe.jar width = 200 height = 100> </ applet> </ body> you are best Still running this file using the HTMLConverter program comes with JDK. Tag applets due to the limitations of the sandbox security model, unsigned Applets cannot be operated in the client, such as writing files, connecting to the local network. [83] Once you have issued Applets, users can check that people who claim to creating this applet are the founder, and they can also confirm that the JAR file is tampered with after leaving the server. Without these minimum guarantees, applet is not possible to do anything that may damage your computer or leak personal privacy. This restriction is critical to the safe use of Applets on the Internet, but it also weakens the ability of the applet.</p> <p>Since I have Java Plugin, the steps to issue Applet have become easier and more standardized, and Applet also has a simpler way of deploying applications. The applet has become very simple, and there is also a standard Java tool.</p> <p>When Plugin hasn't come yet, you have to sign the .jar file with the netscape user using Netscape users, use Microsoft's tool to sign the .cab file for Internet Explorer users, and then prepare a set of tags in the HTML file. . The user must also install the certificate in the browser so applet can get trust.</p> <p>Plugin not only provides a standardized way of signing and deploying Applet, but also automatically installs the certificate, which is convenient for users.</p> <p>Imagine such an applet, it is accessible to the client's file system and reads and writes several files. This is very similar to Filechoosertest.java, just this is an applet, so if you want to open the JFilechooser dialog, it must be a signature JAR file. Otherwise showopndialog () will throw a securityException.</p> <p>//: c14: signedapplet: FileAccessApplet.java// Demonstration of File dialog boxes.package c14.signedapplet; import javax.swing *; import java.awt *; import java.awt.event *; import java.io... . *; import com.bruceeckel.swing *;. public class FileAccessApplet extends JApplet {private JTextField filename = new JTextField (), dir = new JTextField (); private JButton open = new JButton ( "Open"), save = new JButton ("Save"); private JeditorPane EP = New JeditorPane (); private jscrollpane jsp = new jscrollpane (); private file file; public void infit () {jPanel P = new jPanel (); open.addActionListener (new OpenL () ); P.Add (open); new savel ()); p.Add (Save); Container CP = getContentPane (); jsp.getViewPort (). Add (ep); cp.add (JSP, BorderLayout.center; cp.add (p, borderlayout.south); Dir.setedItTable (false); EP.SetContentType ("text / html"); filename.setedItTable (false); p = New jPanel (); p.setlayout (New Gridlayo UT (2, 1)); P.Add (filename); P.Add (Dir); cp.add (p, borderlayout.north);} Class Openl Implements ActionListener {Public Void ActionPerformed (ActionEvent E) {JFilechooser C = new JFileChooser (); c.setFileFilter (new TextFileFilter ()); // Demonstrate "Open" dialog: int rVal = c.showOpenDialog (FileAccessApplet.this); if (rVal == JFileChooser.APPROVE_OPTION) {file = c.getSelectedFile (); Filename.settext (file.getname ()); dir.setText (C.GetcurrentDirectory (). TOSTRING ()); try {system.out.println ("URL IS" file.tourl ()); EP .SETPAGE (File.tourl ());</p> <p>// ep.repaint ();} catch (ioexception ie) {throw new runtimeException (}}} if (rval == jfilechooser.cancel_option) {filename.settext ("You Pressed Cancel"); Dir.Settext (" ");} else {save.setEnabled (true);}}} class SaveL implements ActionListener {public void actionPerformed (ActionEvent e) {JFileChooser c = new JFileChooser (file); c.setSelectedFile (file); // Demonstrate" Save "dialog: int rVal = c.showSaveDialog (FileAccessApplet.this); if (rVal == JFileChooser.APPROVE_OPTION) {filename.setText (c.getSelectedFile () getName ().); dir.setText (c.getCurrentDirectory (). TOSTRING ()); trywriter fw = new filewriter; ep.write (fw);} catch (ioexception ie) {throw new runtimeException (}}}} (rval == jfilechooser.cancel_option) {filename .SETTEXT ("You Pressed Cancel"); Dir.Settext (""); .}}} Public class TextFileFilter extends javax.swing.filechooser.FileFilter {public boolean accept (File f) {return f.getName () endsWith ( "txt.") || f.isDirectory ();} public String getDescription ( ) {RETURN "text files";}}} public static void main (String [] args) {console.run (new fileaccessapplet (), 500, 500);}} ///: ~ This seems to be A very ordinary applet. But although it can run on the client, it is not possible to turn the file. To sign him, you must first make it a JAR file (see the JAR Tools in this chapter), then sign this file.</p> <p>With a jar file, you have to sign your certificate or key. If it is a big company, then you can apply for the "Signing Authority" of VeriSign or Thawte, which will send you a certificate. The certificate is used to sign the code, so that the user can be sure that you are really the provider of this code he downloaded, and after you issued, this code is not tampered with. The essence of electronic signatures is a string of two-way number. When someone wants to check the signature, the certification center that gives you a certificate will testify for you. The certificate issued by the Certification Center is to pay, and it will be updated regularly. For this question, we can sign yourself for yourself. This certificate will exist in files (often referred to as Keychain). You can use the following command:</p> <p>KeyTool -List access the default file. If the default file does not exist, then you have to build one first, or tell it which file it goes. Maybe you should try the "cacerts" file.</p> <p>KeyTool -List -File <path / filename> Its default path is usually</p> <p>{java.home} / lib / security / cacerts where java.home represents the directory where JRE is located.</p> <p>You can also send yourself a certificate with KeyTool for testing. If there is already a Java's "bin" directory in the PATH environment variable, then this command is:</p> <p>KeyTool -Genkey -Alaias <keyname> -keystore <url> where Keyname represents Key alias, such as "mykeyname", the URL indicates the location of the storage key, usually placed in the cacerts file above.</p> <p>It will prompt you to enter (KeyStore) password. The default is "changeit" (reminds you what to do). Then name, department, unit, city, state, and country. This information will be placed in the certificate. Finally it will give you a password to the certificate. If you really care about security, you can give it a separate password. By default, the password of the certificate is the password of the "KeyStore", which is already enough. The above information can also be used with a compilation tool like Ant using the command line.</p> <p>If you don't give parameters, use the keytool command directly to the command line, then print all the options all. You may want to use the -valid option to see how long the certificate is valid.</p> <p>If you want to confirm that the certificate is saved in the cacerts file, use</p> <p>KeyTool -List -KeyStore <URL> and enter the password set in front. Perhaps your certificate and others are stored together (if others have already laid a certificate in this KeyStore).</p> <p>The certificate you just got is issued by yourself, so the certification center will not pay off. If you use this certificate to sign a JAR file, you will see a warning window there, and it is highly recommended that they don't use this program. Unless you go to buy a cost-effective certificate, you will have to bear with your users.</p> <p>Tag JAR file To use Java's Jarsigner standard tool, the command is as follows:</p> <p>Jarsigner -keystore <URL> <jarfile> <keyname> URL represents the location of the cacerts file, JARFILE represents the name of the JAR file, and Keyname is the alias of the certificate. You have to lose a password again.</p> <p>Now this JAR file brings the signature of your certificate, and the user can know that it is not tampered with it after issuance (including modification, addition or deletion, etc.).</p> <p>Next, you have to worry about the "Archive" property of the applet tag of the HTML file, JAR's file name is here. If the browser uses Java's Plugin, the applet's tag is more complicated, but you can create a simple point, just like this:</p> <p><Applet code = package.appletsubclass.class archive = myjar.jar width = 300 height = 200> </ applet> then use HTMLCONVERTER over again (already included in the JDK package, you can download online), it will help You generate the correct applet tag.</p> <p>Now when the user downloads Applet, the browser will remind them that it is now loaded is a signature applet, and ask him to trust this issuer. As we mentioned earlier, the certificate used does not have high credibility, so it will give a warning. If the customer trusted, Applet can access the entire customer system, so it is nothingord of ordinary programs.</p> <p>The source code of this book already contains a full-compiled profile and Ant script, you can download it on www.bruceeckel.com.</p> <p>Although JNLP and Java Web Start is strongly signed, it can even be effectively replaced, but it is still running on a web browser. This not only enables the client to increase the overhead of the browser, but often make the user interface very monotonous and confusing. The browser has its own menus and toolbars, and they are pressing the top of the applet.</p> <p>Java Network Launch Protocol (JNLP) can solve this problem without sacrificing Applet. You can download and install separate JNLP applications on the client. It can be launched with the command line, desktop icon, or application manager distributed with JNLP. The program can even start from the site that was originally downloaded.</p> <p>When the JNLP program runs, it will download the resource from the Internet and automatically check the version (if the user connects to the Internet). That is to say, it also has the advantage of applet and Application.</p> <p>Like Applet, the client must pay attention to security issues when treating JNLP applications. JNLP app is an easy-to-download, web-based application, so it may be maliciously utilized. In view of this, JNLP applications should be placed in the sandbox as applet. Like Applet, it can be deployed with a signature JAR file. At this time, the user can choose whether it is trust the issuer. The difference between Applet is, even if there is no signature, it can still access certain resources of the client system through the JNLP API (this requires the user to recognize these requests when the program is running).</p> <p>JNLP is an agreement rather than the product, so it can be implemented first. Java Web Start is known as Jaws is SUN, which can be downloaded for free, JNLP's official model implementation. You only need to download and install, if you want to do it, don't forget to put the JAR file in the classpath. To deploy JNLP applications on the site, make sure that the server can recognize the MIME type of Application / X-Java-JnLP-File. If you use the latest version of the Tomcat server (http://jakarta.apache.org/tomcat), it should have been configured with you. Otherwise to check the user manual of the server.</p> <p>It is not difficult to create JNLP applications. Create a standard application first, then pack it with JAR, and finally prepare a boot file. The startup file is a very simple XML file, which is responsible for delivering information about downloading and installing the app to the client. If you decide to deploy software with a JAR file without signature, you have to use JNLP API to access resources on the client system. Below is a variant of the Jfilechooser dialog program, but this time we use JNLP services to open it so you can put the program into a JAR package without signature, then use JNLP to deploy.</p> <p>//: C14: JNLP: JNLPFILECHOOOSER.JAVA / / OPENING FILES ON A local Machine with jnlp.// {Depends: javaws.jar} package c14.jnlp; import javax.swing. *; import java.awt. *; import java.awt. *; import java.aw java.awt.event *;. import java.io *;. import javax.jnlp *;. public class JnlpFileChooser extends JFrame {private JTextField filename = new JTextField (); private JButton open = new JButton ( "Open"), save = new JButton ( "Save"); private JEditorPane ep = new JEditorPane (); private JScrollPane jsp = new JScrollPane (); private fileContents fileContents; public JnlpFileChooser () {JPanel p = new JPanel (); open.addActionListener (new OpenL ()); P.Add (open); new savel ()); p.Add (Save); Container CP = getContentPane (); jsp.getViewPort (). Add (EP); cp.add JSP, BorderLayout.center; cp.add (p, borderLayout.South); filename.seteditable (false); p = new jPanel (); p.setlayout (new gridLayout (2, 1)); p.Add (filename ); Cp.add (p, borderlayout.north); ep.setContentType ("text"); save.setEnabled (false);} class OpenL implements ActionListener {public void actionPerformed (ActionEvent e) {FileOpenService fs = null; try {fs = (FileOpenService) ServiceManager.lookup ( "javax.jnlp.FileOpenService");} catch (UnavailableServiceException Use) {throw new runtimeException (use);} if (fs! = null) {Try {filecontents = fs.openfiledialog (".", new string [] {"txt", "*"}); if (filecontents = = null; filename.settext (filecontents.getname ()); ep.read (filecontents.getinputstream (), null;</p> <p>} Catch (Exception exc) {throw new RuntimeException (exc);} save.setEnabled (true);}}} class SaveL implements ActionListener {public void actionPerformed (ActionEvent e) {FileSaveService fs = null; try {fs = (FileSaveService) ServiceManager.lookup ( "javax.jnlp.FileSaveService");} catch (UnavailableServiceException use) {throw new RuntimeException (use); "."} if (! fs = null) {try {fileContents = fs.saveFileDialog (, new String [] {"txt"}, new byterrayinputstream (EP.GETTEXT (). getBytes ()), filecontents.getname ()); if (filecontents == null) return; filename. settext (filecontents.getname ());} Catch (Exception Exc) {throw new runtimeException (exc);}}}} public static void main (string [] args) {jnlpfilechooser fc = new jnlpfilechooser (); fc.setsize (400, 300); fc.setVisib Le (TRUE);}} ///: ~ Note, FileOpenService and FileCloseService are classes in javax.jnlp, which does not mention the JFilechooser dialog in the end of the head until the end. To use these two services, not only use serviceManager.lookup () to request requests, but also to access client resources with objects returned by this method. Here we use JNLP's FileContent interface to read and write the client's file system. Any attempts to access these resources directly, thanks to create a File or FileReader object, will cause the program to throw a securityException, and the result is like in the unqualified Applet. If you don't want to be bound by JNLP, use these classes directly, you must use the signature JAR file (see the previous section, sign the JAR file). Now we have already made a JNLP program, the next task is to put the class in the jar file, and then write a startup file. Below the startup file of the above program:</p> <p><? XML Version = "1.0" encoding = "UTF-8"?> <jnlp spec = "1.0 " codebase = "file: // c: / tij3code / c14 / jnlp" href = "filechooser.jnlp"> < information> <title> FileChooser demo application </ title> <vendor> Mindview Inc. </ vendor> <description> Jnlp File choose Application </ description> <description kind = "short"> A demonstration of opening, reading and writing a Text File </ description> <icon href = "images / tijicon.gif" /> <offline-allowed /> <iNformation> <resourceES> <j2se version = "1.3 " /> <jar href = "jnlpfilechooser.jar "Download =" Eager "/> </ resources> <Application-Desc main-class =" c14.jnlp.jnlpfilechooser "/> </ jnlp> The suffix name of this startup file must be .jnlp, here is Filechooser.jnlp, In addition, it must stay with JAR files in a directory. As you can see, this is an XML file with a root node is <jnlp> tag. The node also includes some child elements, most of which are self-explanatory.</p> <p>The SPEC attribute of the JNLP element tells the client system, which version of JNLP is required. The CodeBase property tells the client which directory to find the startup file and resources. Usually it should be a HTTP URL pointing to the web server, but here, we refer to this machine's directory. The HREF property represents the name of the file.</p> <p>There are multiple sub-elements that provide information-related information in the Information tag. They are used by the management console for Java Web Start or other similar programs. These procedures install the JNLP app to the client, let the user launched by the command line, shortcut or other method.</p> <p>The resource tag is similar to the Applet tag in the HTML file. J2SE child elements indicate the J2SE version of the program run, and JAR child elements tell the client Class file which jar file is hit. In addition, the JAR element has a DOWNLOAD attribute whose value can be "eager" or "lazy", which is to tell JNLP whether it should be downloaded this JAR and start running the program.</p> <p>The Application-DESC property tells the client system, which is the executable class, which is where the port of the JAR file is.</p> <p>The JNLP tag also has a very useful child element, that is, the security tag that is not used here. Let's take a look at what the security tag is:</p> <p><Security> <all-permissions /> <security /> can only use the Security tag when deploying the signature JAR file. The above program does not need this tag, as all local resources are accessed through JNLP services. There are also some other tags, specific details can be referred to http://java.sun.com/products/javawebstart/download-spec.htm</p> <p>Now .jnlp file is also written, the next is to add super link in the web page. This page should be a download page. In addition to complex formats and details, on the page, don't forget to add this:</p> <p><a href="filechooser.jnlp"> Click Here </aine you can click on the link to start the JNLP application's installation process. As long as you download once, you can configure it through the management console. If you use Windows's Java Web Start, then the second startup program, it will prompt you, is it a shortcut to create a shortcut. This thing is configurable.</p> <p>The source code of this book contains a complete configuration file and Ant's compilation script, you can download it on www.bruceeckel.com, then use them to compile and create programs.</p> <p>We only introduced two JNLP services here, and seven in the current version. They are all designed for specific tasks, such as printing, clipboard operation, and more. In-depth discussion of these services exceeds the scope of this chapter.</p> <p>Programming Skills Since Java's GUI programming is a very significant difference between Java 1.0 / 1.1 and Java 2's Swing class, you may find it, from Swing's point of view, Some old program habits will be exposed inside the routine. In addition, Swing allows you to program with a better way compared to the old model. Here, we will introduce some of these questions and test these programming skills.</p> <p>The advantage of dynamically binding event Swing is the flexibility. You can call methods to add or delete events to components. Let's take an example:</p> <p>//: c14: DynamicEvents.java// You can change event behavior dynamically.// Also shows multiple actions for an event.// <applet code = DynamicEvents // width = 250 height = 400> </ applet> import javax. IMPORT JAVA.AWT. *; Import Java.awt.Event. *; Import Java.util. *; Import com.bruceeckel.swing. *; public class dynamicEvents extends japplet {private java.util.list list = new ArrayList (); private int i = 0; private JButton b1 = new JButton ( "Button1"), b2 = new JButton ( "Button2"); private JTextArea txt = new JTextArea (); class B implements ActionListener {public void actionPerformed (ActionEvent e) {txt.append ( "A button was pressed / n");}} class CountListener implements ActionListener {private int index; public CountListener (int i) {index = i;} public void actionPerformed (ActionEvent e) { TXT.APpend ("Counted Listener" index "/ n");}}}} Class B1 Implements ActionListener {Public Void ActionPerformed (ActionEvent E) {TXT.APpend ("Button 1 P RESTLISTENER A = New CountListener (i ); list.add (a); b2.addactionListener (a);}} Class B2 Implements ActionListener {Public Void ActionPerformed (ActionEvent E) {txt.Append ("Button2 PRESSED / N "); int end = list.size () - 1; if (end> = 0) {b2.RemoveActionListener (ActionListener) List.get (end)); list); list);}}} Public void init () {Container CP = getContentPane (); b1.addActionListener (new b ()); b1.addActionListener (new b1 ()); b2.addactionListener (new b ()); b2.addactionListener (New B2) ));</p> <p>JPANel P = new jPanel (); p.Add (b1); p.Add (b2); cp.add (borderLayout.North, P); cp.add (new jscrollpane (txt));} public static void main String [] args) {console.run (New DynamicEvents (), 250, 400);}} ///: ~ New things in this program are: Button has more than one listener. Typical components are handled by multicast modes, that is, you can register multiple Listener for an event. But for some special, unicast mode processing, this will trigger toOManyListenerSexception. When the program is running, you can dynamically add or delete the listener to the BUTTON B2. You should already know how to add Listener, and each component has a REMOVEXXXLISTENER () method that can be used to delete Listener. This flexibility brings you more convenience</p> <p>It is worth noting that the order of adding Listener is not necessarily the order in which they are called (although most JVM is indeed so real).</p> <p>Separation of business logic and user interface, always emphasize a class "only one thing" when designing the class. This is especially the case involving the user interface, because you are likely to make "what to do" is mixed together. This coupling severely hinders the reuse of the code. A preferred approach is to separate the "business login" with the GUI. This not only makes it easy for business logic code, but also simplifies the reuse of GUI.</p> <p>There is also a situation, which is a multi-layer system, that is, "Business Object" is completely stored on another machine. Centralized management of business rules can make rules' updates to take effect on new transactions, so this is the goal pursued in such systems. But many applications use these business objects, so they must never connect with a specific display mode. They should only do business processing, no matter what else. [84]</p> <p>Let's take an example to see if business logic is separated from GUI:</p> <p>//: C14: Separation.java// separating gui logic and business objects.// <applet code = separation width = 250 height = 150> </ applet> import javax.swing. *; import java.awt. *; import javax.swing.event *;. import java.awt.event *;. import java.applet *;. import com.bruceeckel.swing *;. class BusinessLogic {private int modifier; public BusinessLogic (int mod) {modifier = mod ;} public void setModifier (int mod) {modifier = mod;} public int getModifier () {return modifier;} // Some business operations: public int calculation1 (int arg) {return arg * modifier;} public int calculation2 (int arg) {return arg modifier;}} public class Separation extends JApplet {private JTextField t = new JTextField (15), mod = new JTextField (15); private JButton calc1 = new JButton ( "Calculation 1"), calc2 = new JButton ("Calculation 2"); Private BusinessLogic BL = New BusinessLogic (2); Public Static Int GetValue (JtextField TF) {Try {Return Integer.Parseint (tf.getText ());} catch (NumberFormate) xception e) {return 0;}} class Calc1L implements ActionListener {public void actionPerformed (ActionEvent e) {t.setText (Integer.toString (bl.calculation1 (getValue (t))));}} class Calc2L implements ActionListener {public Void ActionPerformed (Integer.tostring (BL.Calculation (BL.Calculation (GetValue (t))))))))))));}} // if you want something to happen wherever // a JtextField Changes, add this listener: Class Modl Implements DocumentListener {Public Void ChangedUpdate (DocumentEvent E) {} public void insertupdate (Document E) {Bl.SetModifier (GetValue (MOD));</p> <p>} Public void removeUpdate (DocumentEvent E) {bl.SetModifier (GetValue (MOD));}} public void init () {Container CP = getContentPane (); cp.setLayout (new flowLayout ()); cp.add (t) Calc1.addActionListener (New Calc1L ()); Calc2.addActionListener (new calc2l ()); jPanel p1 = new jPanel (); p1.Add (CALC1); p1.Add (CALC2); cp.add (p1); MOD.GETDocument (). AdddocumentListener (New MODL ()); JPanel P2 = new jPanel (); p2.add (New Jlabel ("Modifier:"); p2.add (mod); cp.add (p2); } Public static void main (string [] args) {console.run (New Separative (), 250, 100);}} ///: ~ You will find businessLogic is a quite simple class, see it like you I can't think of it will be used in the GUI. It only did its own business. Separation is responsible for the details of all user interfaces, which communicate through BusinessLogic PUBLIC interface. All operations send and receive messages around the user interface and the BusinessLogic object. Next, I will do it myself. Since Separation only knows that it is talking to the businesslogic object (that is, the two is not highly related), you don't have to draw a lot of efforts to talk to other objects.</p> <p>Establishing the view of the UI to the business logic, when you touch the old code left with Java to maintain the old code left, you can easily make a little relaxed.</p> <p>Parallel internal classes, SWING event models, can continue to use the AWT event model, and those who want us to use new class libraries for the old way, all of which make program design more confusing. Now even the way you write the seven-eight-piece code has also become a five-flowers.</p> <p>These situations are truth, but you should always use the simplest and most organized solution: the event is handled with Listener. This is also the plan for the vast majority of this chapter.</p> <p>With this model, you can write a lot less "Let me think about who is" who is emitted ". All code is solving the problem, not the type check. This is the best programming style, which is written not only for summary, readability and maintainability.</p> <p>When you write a Swing program with Swing, you are likely to forget that it is still using threads. Although you didn't make a clear creation of Thread objects, the problem it triggered would take you not to hop. In most cases, the GUI programs you write from the Swing or other window display are event-driven, unless the user clicks on the GUI component with a mouse or keyboard, or nothing will happen.</p> <p>Just remember that Swing has an event dispatching thread, it will run, and handle Swing events in order. If you want to make sure that the program doesn't have a deadlock or competition, then it is necessary to consider this problem.</p> <p>In this section we will explore questions that swings programming should be paid attention to in several multithreaded environments.</p> <p>Reissue Runnable in Chapter 13, I suggest that you must be cautious when implementing Runnable interface. Of course, if your design must inherit another class and this class has a thread behavior, then select Runnable or right. Let's take an example of this. This program creates a Runnable JPanel class that will determine what color of the draw. It acquires parameters from the command line to determine the size of the grid and the length of SLEEP (). By adjusting these values, you will find that the thread has some interesting, but it cannot be explained.</p> <p>//: C14: ColorBoxes.java// Using the runnable interface.// <applet code = colorboxes width = 500 height = 400> // <param name = Grid value = "12"> // <param name = pause value = "50"> </ applet> import javax.swing. *; Import java.awt. *; Import java.awt.event. *; Import java.util. *; Import com.bruceeckel.swing. *; Class CBOX extends JPanel implements Runnable {private Thread t; private int pause; private static final Color [] colors = {Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.LIGHT_GRAY, Color.Magenta, Color.range, Color.Pink, Color.Red, Color.White, Color.Yellow}; private static random rand = new random (); private static final color newcolor () {return colors [rand.nextint Colors.Length)];} private color ccolor = newcolor (); public void PaintComponent (GRAPER.PAINTComponent (g); g.setColor (ccolor); Dimension s = getSize (); g.FillRect (0, 0, S.Width, S.Height); PUBLIC CBOX (INT PAUSE) {this.pause = pause; t = New Thread (this); T.Start ();} public void run () {while {ccolor = newcolor (); repaint (); try {t.sleep (pause);} catch (interruptedException e) { throw new RuntimeException (e);}}}} public class ColorBoxes extends JApplet {private boolean isApplet = true; private int grid = 12; private int pause = 50; public void init () {// Get parameters from Web page: if (isapplet) {String gsize = getParameter ("grid"); if (gsize! = null) Grid = integer.parseint (gsize); string pse = getParameter ("pause"); if (PSE! =</p> <p>NULL) PAUSE = INTEGER.PARSEINT (PSE);} Container CP = getContentPane (); cp.setLayout (New GridLayout (Grid, Grid)); for (int i = 0; i <grid * grid; i ) cp.add (New CBOX (PAUSE)); public static void main (string [] args) {colorBoxes applet = new colorboxes (); applet.isapplet = false; if (args.length> 0) applet.grid = INTEGER.PARSEINT Args [0]); IF (args.length> 1) applet.pause = integer.parseint (args [1]); console.run (applet, 500, 400);}} ///: ~ ColorBoxes is a very Ordinary, use init () to create a GUI's Applet / Application. It has a GridLayout, so it divides the entire plane into a small GRID. Then it put some CBOX object in the lattice, then give each object a PAUSE value. The default value of Pause and Grid is determined in main (), and it also tells you how to modify these two defaults with the parameters of the command line or applet. CBOX is the focus of the entire program. It inherits from JPANEL and implements Runnable interfaces, so these JPANELs are also Thread. Remember, when you implement runnable, there is no THREAD object, which is just some objects with a Run () method. Therefore, you must explicitly create Thread objects, which is to pass this runnable to the constructor of Thread, and then call start () in the constructor). For CBOX, this thread is T.</p> <p>Take a look at the Colors array, this is an enumeration that contains the color defined by all the Color classes. NewColor () method will randomly select a color from it. CColor represents the current color.</p> <p>PainTComponent () is very simple; it first sets the color into ccolor, then fill the entire JPanel with this color.</p> <p>There is an infinite loop in Run (), which first sets CColor to a new random color, and then display it with repaint (), and then according to the parameter SLEEP () of the command line.</p> <p>Just because this design is flexible, and the thread is tied to each JPanel, so you can create any number of threads to do experiments. (The number of threads that actually manage efficiently managed is limited.)</p> <p>This procedure is also a very interesting benchmark, because it demonstrates different JVMs, there is a huge performance and behavioral difference in how to implement threads.</p> <p>Manage and send the properties you use the main method or another thread to modify the properties of the Swing component, you must remember that there is a possible event dispatching thread that is in the same resource with you [85]</p> <p>Below this program demonstrates the unexpected results caused by ignoring the event:</p> <p>//: c14: EventThreadFrame.java// Race Conditions using Swing Components.import javax.swing *; import java.awt *; import java.awt.event *; import com.bruceeckel.swing.Console; public class... EventThreadFrame extends JFrame {private JTextField statusField = new JTextField ( "Initial Value"); public EventThreadFrame () {Container cp = getContentPane (); cp.add (statusField, BorderLayout.NORTH); addWindowListener (new WindowAdapter () {public void windowOpened (WindowEvent e) {try {// Simulate initialization overhead Thread.sleep (2000);} catch (InterruptedException ex) {throw new RuntimeException (ex);} statusField.setText ( "Initialization complete");}});} public Static void main (string [] args) {eventthreadframe etf = new eventthreadframe (); console.run (ETF, 150, 60); etf.statusfield.settext ("Application Ready); System.out.Println (" DONE " );}} ///: ~ To determine how the program is very easy to do. The MAIN method first creates an eventthreadframe object and then calls the console.run () method. After creating and running this frame, it sets the value of Frame to "Application Ready" and exits main () and prints "DONE" on the console. When creating Frame, the constructor sets the value of the TEXT Field to "Initial Value" and add a listener specifically to listen to the window to be opened. When (console.run () method) calls setvisible (TRUE), JFrame has received this event, so this event is also a good place to do with the display window. Here, we use SLEEP () to simulate some initialization code, because initialization may spend a few seconds. After these, the value of the text box should be set to "Initialization Complete".</p> <p>Your original expected order should be, first display "Initial Value" on the text box, then "Initialization Complete", then "Application Ready", and finally print "DONE" on the console. However, the actual process is, but there is no EventThreadFrame to finish the event, main () first calls the jtextfield's setText (). In other words, "Application Ready" is likely to have already shown before "Initialization Complete". This is not necessarily the order of actual operation, it also depends on your system's speed. Swing event dispatching thread may be busy with the WindowOpended event, so you can't see the value of the text box before the event is processed, and you have seen it, it has become "Initializaiton Complete". Because this is the last set value set by the text box, "Application Ready" is lost. Worse, "DONE" has been sent to the console before this. This unexpected and unpredictability comes from such a simple fact, there are two threads that need synchronization. It seems that when the thread encounters Swing, the trouble is also coming. To solve this problem, you must ensure that the properties of the Swing component can only be modified by the event assignment thread.</p> <p>This is more prone to it. Swing provides two ways, swingutilities.invokelater () and swingutilities.invokeAndwait (), you can choose one. They are responsible for most of the work, that is, you don't have to worry about those very complex threads.</p> <p>Both methods require Runnable objects as parameters. When Swing event handles all the hoping events in the thread, it will start its Run () method.</p> <p>//: c14: InvokeLaterFrame.java// Eliminating race Conditions using Swing Components.import javax.swing *; import java.awt *; import java.awt.event *; import com.bruceeckel.swing.Console; public... class InvokeLaterFrame extends JFrame {private JTextField statusField = new JTextField ( "Initial Value"); public InvokeLaterFrame () {Container cp = getContentPane (); cp.add (statusField, BorderLayout.NORTH); addWindowListener (new WindowAdapter () {public void windowOpened (WindowEvent e) {try {// Simulate initialization overhead Thread.sleep (2000);} catch (InterruptedException ex) {throw new RuntimeException (ex);} statusField.setText ( "Initialization complete");}});} public static void main (String [] args) {final InvokeLaterFrame ilf = new InvokeLaterFrame (); Console.run (ilf, 150, 60); // Use invokeAndWait () to synchronize output to prompt: // SwingUtilities.invokeAndWait (new Runnable () {swingutilities.i NVokelater (new runnable () {iv.statusfield.setText ("Application Ready);}}); System.out.Println (" DONE ");}} ///: ~ main () The anonymous internal class of Runnable was passed to swingutilities.invokelater (), and this internal class called the TEXT Field's setText () method. Such RunNable objects are in the queue as an event, and after the event is assigned, it can call its setText () method. That is, it will process the WindowOpening event first, and then display "Application Ready" in the text box, which is what we want. Invokelater ()</p> <p>It is asynchronous, so it can be quickly returned quickly. This method is very useful because it will not block, so the program can run very smooth. But it still can't solve the problem that "DONE" will be printed without doing anything.</p> <p>To solve this problem, you can change the invokelater () to invokeAit (), let it set the value of the text box as "Application Ready". This method is synchronized, that is, it will always be in a blocking state before the event is processed and returned. Such System.out.Println ("DONE") statements are running again after the value of the text box is set. This way we have gained a fully predictive correct behavior. InvokeAndWait () provides the necessary conditions for deadlocks. So if you want to use InvokeAndWait (), especially if you call with another thread, you must carefully control the shared resources.</p> <p>Perhaps you have more opportunities to use Invokelater, but keep in mind that you can only use these two ways to set the properties of the Swing component after initialization.</p> <p>Visual programming and JavaBeans see now you already know that Java's value in code multiplexing. The code with the highest degree is class because it is composed of a set of closely related features (field field) and behavior (methods), which can be multiplexed in synthesis and inheritance.</p> <p>Inheritance and polymorphism is the foundation for object-oriented programming, but when building applications, in most cases, you really need to help you complete a specific task. You want to use these components inside, just like electronic engineers insert the chip to the board. Similarly, there should be some programming methods that can accelerate this "modular installation".</p> <p>Microsoft's Visual Basic has won the initial success - Visual Programming, which is very huge, followed by the second generation of Borland Delphi (directly inspired JavaBean design). With these tools, the components have become seen, and the components usually represent a visual component such as a button, a text box, so that the component programming has also become meaningful. In fact, the appearance of the component is usually designed to operate. That is, so dragging and dropping the components from the Control Box (Palette) to the form. And when you do this, the application constructor is helping you write code, so when the program runs, it will create those components.</p> <p>Usually, it is not enough to drag the component to the form is not enough to create a program. You have to modify some features, such as its color, above text, connected database, and more. These features that can be modified in design are called properties. You can control the properties of components in the application's build tool. When the program is created, these configuration information are also saved so that these configuration information can be activated when the program is running.</p> <p>Seeing that you may have used it to understand the object, that is, the object is not only a set of features, but also a set of acts. When designing, the performance of the behavior of the visual components is event, that is, "is something that can happen on this component." Generally speaking, you will use a way to connect the code to the event to determine what the event happens.</p> <p>The following is a key part: The application's build tool is dynamically queried by the Reflection, which attributes and events are found to support this component. Once you know who it is, build tools to display these properties, then let you modify (save these status when you create a program), of course, there is an event. In short, as long as you double-click on the mouse or other operations on an event, the programming tool will help you prepare the framework of the code, and then connect the event. Now, as long as you write the code that the event occurs when the event occurs.</p> <p>Programming tools have been doing so much, so you can concentrate on resolving the appearance and functional problems of the program, as for the details of each partial connection, give it to the build tool. Visual programming tools can achieve such a huge success because it can greatly improve the efficiency of programming, of course, this is first reflected in the user interface, but other aspects often benefit. What is JavaBean to do? The words retired, the components are actually a piece of package that encapsulates. The key is that it allows the application's build tool to extract your properties and events. When creating a VB component, the programmer must discover the properties and events with a fairly complex code in accordance with a specific agreement. Delphi is the second generation visual programming tool, and the entire language is designed around visual programming, so it is necessary to use it to create visual components. But Java leads the leader in the creation technology of visual components with its JavaBean. Bean is just a class, so you don't have to write any additional code for creating a bean, nor do you have to use special language extensions. In fact, you have to do it just a little habit named. Is the name of the method tells the application build tool, this is an attribute, the event is still a general method.</p> <p>The JDK document incorrectly expresses the Naming Convention "" Design Pattern ". This is unfortunate, design mode (see the Thinking in patient (with java) on www.bruceeckel.com) itself is enough to be a brainstorm, and some people still confuse audiovisual. Reiterates it, this is not a design pattern, just naming norms, and it is quite simple.</p> <p>For properties called xxx, you usually have to create two ways: getxxx () and setxxx (). Note The build tool automatically converts the first letters behind "Get" and "Set" into lowercase to obtain the name of the attribute. The type returned by GET is the same as the type of parameters used by "SET". The name of the property is independent of the type returned by "GET" and "set" method. For the Boolean type properties, you can use the "GET" and "Set" methods described above, or "IS" can be used instead of "get". BEAN's conventional methods do not need to follow the above naming specifications, but they must be public. Turn out the event with Swing Listener. That is to say that this program has been in use: Treat Bouncener with AddbouNcelistener (BounceListener) and RemovebouNcelistener (BounceListener). In most cases, built-in events and listeners can already meet your needs, but you can also create your own events and listener interfaces. The first point answered a question that you may pay attention to when comparing the new old code: Many names have some very small, but there is no significant change. Now you should know, in order to make the component into Javabean, most modifications are in line with the "GET" and "SET" naming specification.</p> <p>We can create a simple bean based on these principles:</p> <p>//: frogbean: Frog.java// A trivial JavaBean.package frogbean; import java.awt *; import java.awt.event *; class Spots {} public class Frog {private int jumps; private Color color; private.. Spots spots; private boolean jmpr; public int getJumps () {return jumps;} public void setJumps (int newJumps) {jumps = newJumps;} public Color getColor () {return color;} public void setColor (Color newColor) {color = newColor;} public Spots getSpots () {return spots;} public void setSpots (Spots newSpots) {spots = newSpots;} public boolean isJumper () {return jmpr;} public void setJumper (boolean j) {jmpr = j;} public void addActionListener (ActionListener l) {// ...} public void removeActionListener (ActionListener l) {// ...} public void addKeyListener (KeyListener l) {// ...} public void removeKeyListener (KeyListener l) {/ / ...} // an "orderinaary" public method: public void crint () {system.out.println ("Ribbet!");}} ///: ~ First, you will find it just a class. Usually all fields are private and can only be accessed by way. The names of the attributes Jumps, Color, Spots, and Jumper are strictly followed by naming specifications (note changes in the first letter of attribute). Although the name of the internal variable associated with the top three properties is the same as the name of the attribute, you can see from Jumper, the name of the property does not have to use the name of the internal variable (actually or not this internal variable). According to the "Add" and "Remove" method, we know that this bean can handle ActionEvent and KeyEvent events. Finally, you will find that Bean has a general method croak (), not because it follows the naming specification, just because it is public.</p> <p>Extract BeanInfo with Introspector When you drag the Bean to the Control Box (Palette), the most important ring in the JavaBean architecture starts working. The application build tool must be able to create this bean (if you have a default constructor), then extract all necessary information without watching the Bean source code, then create the property table and event handle.</p> <p>From Chapter 10, we have been able to partially solve this problem: Java's Reflection mechanism can help us find all the methods of the class. We don't want to use special keywords like other visual programming languages ​​to solve the JavaBean problem, so this is a perfect solution. In fact, give Java's main reasons for support JavaBean (although it also supports "Object Serializaiton" and "Remote Method Invocation". Maybe you want to design applications. The people who build tools will reflect bean one by one, find all the methods, then pick up the bean properties and events. Of course, Java provides us with a standard tool. This not only makes the use of beans It is more convenient, and also creates a more complex bean to point out a standard channel. This tool is Introspector, where the most important method is static getBeanInfo (). When you send a Class object to this method, it will A complete discharm, then return a beanInfo object so you can find the property, methods, and events of Bean through this object.</p> <p>Usually you don't have to worry about it at all; most of the beans have bought them directly from the supplier, let alone you don't have to know what the pattern is playing at the bottom. You only need to put the bean on the form and then configure the property, and then write a program to handle the event. But using Introspector Shows Bean's information is very interesting, it is also very meaningful to practice, so let's write a tool:</p> <p>//: C14: beandumper.java// Introspecting a bean.import java.beans. *; import java.lang.reflect. *; import javax.swing. *; import java.awt. *; import java.awt.event . *; import com.bruceeckel.swing *;. public class BeanDumper extends JFrame {private JTextField query = new JTextField (20); private JTextArea results = new JTextArea (); public void print (String s) {results.append (s "/ n");} public void dump (class bean) {results.setText (""); beanInfo bi = null; try {bi = Introspector.getBeanInfo (bean, object.class);} catch (IntrospectionException E) {Print ("couldn't Introspect" bean.getName ()); return;} protydescriptor [] Properties = bi.getPropertyDescriptors (); for (int i = 0; i <properties.length; i ) {class P = Properties [i] .GetPropertyType (); if (p == null) Continue; Print ("Property Type: / N" P.GetName () "Property Name: / N" Properties [i] .Getname () ); Method readmethod = Properties [i] .getreadMethod (); if ( ReadMethod! = null) Print ("Read method: / n" readmeth; method writeMethod = Properties [i] .GetwriteMethod (); if (WriteMethod! = null) Print ("Write Method: / N" WriteMethod; Print ("=====================");} Print ("Public Methods:"); MethodDescriptor [] methods = bi.getMethodDescriptors (); for (int i = 0; i <methods.length; i ) print (Methods [i] .getMethod (). Tostring ()); print ("=========</p> <p>============== ");" Event Support: "); EventSetDescriptor [] events = bi.geteventsetDescriptors (); for (int i = 0; i <events.Length; i ) {Print ("Listener Type: / N" Events [i] .Getlistenertype (). GetName ()); method [] lm = events [i] .getlistenerMethods (); for (int J = 0; J <LM) .length; J ) Print ("Listener Method: / N" LM [J] .GetName ()); methoddscriptor [] lmd = events [i] .getlistenerMethodDescriptors (); for (int J = 0; j <LMD. Length; J ) Print ("Method Descriptor: / N" LMD [J] .getMethod ()); Method AddListener = Events [i] .GetaddListenerMethod (); Print ("Add Listener Method: / N" AddListener; Method RemoveliStener = Events [i] .getremovelistenerMethod (); Print ("Remove Listener Method: / N" Removelistener; Print ("====================" }}} Class Dumper Implements ActionListener {Public Void ActionPerformed (ActionEvent E) {String Name = query.getText (); Class C = NULL; try {c = class.forname (name);} catch (classnotfoundexception ex) {results.settext ("couldn't find" name); return;} dump (c);}} public beandumper () {Container CP = getContentPane (); JPANEL P = new jPanel (); p.setLayout (new flowLayout ()); P.Add ("Qualified Bean Name:)); P.Add (query); CP .add (BorderLayout.North, P);</p> <p>CP.Add (results); Dumper DMPR = New Dumper (); Query.AddActionListener (DMPR); Query.Settext ("frogbean.frog"); // force evAluation DMPR.ActionPerformed (New ActionEvent (DMPR, 0, ""));} public static void main (string [] args) {console.run (New Beandumper (), 600, 500);}} ///: ~ beandumper.dump () method completes all task. It first tries to create a beanInfo object. If successful, use BeanInfo's method to get the bean properties, methods, and events. You will find two parameters in INTROSPECTOR.GETBEANINFO (). The second one is to tell Introspector, which level should be traced back to the inheritance hierarchy. Here, we will let it stop in Object, because we are not interested in this. For properties, getPropertyDescriptors () returns a PropertyDescriptor array. You can call getPropertyType () to PropertyDescriptor, so you can know what type is when it is transmitted by the property. Next, you can use getName () to obtain the pseudonym of the attribute (by judging the name of the method), the method of reading the property with getReadMethod (), the method of writing attributes (). The last two methods returned a Method object, which is really used to call the object (this part belongs to the reflection).</p> <p>GetMethodDescriptors () returns a MethodDescriptor array for publicDescriptors (including attribute methods). You can get the Method object associated with it, then print it out.</p> <p>For events, getEventSetDescriptors () will return an EventSetDescriptor array (who can it be?). You can know the type of Listener, what methods, add, and remove methods. Beandumper will print all this information.</p> <p>The information of FrogBean.frog will be extracted when the program starts. Remove all insignificant things, the output is like this:</p> <p>Class name: frogproperty type: colorProperty name: ColorRead method: public color color getColor () Write method: public void setColor (color) ==================================Potsproperty Name: Spotsread Method: Public Spots GetSpots () Write Method: Public Void SetSpots (Spots) =================================Property Type: BooleanProperty Name: JumperRead Method: Public Boolean ISJUMPER () WRITE METHOD: PUBLIC VOID SetJumper (Boolean) ==================================== void setJumps (int) ==================== public methods: public void setJumps (int) public void croak () public void removeActionListener (ActionListener) public void addActionListener (ActionListener ) public int getJumps () public void setColor (Color) public void setSpots (Spots) public void setJumper (boolean) public boolean isJumper () public void addKeyListener (KeyListener) public Color getColor () public void removeKeyListener (KeyListener) public Spots getSpots ( ) ========= =============</p> <p>Event support: Listener type: KeyListenerListener method: keyTypedListener method: keyPressedListener method: keyReleasedMethod descriptor: public void keyTyped (KeyEvent) Method descriptor: public void keyPressed (KeyEvent) Method descriptor: public void keyReleased (KeyEvent) Add Listener Method: public void addKeyListener ( KeyListener) Remove Listener Method: public void removeKeyListener (KeyListener) ==================== Listener type: ActionListenerListener method: actionPerformedMethod descriptor: public void actionPerformed (ActionEvent) Add Listener Method : Public void addActionListener (ActionListener) Remove Listener method: public void removeactionListener (ActionListener) ==================== Here included Introspect to get from BeanInfo About Bean Most of the information. You will find the type of attribute independeand to their name. Note that the attribute name is lowercase. (This sentence is not true when the attribute name in the "Get / Set" method is at the beginning of two or more uppercase letters or two or more uppercase letters, this sentence is not established.) And remember, The method name (such as reading and writing) is actually extracted from the Method object, and you can use the Method object to invoke the method associated with it. The list of public methods includes not only methods such as croak () as attributes or events, but also related methods. They are all methods you can call when you program, and the application build tool will be all listed all when you need to call the method, so you can reduce your burden.</p> <p>Finally, you will find that all events are parsed into Listener, Listener's methods, and Listener's Add and REMOVE methods. Basically, as long as you can get BeanInfo, you can find all important information in the bean. You can even use the bean itself without any other information (this is also the characteristics of the reflection).</p> <p>One more complex bean will take a slightly complicated example, but there are also some discrete examples. This is one of the mouse, which will draw a circle on the top JPanel. When you press the mouse, it will display "Bang" on the center of the screen while triggeting an event listener.</p> <p>The properties you can modify include the size of the circle and the color and font size of the text displayed when the mouse is pressed. In addition, BangBean has his own addActionListener () and removeactionListener (), so you can connect your own listener, which triggers this Listener when the user presses Bangbean. You should know how to provide properties and events:</p> <p>//: bangbean: bangbean.java//A graphical bean.Package Bangbean; import javax.swing. *; import java.awt. *; import java.awt.event. *; import java.io. *; import java. util *;. import com.bruceeckel.swing *;. public classBangBean extends JPanel implements Serializable {private int xm, ym; private int cSize = 20; // Circle size private String text = "Bang!"; private int fontSize = 48 ; private Color tColor = Color.RED; private ActionListener actionListener; public BangBean () {addMouseListener (new ML ()); addMouseMotionListener (new MML ());} public int getCircleSize () {return cSize;} public void setCircleSize (int newSize) {cSize = newSize;} public String getBangText () {return text;} public void setBangText (String newText) {text = newText;} public int getFontSize () {return fontSize;} public void setFontSize (int newSize) {fontSize = Newsize;} public color getTextColor () {Return Tcolor;} public void settextColor (color newcolor) {tcolor = newcolor;} PUBL IC Void PaintComponent (GRAPHICS G) {Super.PaintComponent (G); G.SetColor (color.black); g.drawoval (XM - CSIZE / 2, YM - CSIZE / 2, CSIZE, CSIZE);} // this is a unicast listener, which is // the simplest form of listener management: public void addActionListener (ActionListener l) throws TooManyListenersException {if (! actionListener = null) throw new TooManyListenersException (); actionListener = l;} public void removeActionListener (ActionListener l) {ActionListener = NULL;} Class Ml Extends Mouseadapter {public void mousepressed (MouseEvent E) {graphics g = getGraphics (); g.setcolor; g.setfont (New Font ("TimeesRoman"</p> <p>, Font.bold, fontsize); int width = g.getFontMetrics (). StringWidth (text); g.drawstring (text, (getsize (). Width - width / 2, getsize (). Height / 2); g.dispose (); // Call the listener's method: if (! actionListener = null) actionListener.actionPerformed (new ActionEvent (BangBean.this, ActionEvent.ACTION_PERFORMED, null));}} class MML extends MouseMotionAdapter {public void mouseMoved ( MouseEvent E) {xm = E.GETX (); ym = E.GETY (); repaint ();}} public dimension getpreferredsize () {Return New Dimension (200);}} ///: ~ First, You will notice that the BangBean implements the Serializable interface. That is to say, after the designer modified the property value of Bangbean, the application build tool can save this information by serialization. When the application is to create a bean, then the property of "saving" is restored, so that the design can be obtained. You will find that all fields are private, in fact, this is also the usual practice of bean - that is, after "attributes", it usually only uses the method to access.</p> <p>When you look at AddActionListener () (Translator Note: That is, the parameter table and return value), you will find it to throw the toomanListenerSexception. This means that it is unicast, that is, it will only send a notification to a listener when an event occurs. But usually you are all multicast events, that is, an event can pass to multiple listeners. But do this involve thread problems, and this part of the content is in the "JavaBeans and Synchronization" section. So now we use unicast to deal it.</p> <p>When you press the mouse, the text will appear in the positive center of Bangbean. If ActionListener is not empty, it will create an ActionEvent, then call it an actionPerformed () method. Whenever you move the mouse, Bangbean will capture new coordinates, and redraw Canvas (as you can see, put the text on the canvas all).</p> <p>Below is the BangBeantest class for testing:</p> <p>//: c14: bangbeantest.javaimport Bangbean. *; import javax.swing. *; import java.awt. *; import java.awt.event. *; import java.util. *; import com.bruceeckel.swing. * ; public class BangBeanTest extends JFrame {private JTextField txt = new JTextField (20); // During testing, report actions: class BBL implements ActionListener {private int count = 0; public void actionPerformed (ActionEvent e) {txt.setText ( "BangBean Action " count );}} public Bangbeantest ()} PUBLIC BANGBEANTEST () {Bangbean BB = New Bangbean (); try {bb.addactionListener (new bbl ());} catch (toomanylistenersexcection e) {txt.setText (" Too Many Listener ") Container cp = getContentPane (); cp.add (bb); cp.add (borderLayout.South, txt);} public static void main (string [] args) {console.run (New Bangbeantest (), 400, 500);}} ///: ~ If you use the bean provided by IDE, then this class is not used to use, but it can help you create a test program that can quickly test your own beans. BangbeanTest will put Bangbean in the Applet, then connect a simple actionListener, once an event, which prints the cumulative number of events to JTextField. Of course, usually the application build tool creates most of the code. If you use Beandumper to observe Bangbean, or put it in a support bean IDE, you will find that its properties and behavior are much more than the code written in the code. This is because Bangbean is a derived class of JPanel, and JPanel is also bean, so you see it also includes its properties and events.</p> <p>JavaBeans and synchronization As long as you have created Beans, you have to ensure that it works normally in multithreaded environments, this is:</p> <p>As long as it allows, all beans's public methods must be synchronized. Of course, this will affect performance (but in the latest version of JDK, this impact has fallen significantly). If performance is really a problem, then you can get rid of Synchronized that is not caused by problems, but you have to remember that you will not cause problems that you can see. This method first is small (just like getCirclesize ()) in the previous program, and / or "atomic operation", that is, the code called by this method is so small that the object will not be edited. So make this method non-synchronized, and will not have a significant impact on performance. So you should make all the public methods of the bean Synchronized, only when there is absolutely necessary, and doing effective to improve performance, you can remove the synchronized. When you send a multicast event to a team of Listener, you must prepare, Listener will be added or removed from the queue. The first question is very good, but the second question is going to think about it. The last version of Bangbean.java uses ignored synchronized keywords and unicast events to avoid multithreading. Below we will write a modified version that can be run in multi-threaded environment and can use multicast events:</p> <p>//: C14: Bangbean2.java// You Should Write Your Beans this Way So They // Can Run in a Multithreaded Environment.Import javax.swing. *; import java.awt. *; import java.awt.event. * ; import java.util *;. import java.io *;. import com.bruceeckel.swing *;. public class BangBean2 extends JPanelimplements Serializable {private int xm, ym; private int cSize = 20; // Circle size private String text = "Bang!"; private int fontSize = 48; private Color tColor = Color.RED; private ArrayList actionListeners = new ArrayList (); public BangBean2 () {addMouseListener (new ML ()); addMouseMotionListener (new MM ()); } public synchronized int getCircleSize () {return cSize;} public synchronized void setCircleSize (int newSize) {cSize = newSize;} public synchronized String getBangText () {return text;} public synchronized void setBangText (String newText) {text = newText; } Public synchronized int getFontsize () {Return FontSize;} public synchronized void setfontsize (int news) {fonts ize = newSize;} public synchronized Color getTextColor () {return tColor;} public synchronized void setTextColor (Color newColor) {tColor = newColor;} public void paintComponent (Graphics g) {super.paintComponent (g); g.setColor (Color . Black); g.drawoval (XM - CSIZE / 2, YM - CSIZIZE / 2, CSIZE, CSIZE);} // this is a multicast listener, which is more type // buy Than the Unicast Approach Taken In Bangbean.java : public synchronized void addActionListener (ActionListener l) {actionListeners.add (l);} public synchronized void removeActionListener (ActionListener l) {actionListeners.remove (l);} // Notice this isn '</p> <p>t synchronized: public void notifyListeners () {ActionEvent a = new ActionEvent (BangBean2.this, ActionEvent.ACTION_PERFORMED, null); ArrayList lv = null; // Make a shallow copy of the List in case // someone adds a listener while we 'RE // Calling Listener: Synchronized (this) {lv = (arraylist) ActionListeners.clone ();} // call all the listener methods: for (int i = 0; i <lv.size (); i ) ( (ActionListener). ActionPerformed (a);} Class ML Extends Mouseadapter {public void mousepressed (MouseEvent E) {graphics g = getGraphics (); g.setcolor; g.setfont (New font ("Timeesroman", Font.Bold, FontSize); int width = g.GetFontMetrics (). StringWidth (text); g.drawstring (text, (getSize (). Width - width / 2, getsize (). HEIGHT / 2); g.dispose (); notifyListener ();}} class mm extends mousemotionAdapter {public void mousemoved (mouseEvent E) {xm = E.GETX (); ym = E.Gety (); repaint ();}} public static void main (String [] args) {BangBean2 bb = new BangBean2 (); bb.addActionListener (new ActionListener () {public void actionPerformed (ActionEvent e) {System.out.println ( "ActionEvent " E);}}; bb.addActionListener (new actionListener () {public void actionPerformed (ActionEvent E) {system.out.println (" Bangbean2 Action ");}}); bb.addActionListener (New ActionListener () {Public Void ActionPerformed (ActionEvent E) {System.out.Println ("more action");}}); console.run (bb, 300, 300);}} ///: ~ Give method plus synchronized is a simple Modifications,</p> <p>But please note addActionListener () and removeactionListener (), which are in ArrayList to increase or decrease the ActionListener, so the number of ActionListener now is not limited. NotifyListeners () is not synchronized. It may be called simultaneously by multiple threads. The same addActionListener () and removeactionListener () may also be called by other threads when NOTIFYLISTENER () is running to half. Since NotifyListener () needs to traverse ArrayList ActionListeners, there is a problem. In order to solve this problem, we use the key paragraph Clone with arraylist, then let the code go to traverse this clone (see Appendix A). This will never affect the original ArrayList will not affect NotifyListeners ().</p> <p>PainTComponent () also has no synchronized. When determining the override method, it is not as clear as the method of deciding what you write. . Here, it seems to work like PaintComponent () does not add Synchronized. But the questions must be considered:</p> <p>Does this method modify the "key" variable of the object? Whether the variable is "key" is whether they are written by other threads. (Here, reading and writing is actually completed by the synchronized method, so you can see this) in this program, PaintComponent () does not modify anything. Is this method related to the state of this "key" variable? If there is a synchronized method to modify the variable to be used this method, then it is best to make this method into synchronized. Based on this, you may find that CSIZE is modified by the synchronized method, so PaintComponent () should also be synchronized. But here you should ask "If you perform PaintComponent (), CSIZE is modified, what is the worst situation?" If the problem is not serious, and turns fleet, then to prevent the performance caused by Synchronized Decline, you can make PaintComponent () into non-synchronized. The third idea is to see the base class PaintComponent () is SYNCHRONIZED. The answer is "No". This is not a thousand unlunished judgment criteria, just a thinking. Take the above program, PaintComponent () mixed a CSIZE field modified by the Synchronized method, so the situation has changed. However, please note that SYNCHRONIZED will not inherit; Paint () and PaintComponent () are the faster way to perform. Any of the way to improve performance is worthy of recommendation, so if you find that you have to use synchronized to these methods, it is likely to be a signal that fails. Main () test code is based on BangBeantest modified. In order to demonstrate the multicast function of Bangbean2, it adds more listeners.</p> <p>Package Bean To use JavaBean in the visual programming tool, you must first put it in a standard Bean container. That is, all the Class files of all beans and a "manifest" file of a statement "this is a bean" file into a jar package. The Manifest file is a text file with a certain format. For Bangbean, its manifest file is like this: manifest-version: 1.0Name: bangbean / bangbean.classjava-bean: True The first line indicates the version of Manifest, unless sun sent future notice, otherwise it is 1.0. The second line (empty line is ignored) Special mentioned BangBean.class file, and the third line means "this is Y a bean". Without a third line, the application build tool will not look into a bean.</p> <p>The only place where you can play, you must indicate the correct path in "Name:". If you turn to your front to see Bangbean.java, you will find it belonging to Bangbean Package (so you must put it in the "Bangbean" subdirectory of a directory of ClassPath), and the manifest's Name must also contain this package information. In addition, the Manifest file must be placed in the last layer directory of the root directory of the package path, where manifest is placed in the "BANGBEAN" subdirectory. Then Impress the JAR command below in the directory where the Manifest file is stored:</p> <p>Jar cfm bangbean.jar Bangbean.mf Bangbean This assumes that the name of the JAR file is bangbean.jar, and the name of the Manifest file is Bangbean.mf.</p> <p>Maybe you will feel a little strange. "I also generated some other class files when I compiled Bangbean.java. Where did they go?" Yes, they finally put them in the bangbean subdirectory, and the above The last parameter of the jar command is Bangbean. When you give the JAR a subdirectory, it will enhance the entire subdirectory into the JAR file (here also included the source code of Bangbean.java - I will never want to put the source code when you write bean yourself. Bag). In addition, if you let the JAR files you just do, you will find that the manifest you just wrote is already inside. Instead, it is the manifest file named Manifest.mf in JAR himself. And it puts it in the meta-INF subdirectory (meaning "meta-information"). If you open this manifest file, you will find information that JAR adds a signature of each file, just like this:</p> <p>Digest-Algorithms: SHA MD5 SHA-Digest: pdpeag9naecx8AFTQPI4UDSX / O0 = MD5-Digest: O4NCS1HE3SMNZLP2HJ6QEG == In short, you don't have to worry about these things. When you make changes, you can only change your own manifest file, and then re-run the JAR, let it create a new JAR file. You can also add new Beans to the JAR file, just add their information to Manifest.</p> <p>It is worth noting that you should create a subdirectory for each bean. This is because when you create a JAR file, you will hand over the name of the subdirectory to JAR, and JAR will put all things in the subdirectory into JAR. So frog and bangbean have their own subdirectory.</p> <p>After you encapsulate the bean into a JAR file, you can use them to support the Bean's IDE. This step will have some differences with the development tools, but Sun offers a free JavaBean test bed (you can go to java.sun.com/beans) in their "Bean Builder". To join the bean to bean Builer, just copy the JAR file to the correct directory. Bean's advanced features You already know how simple it is, but its function is not limited to this. Javabean's architecture allows you to get started quickly, but through an extension, it can also adapt to more complex situations. These uses have exceeded the scope of this book, but I will do a simple introduction. You can find more details on java.sun.com/beans.</p> <p>Attribute is a place that can be enhanced. In our example, attributes are single, but you can also use an array to represent multiple properties. This is called an indexed property. As long as you give the correct way (or to follow the naming specification of the method), the Introspector can find an indexed property so that the application build tool can make the correct reflection.</p> <p>The property can be bound, that is, they can notify other objects via the PropertyChangeEvent. Other objects can modify their state according to the changes in Beans.</p> <p>Attributes can be restricted, that is, if other objects think this change is unacceptable, they can veto this change. Bean informs other objects with PropertyChangeevent, while other objects use protyvetoexception to represent opposition, and command it to restore the value of the attribute to the original state.</p> <p>You can also modify the way beans in design:</p> <p>You can provide a custom property list for Beans. When the user selects other beans, the build tool provides a list of normal properties, but when they choose your bean, it provides your definition list. You can create a custom editor for attributes, which although the build tool is a normal attribute list, but when the user wants to edit this special property, the editor will automatically start. You can provide a custom Beanfo class for beans, which returns the information that can be different from the BEANInfo provided by the INTROSPector. You can also open all FeatureDescriptor's "Expert" mode to see what is the difference between basic functions and advanced features. Bean's other information has a lot of books about Javabean; such as Elliotte Rusty Harold JavaBeans (IDG, 1998)</p> <p>Summary In the upgrade process from Java 1.0 to Java 2, the GUI class library is the most severe in all class libraries. The Java 1.0 AWT has been unscrupulous and even known as the worst design ever. Although it achieves the goal of creating cross-platform programs, its interface "is so mediocrity on all platforms." Compared with their respective platforms, it seems to be promoted, weird and unsatisfactory.</p> <p>When Java 1.1 introduces new event models and JavaBean, things start entering the right track - now you can create a GUI component that can drag in the visual development tool. In addition, event models and JavaBeans fully demonstrate that Java's designers have multiple stickers for help programmers to reduce development and maintenance (can't see in AWT 1.0). But before JFC / SWING was released, this is not satisfactory. With SWING components, cross-platform GUI programming finally became elegant.</p> <p>In fact, the only lack is the application build tool, which is the development of the revolution. Microsoft's Visual Basic and Visual C require you the same as Microsoft programming tools, Borland's Delphi and C Builder. If you think that these can't make you satisfied, you can only go all over ten, I hope to have developers to make you. But Java is an open environment, so it not only allows even encourages the competition of programming tools. And if the programming tool really wants to participate in competition, it must support JavaBean. This forms an equal competitive environment; with good programming tools, you can not hang on a tree. You can pick up the most satisfied, then move the old items, so you can improve efficiency. This fierce competition in this GUI development tool market is unprecedented, and its results will only have a positive impact on the production efficiency of programmers. This chapter just wants to introduce you to Swing's powerful features and lead you to get started. This way you can go to the road after you know how much Swing. These you have seen can already meet the UI design. But Swing is more than this; its goal is to be a fully fully equipped UI design tool. As long as you can think of it, it has a way to do it.</p> <p>If you can't find what you want here, then study Sun's JDK document, or go to the web. If you can't do it, you will find a Swing monograph. The JFC Swing Tutorial (Addison Wesley, 1999) written by Walrath and Campione is a good entry textbook.</p> <p>-------------------------------------------------- ------------------------------</p> <p>[74] Another statement is "Minimal Surprising Principle", its essence is "Don't scare users".</p> <p>[75] Note that IBM's GUI class library created by the new open source code created by their Eclipse editor (www.eclipse.org), you may consider using it to replace Swing.</p> <p>[76] The application framework is a design pattern, referred to as "template method".</p> <p>[77] This is assumed here that the reader is familiar with the basics of HTML. In fact, there are many books and materials in this area, nor is it too difficult to understand.</p> <p>[78] According to me, you don't have to waste time after you have learned Swing.</p> <p>[79] As mentioned earlier, "frame" has been treated by AWT, so swing can only use JFrame.</p> <p>[80] Waiting for you to see it later. First make a member of the Static of the Japplet (instead of main () of the local variable). Then call Applet.Stop () and Applet.Destroy () using the Windowadapter.WindowClosing () method before system.exit ().</p> <p>[81] Although you will feel that there should be a mousemotionelent, but it is not actually. Click and exercise is merged into mouseevent, so MouseEvent has two times in the form, which is not a pen.</p> <p>[82] In Java 1.0 / 1.1, you can't even effectively create a derived class for the button. This is just an example in which a few countless design defects.</p> <p>[83] This section and the following section written by Jeremy Meyer.</p> <p>[84] This concept will be fully elaborated in Thinking in Enterprise Java, you can download this book on www.bruceeckel.com.</p> <p>[85] This section writes by Jeremy Meyer.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-59169.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="59169" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.043</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'FcCxXcPrdTtvOx7EGMmAfoVn2ySP6S4dMbEihuGLZj8P2Phln74vvkBODvbmAZ9UqB2EE13kl1Q1jAkdwtf9vQ_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>