Dialog with list control - Java Swing

Java examples for Swing:JDialog

Description

Dialog with list control

Demo Code

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;

/**//from w  ww .j a va  2s . com
 * A 1.4 application that brings up a ListDialog.
 */
public class Main {
  static JFrame frame;
  static String[] names = { "Arlo", "Cosmo", "Elmo", "Hugo", "Jethro",
      "Laszlo", "Milo", "Nemo", "Otto", "Ringo", "Rocco", "Rollo" };

  public static JPanel createUI() {
    // Create the labels.
    JLabel intro = new JLabel("The chosen name:");
    final JLabel name = new JLabel(names[1]);
    intro.setLabelFor(name);

    // Use a wacky font if it exists. If not, this falls
    // back to a font we know exists.
    name.setFont(getAFont());

    // Create the button.
    final JButton button = new JButton("Pick a new name...");
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String selectedName = ListDialog.showDialog(frame, button,
            "Baby names ending in O:", "Name Chooser", names, name.getText(),
            "Cosmo  ");
        name.setText(selectedName);
      }
    });

    // Create the panel we'll return and set up the layout.
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
    panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 10, 20));
    intro.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    name.setAlignmentX(JComponent.CENTER_ALIGNMENT);
    button.setAlignmentX(JComponent.CENTER_ALIGNMENT);

    // Add the labels to the content pane.
    panel.add(intro);
    panel.add(Box.createVerticalStrut(5)); // extra space
    panel.add(name);

    // Add a vertical spacer that also guarantees us a minimum width:
    panel.add(Box.createRigidArea(new Dimension(150, 10)));

    // Add the button.
    panel.add(button);

    return panel;
  }

  /**
   * Finds a cursive font to use, or falls back to using an italic serif font.
   */
  protected static Font getAFont() {
    // initial strings of desired fonts
    String[] desiredFonts = { "French Script", "FrenchScript", "Script" };

    String[] existingFamilyNames = null; // installed fonts
    String fontName = null; // font we'll use

    // Search for all installed font families. The first
    // call may take a while on some systems with hundreds of
    // installed fonts, so if possible execute it in idle time,
    // and certainly not in a place that delays painting of
    // the UI (for example, when bringing up a menu).
    //
    // In systems with malformed fonts, this code might cause
    // serious problems; use the latest JRE in this case. (You'll
    // see the same problems if you use Swing's HTML support or
    // anything else that searches for all fonts.) If this call
    // causes problems for you under the latest JRE, please let
    // us know.
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    if (ge != null) {
      existingFamilyNames = ge.getAvailableFontFamilyNames();
    }

    // See if there's one we like.
    if ((existingFamilyNames != null) && (desiredFonts != null)) {
      int i = 0;
      while ((fontName == null) && (i < desiredFonts.length)) {

        // Look for a font whose name starts with desiredFonts[i].
        int j = 0;
        while ((fontName == null) && (j < existingFamilyNames.length)) {
          if (existingFamilyNames[j].startsWith(desiredFonts[i])) {

            // We've found a match. Test whether it can display
            // the Latin character 'A'. (You might test for
            // a different character if you're using a different
            // language.)
            Font f = new Font(existingFamilyNames[j], Font.PLAIN, 1);
            if (f.canDisplay('A')) {
              fontName = existingFamilyNames[j];
              System.out.println("Using font: " + fontName);
            }
          }

          j++; // Look at next existing font name.
        }
        i++; // Look for next desired font.
      }
    }

    // Return a valid Font.
    if (fontName != null) {
      return new Font(fontName, Font.PLAIN, 36);
    } else {
      return new Font("Serif", Font.ITALIC, 36);
    }
  }

  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    // Create and set up the window.
    frame = new JFrame("Name That Baby");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // Create and set up the content pane.
    JComponent newContentPane = createUI();
    newContentPane.setOpaque(true); // content panes must be opaque
    frame.setContentPane(newContentPane);

    // Display the window.
    frame.pack();
    frame.setVisible(true);
  }

  public static void main(String[] args) {
    // Schedule a job for the event-dispatching thread:
    // creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}

/*
 * ListDialog.java is meant to be used by programs such as ListDialogRunner. It
 * requires no additional files.
 */

/**
 * Use this modal dialog to let the user choose one string from a long list. See
 * ListDialogRunner.java for an example of using ListDialog. The basics:
 * 
 * <pre>
 * String[] choices = { &quot;A&quot;, &quot;long&quot;, &quot;array&quot;, &quot;of&quot;, &quot;strings&quot; };
 * String selectedName = ListDialog.showDialog(componentInControllingFrame,
 *     locatorComponent, &quot;A description of the list:&quot;, &quot;Dialog Title&quot;, choices,
 *     choices[0]);
 * </pre>
 */
class ListDialog extends JDialog implements ActionListener {
  private static ListDialog dialog;
  private static String value = "";
  private JList list;

  /**
   * Set up and show the dialog. The first Component argument determines which
   * frame the dialog depends on; it should be a component in the dialog's
   * controlling frame. The second Component argument should be null if you want
   * the dialog to come up with its left corner in the center of the screen;
   * otherwise, it should be the component on top of which the dialog should
   * appear.
   */
  public static String showDialog(Component frameComp, Component locationComp,
      String labelText, String title, String[] possibleValues,
      String initialValue, String longValue) {
    Frame frame = JOptionPane.getFrameForComponent(frameComp);
    dialog = new ListDialog(frame, locationComp, labelText, title,
        possibleValues, initialValue, longValue);
    dialog.setVisible(true);
    return value;
  }

  private void setValue(String newValue) {
    value = newValue;
    list.setSelectedValue(value, true);
  }

  private ListDialog(Frame frame, Component locationComp, String labelText,
      String title, Object[] data, String initialValue, String longValue) {
    super(frame, title, true);

    // Create and initialize the buttons.
    JButton cancelButton = new JButton("Cancel");
    cancelButton.addActionListener(this);
    //
    final JButton setButton = new JButton("Set");
    setButton.setActionCommand("Set");
    setButton.addActionListener(this);
    getRootPane().setDefaultButton(setButton);

    // main part of the dialog
    list = new JList(data) {
      // Subclass JList to workaround bug 4832765, which can cause the
      // scroll pane to not let the user easily scroll up to the beginning
      // of the list. An alternative would be to set the unitIncrement
      // of the JScrollBar to a fixed value. You wouldn't get the nice
      // aligned scrolling, but it should work.
      public int getScrollableUnitIncrement(Rectangle visibleRect,
          int orientation, int direction) {
        int row;
        if (orientation == SwingConstants.VERTICAL && direction < 0
            && (row = getFirstVisibleIndex()) != -1) {
          Rectangle r = getCellBounds(row, row);
          if ((r.y == visibleRect.y) && (row != 0)) {
            Point loc = r.getLocation();
            loc.y--;
            int prevIndex = locationToIndex(loc);
            Rectangle prevR = getCellBounds(prevIndex, prevIndex);

            if (prevR == null || prevR.y >= r.y) {
              return 0;
            }
            return prevR.height;
          }
        }
        return super.getScrollableUnitIncrement(visibleRect, orientation,
            direction);
      }
    };

    list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    if (longValue != null) {
      list.setPrototypeCellValue(longValue); // get extra space
    }
    list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
    list.setVisibleRowCount(-1);
    list.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) {
          setButton.doClick(); // emulate button click
        }
      }
    });
    JScrollPane listScroller = new JScrollPane(list);
    listScroller.setPreferredSize(new Dimension(250, 80));
    listScroller.setAlignmentX(LEFT_ALIGNMENT);

    // Create a container so that we can add a title around
    // the scroll pane. Can't add a title directly to the
    // scroll pane because its background would be white.
    // Lay out the label and scroll pane from top to bottom.
    JPanel listPane = new JPanel();
    listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
    JLabel label = new JLabel(labelText);
    label.setLabelFor(list);
    listPane.add(label);
    listPane.add(Box.createRigidArea(new Dimension(0, 5)));
    listPane.add(listScroller);
    listPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

    // Lay out the buttons from left to right.
    JPanel buttonPane = new JPanel();
    buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
    buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
    buttonPane.add(Box.createHorizontalGlue());
    buttonPane.add(cancelButton);
    buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
    buttonPane.add(setButton);

    // Put everything together, using the content pane's BorderLayout.
    Container contentPane = getContentPane();
    contentPane.add(listPane, BorderLayout.CENTER);
    contentPane.add(buttonPane, BorderLayout.PAGE_END);

    // Initialize values.
    setValue(initialValue);
    pack();
    setLocationRelativeTo(locationComp);
  }

  // Handle clicks on the Set and Cancel buttons.
  public void actionPerformed(ActionEvent e) {
    if ("Set".equals(e.getActionCommand())) {
      ListDialog.value = (String) (list.getSelectedValue());
    }
    ListDialog.dialog.setVisible(false);
  }
}

/*
 * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle or the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

Related Tutorials