################# NestedLayout.java Layout of complicated GUI by taking advantage of nested containers. Uses WindowUtilities.java and ExitListener.java. ################## import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; /** An example demonstrating the use of nested containers * to lay out the components. See GridBagTest.java for * implementation by a single layout manager, GridBagLayout. * ******************* */ public class NestedLayout extends JPanel { private JTextArea textArea; private JButton bSaveAs, bOk, bExit; private JTextField fileField; public NestedLayout() { setLayout(new BorderLayout(2,2)); setBorder(BorderFactory.createEtchedBorder()); textArea = new JTextArea(12,40); // 12 rows, 40 cols bSaveAs = new JButton("Save As"); fileField = new JTextField("C:\\Document.txt"); bOk = new JButton("OK"); bExit = new JButton("Exit"); add(textArea,BorderLayout.CENTER); // Set up buttons and textfield in bottom panel. JPanel bottomPanel = new JPanel(); bottomPanel.setLayout(new GridLayout(2,1)); JPanel subPanel1 = new JPanel(); JPanel subPanel2 = new JPanel(); subPanel1.setLayout(new BorderLayout()); subPanel2.setLayout(new FlowLayout(FlowLayout.RIGHT,2,2)); subPanel1.add(bSaveAs,BorderLayout.WEST); subPanel1.add(fileField,BorderLayout.CENTER); subPanel2.add(bOk); subPanel2.add(bExit); bottomPanel.add(subPanel1); bottomPanel.add(subPanel2); add(bottomPanel,BorderLayout.SOUTH); } public static void main(String[] args) { WindowUtilities.setNativeLookAndFeel(); JFrame frame = new JFrame("Nested Containers"); frame.setContentPane(new NestedLayout()); frame.addWindowListener(new ExitListener()); frame.pack(); frame.setVisible(true); } } ##########################
Aug 26
Layout of complicated GUI by taking advantage of nested containers
Aug 26
A demo providing multiple buttons to select a playing card-A Panel, using CardLayout control which of four possible subpanels, holding a different card, to display
####################### # CardDemo.java A demo providing multiple buttons to select a playing card. A Panel, using CardLayout control which of four possible subpanels, holding a different card, to display.Uses the following class and images: * CardPanel.java A Panel that displays a playing card. * ImageLabel.java A Canvas for displaying images. * Ace.gif, King.gif, Queen.gif, Jack.gif. ##################### import java.applet.Applet; import java.awt.*; import java.awt.event.*; /** An example of CardLayout. The right side of the window holds * a Panel that uses CardLayout to control four possible * subpanels (each of which is a CardPanel that shows a * picture of a playing card). The buttons on the left side * of the window manipulate the "cards" in this layout by * calling methods in the right-hand panel's layout manager. * ********************************* public class CardDemo extends Applet implements ActionListener { private Button first, last, previous, next; private String[] cardLabels = { "Jack","Queen","King","Ace" }; private CardPanel[] cardPanels = new CardPanel[4]; private CardLayout layout; private Panel cardDisplayPanel; public void init() { setBackground(Color.white); setLayout(new BorderLayout()); addButtonPanel(); addCardDisplayPanel(); } private void addButtonPanel() { Panel buttonPanel = new Panel(); buttonPanel.setLayout(new GridLayout(9, 1)); Font buttonFont = new Font("SansSerif", Font.BOLD, 18); buttonPanel.setFont(buttonFont); for(int i=0; inot use CardLayout. Rather, instances of CardPanel * are contained in another window used in the CardDemo * example. It is this enclosing window that uses CardLayout * to manipulate which CardPanel it shows. * ************************* public class CardPanel extends Panel { private Label name; private ImageLabel picture; public CardPanel(String cardName, URL directory, String imageFile) { setLayout(new BorderLayout()); name = new Label(cardName, Label.CENTER); name.setFont(new Font("SanSerif", Font.BOLD, 50)); add(name, BorderLayout.NORTH); picture = new ImageLabel(directory, imageFile); Panel picturePanel = new Panel(); picturePanel.add(picture); add(picturePanel, BorderLayout.CENTER); setSize(getPreferredSize()); } public Label getLabel() { return(name); } public ImageLabel getImageLabel() { return(picture); } } ******************* ImageLabel.java A Canvas for displaying images. ******************* import java.awt.*; import java.net.*; /** A class for displaying images. It places the Image * into a canvas so that it can moved around by layout * managers, will get repainted automatically, etc. * No mouseXXX or action events are defined, so it is * most similar to the Label Component. * * By default, with FlowLayout the ImageLabel takes * its minimum size (just enclosing the image). The * default with BorderLayout is to expand to fill * the region in width (North/South), height * (East/West) or both (Center). This is the same * behavior as with the builtin Label class. If you * give an explicit setSize or * setBounds call before adding the * ImageLabel to the Container, this size will * override the defaults. * * Here is an example of its use: * * * public class ShowImages extends Applet { * private ImageLabel image1, image2; * * public void init() { * image1 = new ImageLabel(getCodeBase(), * "some-image.gif"); * image2 = new ImageLabel(getCodeBase(), * "other-image.jpg"); * add(image1); * add(image2); * } * } * * */ public class ImageLabel extends Canvas { // Instance variables. // The actual Image drawn on the canvas. private Image image; // A String corresponding to the URL of the image you will // get if you call the constructor with no arguments. private static String defaultImageString = "http://java.sun.com/lib/images/" + "logo.java.color-transp.55x60.gif"; // The URL of the image. But sometimes we will use an existing // image object (e.g. made by createImage) for which this info // will not be available, so a default string is used here. private String imageString = ""; // Turn this on to get verbose debugging messages. private boolean debug = false; /** Amount of extra space around the image. */ private int border = 0; /** If there is a non-zero border, what color should it be? * Default is to use the background color of the Container. */ private Color borderColor = null; // Width and height of the Canvas. This is the // width/height of the image plus twice the border. private int width, height; /** Determines if it will be sized automatically. If the user * issues a setSize() or setBounds()call before adding the * label to the Container, or if the LayoutManager resizes * before drawing (as with BorderLayout), then those sizes * override the default, which is to make the label the same * size as the image it holds (after reserving space for the * border, if any). This flag notes this, so subclasses that * override ImageLabel need to check this flag, and if it is * true, and they draw modified image, then they need to draw * them based on the width height variables, not just blindly * drawing them full size. */ private boolean explicitSize = false; private int explicitWidth=0, explicitHeight=0; // The MediaTracker that can tell if image has been loaded // before trying to paint it or setSize based on its size. private MediaTracker tracker; // Used by MediaTracker to be sure image is loaded before // paint & setSize, since you can't find out the size until it // is done loading. private static int lastTrackerID=0; private int currentTrackerID; private boolean doneLoading = false; private Container parentContainer; /** Create an ImageLabel with the default image. * * @see #getDefaultImageString * @see #setDefaultImageString */ // Remember that the funny "this()" syntax calls // constructor of same class public ImageLabel() { this(defaultImageString); } /** Create an ImageLabel using the image at URL * specified by the string. * * @param imageURLString A String specifying the * URL of the image. */ public ImageLabel(String imageURLString) { this(makeURL(imageURLString)); } /** Create an ImageLabel using the image at URL * specified. * * @param imageURL The URL of the image. */ public ImageLabel(URL imageURL) { this(loadImage(imageURL)); imageString = imageURL.toExternalForm(); } /** Create an ImageLabel using the image in the file * in the specified directory. * * @param imageDirectory Directory containing image * @param file Filename of image */ public ImageLabel(URL imageDirectory, String file) { this(makeURL(imageDirectory, file)); imageString = file; } /** Create an ImageLabel using the image specified. The other * constructors eventually call this one, but you may want * to call it directly if you already have an image (e.g. * created through createImage). * * @param image The image */ public ImageLabel(Image image) { this.image = image; tracker = new MediaTracker(this); currentTrackerID = lastTrackerID++; tracker.addImage(image, currentTrackerID); } /** Makes sure that the Image associated with the Canvas is * done loading before returning, since loadImage spins off * a separate thread to do the loading. Once you get around * to drawing the image, this will make sure it is loaded, * waiting if not. The user does not need to call this at * all, but if several ImageLabels are used in the same * Container, this can cause several repeated layouts, so * users might want to explicitly call this themselves before * adding the ImageLabel to the Container. Another * alternative is to start asynchronous loading by calling * prepareImage on the ImageLabel's image (see getImage). * * @param doLayout Determines if the Container should be * re-laid out after you are finished waiting. This * should be true when called from user functions, * but is set to false when called from getPreferredSize * to avoid an infinite loop. This is needed when using * BorderLayout, which calls getPreferredSize * before calling paint. */ public void waitForImage(boolean doLayout) { if (!doneLoading) { debug("[waitForImage] - Resizing and waiting for " + imageString); try { tracker.waitForID(currentTrackerID); } catch (InterruptedException ie) {} catch (Exception e) { System.out.println("Error loading " + imageString + ": " + e.getMessage()); e.printStackTrace(); } if (tracker.isErrorID(0)) new Throwable("Error loading image " + imageString).printStackTrace(); doneLoading = true; if (explicitWidth != 0) width = explicitWidth; else width = image.getWidth(this) + 2*border; if (explicitHeight != 0) height = explicitHeight; else height = image.getHeight(this) + 2*border; setSize(width, height); debug("[waitForImage] - " + imageString + " is " + width + "x" + height + "."); // If no parent, you are OK, since it will have // been resized before being added. But if // parent exists, you have already been added, // and the change in size requires re-layout. if (((parentContainer = getParent()) != null) && doLayout) { setBackground(parentContainer.getBackground()); parentContainer.doLayout(); } } } /** Moves the image so that it is centered at * the specified location, as opposed to the setLocation * method of Component which places the top left * corner at the specified location. * * Note: The effects of this could be undone * by the LayoutManager of the parent Container, if * it is using one. So this is normally only used * in conjunction with a null LayoutManager. * * @param x The X coord of center of the image * (in parent's coordinate system) * @param y The Y coord of center of the image * (in parent's coordinate system) * @see java.awt.Component#setLocation */ public void centerAt(int x, int y) { debug("Placing center of " + imageString + " at (" + x + "," + y + ")"); setLocation(x - width/2, y - height/2); } /** Determines if the x and y (in the ImageLabel's * own coordinate system) is inside the * ImageLabel. Put here because Netscape 2.02 has * a bug in which it doesn't process contains() and * locate() tests correctly. */ public synchronized boolean contains(int x, int y) { return((x >= 0) && (x <= width) && (y >= 0) && (y <= height)); } /** Draws the image. If you override this in a * subclass, be sure to call super.paint. */ public void paint(Graphics g) { if (!doneLoading) waitForImage(true); else { if (explicitSize) g.drawImage(image, border, border, width-2*border, height-2*border, this); else g.drawImage(image, border, border, this); drawRect(g, 0, 0, width-1, height-1, border, borderColor); } } /** Used by layout managers to calculate the usual * size allocated for the Component. Since some * layout managers (e.g. BorderLayout) may * call this before paint is called, you need to * make sure that the image is done loading, which * will force a setSize, which determines the values * returned. */ public Dimension getPreferredSize() { if (!doneLoading) waitForImage(false); return(super.getPreferredSize()); } /** Used by layout managers to calculate the smallest * size allocated for the Component. Since some * layout managers (e.g. BorderLayout) may * call this before paint is called, you need to * make sure that the image is done loading, which * will force a setSize, which determines the values * returned. */ public Dimension getMinimumSize() { if (!doneLoading) waitForImage(false); return(super.getMinimumSize()); } // LayoutManagers (such as BorderLayout) might call // setSize or setBounds with only 1 dimension of // width/height non-zero. In such a case, you still // want the other dimension to come from the image // itself. /** Resizes the ImageLabel. If you don't setSize the * label explicitly, then what happens depends on * the layout manager. With FlowLayout, as with * FlowLayout for Labels, the ImageLabel takes its * minimum size, just enclosing the image. With * BorderLayout, as with BorderLayout for Labels, * the ImageLabel is expanded to fill the * section. Stretching GIF/JPG files does not always * result in clear looking images. So just as * with builtin Labels and Buttons, don't * use FlowLayout if you don't want the Buttons to * get resized. If you don't use any * LayoutManager, then the ImageLabel will also * just fit the image. * * Note that if you setSize explicitly, you must do * it before the ImageLabel is added to the * Container. In such a case, the explicit size * overrides the image dimensions. * * @see #setBounds */ public void setSize(int width, int height) { if (!doneLoading) { explicitSize=true; if (width > 0) explicitWidth=width; if (height > 0) explicitHeight=height; } super.setSize(width, height); } /** Resizes the ImageLabel. If you don't setSize the * label explicitly, then what happens depends on * the layout manager. With FlowLayout, as with * FlowLayout for Labels, the ImageLabel takes its * minimum size, just enclosing the image. With * BorderLayout, as with BorderLayout for Labels, * the ImageLabel is expanded to fill the * section. Stretching GIF/JPG files does not always * result in clear looking images. So just as * with builtin Labels and Buttons, don't * use FlowLayout if you don't want the Buttons to * get resized. If you don't use any * LayoutManager, then the ImageLabel will also * just fit the image. * * Note that if you setSize explicitly, you must do * it before the ImageLabel is added to the * Container. In such a case, the explicit size * overrides the image dimensions. * * @see #setSize */ public void setBounds(int x, int y, int width, int height) { if (!doneLoading) { explicitSize=true; if (width > 0) explicitWidth=width; if (height > 0) explicitHeight=height; } super.setBounds(x, y, width, height); } // You can't just set the background color to // the borderColor and skip drawing the border, // since it messes up transparent gifs. You // need the background color to be the same as // the container. /** Draws a rectangle with the specified OUTSIDE * left, top, width, and height. * Used to draw the border. */ protected void drawRect(Graphics g, int left, int top, int width, int height, int lineThickness, Color rectangleColor) { g.setColor(rectangleColor); for(int i=0; i
Aug 26
BorderLayout divides the window into five regions
# BorderTest.java Five buttons arranged by BorderLayout BorderLayout divides the window into five regions: NORTH, SOUTH, EAST, WEST, and CENTER. /./././././././././././././ import java.applet.Applet; import java.awt.*; /** An example of BorderLayout. * &&&&&&&&&&&&&&&&&&&&&&&&&&& public class BorderTest extends Applet { public void init() { setLayout(new BorderLayout()); add(new Button("Button 1"), BorderLayout.NORTH); add(new Button("Button 2"), BorderLayout.SOUTH); add(new Button("Button 3"), BorderLayout.EAST); add(new Button("Button 4"), BorderLayout.WEST); add(new Button("Button 5"), BorderLayout.CENTER); } } &&&&&&&&&&&&&&&&&&&&
Aug 26
Checkboxes
Checkboxes.java Inherits from CloseableFrame.java. ****************** import java.awt.*; /./././././././././ public class Checkboxes extends CloseableFrame { public static void main(String[] args) { new Checkboxes(); } public Checkboxes() { super("Checkboxes"); setFont(new Font("SansSerif", Font.BOLD, 18)); setLayout(new GridLayout(0, 2)); Checkbox box; for(int i=0; i<12; i++) { box = new Checkbox("Checkbox " + i); if (i%2 == 0) { box.setState(true); } add(box); } pack(); setVisible(true); } }
Aug 26
Places a Panel holding 100 buttons in a ScrollPane
import java.applet.Applet; import java.awt.*; /** Places a Panel holding 100 buttons in a ScrollPane that is * too small to hold it. * */ public class ScrollPaneTest extends Applet { public void init() { setLayout(new BorderLayout()); ScrollPane pane = new ScrollPane(); Panel bigPanel = new Panel(); bigPanel.setLayout(new GridLayout(10, 10)); for(int i=0; i<100; i++) { bigPanel.add(new Button("Button " + i)); } pane.add(bigPanel); add(pane, BorderLayout.CENTER); } }
Aug 26
Five buttons arranged by FlowLayout
FlowTest.java ************* FlowTest.java Five buttons arranged by FlowLayout By default, FlowLayout arranges components in rows, left to right, and centered. /././././././././././././ import java.applet.Applet; import java.awt.*; /** FlowLayout puts components in rows. * ************************************ public class FlowTest extends Applet { public void init() { for(int i=1; i<6; i++) { add(new Button("Button " + i)); } } }
Aug 26
A Frame that lets you draw circles with mouse clicks
SavedFrame.java **************** A Frame that lets you draw circles with mouse clicks //************** import java.awt.*; import java.awt.event.*; import java.io.*; /** A Frame that lets you draw circles with mouse clicks * and then save the Frame and all circles to disk. * public class SavedFrame extends CloseableFrame implements ActionListener { /** If a saved version exists, use it. Otherwise create a * new one. */ public static void main(String[] args) { SavedFrame frame; File serializeFile = new File(serializeFilename); if (serializeFile.exists()) { try { FileInputStream fileIn = new FileInputStream(serializeFile); ObjectInputStream in = new ObjectInputStream(fileIn); frame = (SavedFrame)in.readObject(); frame.setVisible(true); } catch(IOException ioe) { System.out.println("Error reading file: " + ioe); } catch(ClassNotFoundException cnfe) { System.out.println("No such class: " + cnfe); } } else { frame = new SavedFrame(); } } private static String serializeFilename ="SavedFrame.ser"; private CirclePanel circlePanel; private Button clearButton, saveButton; /** Build a frame with CirclePanel and buttons. */ public SavedFrame() { super("SavedFrame"); setBackground(Color.white); setFont(new Font("Serif", Font.BOLD, 18)); circlePanel = new CirclePanel(); add("Center", circlePanel); Panel buttonPanel = new Panel(); buttonPanel.setBackground(Color.lightGray); clearButton = new Button("Clear"); saveButton = new Button("Save"); buttonPanel.add(clearButton); buttonPanel.add(saveButton); add(buttonPanel, BorderLayout.SOUTH); clearButton.addActionListener(this); saveButton.addActionListener(this); setSize(300, 300); setVisible(true); } /** If "Clear" clicked, delete all existing circles. If "Save" * clicked, save existing frame configuration (size, * location, circles, etc.) to disk. */ public void actionPerformed(ActionEvent event) { if (event.getSource() == clearButton) { circlePanel.removeAll(); circlePanel.repaint(); } else if (event.getSource() == saveButton) { try { FileOutputStream fileOut = new FileOutputStream("SavedFrame.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(this); out.flush(); out.close(); } catch(IOException ioe) { System.out.println("Error saving frame: " + ioe); } } } } ****************
Aug 26
FrameExample1.java and 2
****************** # FrameExample1.java ****************** import java.awt.*; /** */ public class FrameExample1 { public static void main(String[] args) { Frame f = new Frame("Frame Example 1"); f.setSize(400, 300); f.setVisible(true); } } ********************* # FrameExample2.java ********************* import java.awt.*; /** */ public class FrameExample2 extends Frame { public static void main(String[] args) { new FrameExample2(); } public FrameExample2() { super("Frame Example 2"); setSize(400, 300); setVisible(true); } } **********************
Aug 26
ThreadedRSAKey.java Illustrates converting a method in an existing class from a single-threaded method to a multi-threaded method.
ThreadedRSAKey.java Illustrates converting a method in an existing class from a single-threaded method to a multi-threaded method. In this example, RSAKey computes an RSA public-private key pair, where the key size has a specified number of digits. As large prime numbers require considerable CPU time, ThreadedRSAKey converts the original computeKey method in RSAKey to a multi-threaded method, thus allowing simultaneous (multithreaded) computation of multiple key pairs. Uses the following classes:
import java.io.*; * RSAKey.java Computes RSA public-private key pairs of arbitrary length. * Primes.java Generates large prime numbers. /** An example of creating a background process for an * originally nonthreaded, class method. Normally, * the program flow will wait until computeKey is finished. public class ThreadedRSAKey extends RSAKey implements Runnable { // Store strNumDigits into the thread to prevent race // conditions. public void computeKey(String strNumDigits) { RSAThread t = new RSAThread(this, strNumDigits); t.start(); } // Retrieve the stored strNumDigits and call the original // method. Processing is now done in the background. public void run() { RSAThread t = (RSAThread)Thread.currentThread(); String strNumDigits = t.getStrDigits(); super.computeKey(strNumDigits); } public static void main(String[] args){ ThreadedRSAKey key = new ThreadedRSAKey(); for (int i=0; i " + n); System.out.println("public => " + encrypt); System.out.println("private => " + decrypt); } } * Primes.java Generates large prime numbers. *** import java.math.BigInteger; /** A few utilities to generate a large random BigInteger, * and find the next prime number above a given BigInteger. public class Primes { // Note that BigInteger.ZERO was new in JDK 1.2, and 1.1 // code is being used to support the most servlet engines. private static final BigInteger ZERO = new BigInteger("0"); private static final BigInteger ONE = new BigInteger("1"); private static final BigInteger TWO = new BigInteger("2"); // Likelihood of false prime is less than 1/2^ERR_VAL // Assumedly BigInteger uses the Miller-Rabin test or // equivalent, and thus is NOT fooled by Carmichael numbers. // See section 33.8 of Cormen et al. Introduction to // Algorithms for details. private static final int ERR_VAL = 100; public static BigInteger nextPrime(BigInteger start) { if (isEven(start)) start = start.add(ONE); else start = start.add(TWO); if (start.isProbablePrime(ERR_VAL)) return(start); else return(nextPrime(start)); } private static boolean isEven(BigInteger n) { return(n.mod(TWO).equals(ZERO)); } private static StringBuffer[] digits = { new StringBuffer("0"), new StringBuffer("1"), new StringBuffer("2"), new StringBuffer("3"), new StringBuffer("4"), new StringBuffer("5"), new StringBuffer("6"), new StringBuffer("7"), new StringBuffer("8"), new StringBuffer("9") }; private static StringBuffer randomDigit() { int index = (int)Math.floor(Math.random() * 10); return(digits[index]); } public static BigInteger random(int numDigits) { StringBuffer s = new StringBuffer(""); for(int i=0; i 0) numDigits = Integer.parseInt(args[0]); else numDigits = 150; BigInteger start = random(numDigits); for(int i=0; i<50; i++) { start = nextPrime(start); System.out.println("Prime " + i + " = " + start); } } }
Aug 26
Eight ungrouped buttons in an Applet using FlowLayout
mport java.applet.Applet; import java.awt. *; ************************** /** Eight ungrouped buttons in an Applet using FlowLayout. * */ public class ButtonTest1 extends Applet { public void init() { String[] labelPrefixes = { "Start", "Stop", "Pause", "Resume" }; for (int i=0; i<4; i++) { add(new Button(labelPrefixes[i] + " Thread1")); } for (int i=0; i<4; i++) { add(new Button(labelPrefixes[i] + " Thread2")); } } }