Yes / No Panel : Panel « Swing Components « Java

Yes / No Panel


 * Copyright (c) 2004 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 3nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose,
 * including teaching and use in open-source projects.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book, 
 * please visit

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Alignment {
  /** This private constructor prevents anyone from instantiating us */
  private Alignment() {

  // The following three constants are the only instances of this class
  public static final Alignment LEFT = new Alignment();

  public static final Alignment CENTER = new Alignment();

  public static final Alignment RIGHT = new Alignment();

 * A custom component that displays multiple lines of text with specified
 * margins and alignment.
class MultiLineLabel extends JComponent {
  // User-specified properties
  protected String label; // The label, not broken into lines

  protected int margin_width; // Left and right margins

  protected int margin_height; // Top and bottom margins

  protected Alignment alignment; // The alignment of the text.

  // Computed state values
  protected int num_lines; // The number of lines

  protected String[] lines; // The label, broken into lines

  protected int[] line_widths; // How wide each line is

  protected int max_width; // The width of the widest line

  protected int line_height; // Total height of the font

  protected int line_ascent; // Font height above baseline

  protected boolean measured = false; // Have the lines been measured?

  // Here are five versions of the constructor.
  public MultiLineLabel(String label, int margin_width, int margin_height, Alignment alignment) {
    this.label = label; // Remember all the properties.
    this.margin_width = margin_width;
    this.margin_height = margin_height;
    this.alignment = alignment;
    newLabel(); // Break the label up into lines.

  public MultiLineLabel(String label, int margin_width, int margin_height) {
    this(label, margin_width, margin_height, Alignment.LEFT);

  public MultiLineLabel(String label, Alignment alignment) {
    this(label, 10, 10, alignment);

  public MultiLineLabel(String label) {
    this(label, 10, 10, Alignment.LEFT);

  public MultiLineLabel() {

  // Methods to set and query the various attributes of the component.
  // Note that some query methods are inherited from the superclass.
  public void setLabel(String label) {
    this.label = label;
    newLabel(); // Break the label into lines.
    repaint(); // Request a redraw.
    measured = false; // Note that we need to measure lines.
    invalidate(); // Tell our containers about this

  public void setAlignment(Alignment a) {
    alignment = a;

  public void setMarginWidth(int mw) {
    margin_width = mw;

  public void setMarginHeight(int mh) {
    margin_height = mh;

  // Override this property setter method because we need to remeasure
  public void setFont(Font f) {
    super.setFont(f); // Tell our superclass about the new font.
    repaint(); // Request a redraw.
    measured = false; // Note that we need to remeasure lines.
    invalidate(); // Tell our containers about new size

  // Property getter methods.
  public String getLabel() {
    return label;

  public Alignment getAlignment() {
    return alignment;

  public int getMarginWidth() {
    return margin_width;

  public int getMarginHeight() {
    return margin_height;

   * This method is called by a layout manager when it wants to know how big
   * we'd like to be.
  public Dimension getPreferredSize() {
    if (!measured)
    return new Dimension(max_width + 2 * margin_width, num_lines * line_height + 2 * margin_height);

   * This method is called when the layout manager wants to know the bare
   * minimum amount of space we need to get by.
  public Dimension getMinimumSize() {
    return getPreferredSize();

   * This method draws the component. Note that it handles the margins and the
   * alignment, but that it doesn't have to worry about the color or font--the
   * superclass takes care of setting those in the Graphics object we're passed.
  public void paintComponent(Graphics g) {
    int x, y;
    Dimension size = this.getSize();
    if (!measured)
    y = line_ascent + (size.height - num_lines * line_height) / 2;
    for (int i = 0; i < num_lines; i++, y += line_height) {
      if (alignment == Alignment.LEFT)
        x = margin_width;
      else if (alignment == Alignment.CENTER)
        x = (size.width - line_widths[i]) / 2;
        x = size.width - margin_width - line_widths[i];
      g.drawString(lines[i], x, y);

   * This internal method breaks a specified label up into an array of lines. It
   * uses the StringTokenizer utility class.
  protected synchronized void newLabel() {
    StringTokenizer t = new StringTokenizer(label, "\n");
    num_lines = t.countTokens();
    lines = new String[num_lines];
    line_widths = new int[num_lines];
    for (int i = 0; i < num_lines; i++)
      lines[i] = t.nextToken();

   * This internal method figures out how the font is, and how wide each line of
   * the label is, and how wide the widest line is.
  protected synchronized void measure() {
    FontMetrics fm = this.getFontMetrics(this.getFont());
    line_height = fm.getHeight();
    line_ascent = fm.getAscent();
    max_width = 0;
    for (int i = 0; i < num_lines; i++) {
      line_widths[i] = fm.stringWidth(lines[i]);
      if (line_widths[i] > max_width)
        max_width = line_widths[i];
    measured = true;

class AnswerEvent extends java.util.EventObject {
  public static final int YES = 0, NO = 1, CANCEL = 2; // Button constants

  protected int id; // Which button was pressed?

  public AnswerEvent(Object source, int id) {
    super(source); = id;

  public int getID() {
    return id;
  } // Return the button

interface AnswerListener extends java.util.EventListener {
  public void yes(AnswerEvent e);

  public void no(AnswerEvent e);

  public void cancel(AnswerEvent e);

 * This JavaBean displays a multi-line message and up to three buttons. It fires
 * an AnswerEvent when the user clicks on one of the buttons
public class YesNoPanel extends JPanel {
  // Properties of the bean.
  protected String messageText; // The message to display

  protected Alignment alignment; // The alignment of the message

  protected String yesLabel; // Text for the yes, no, & cancel buttons

  protected String noLabel;

  protected String cancelLabel;

  // Internal components of the panel
  protected MultiLineLabel message;

  protected JPanel buttonbox;

  protected JButton yes, no, cancel;

  /** The no-argument bean constructor, with default property values */
  public YesNoPanel() {

  public YesNoPanel(String messageText) {
    this(messageText, Alignment.LEFT, "Yes", "No", "Cancel");

  /** A constructor for programmers using this class "by hand" */
  public YesNoPanel(String messageText, Alignment alignment, String yesLabel, String noLabel,
      String cancelLabel) {
    // Create the components for this panel
    setLayout(new BorderLayout(15, 15));

    // Put the message label in the middle of the window.
    message = new MultiLineLabel(messageText, 20, 20, alignment);
    message.setOpaque(false); // allow background color to show through
    add(message, BorderLayout.CENTER);

    // Create a panel for the Panel buttons and put it at the bottom
    // of the Panel. Specify a FlowLayout layout manager for it.
    buttonbox = new JPanel();
    buttonbox.setLayout(new FlowLayout(FlowLayout.CENTER, 25, 15));
    buttonbox.setOpaque(false); // allow background color to show through
    add(buttonbox, BorderLayout.SOUTH);

    // Create each specified button, specifying the action listener
    // and action command for each, and adding them to the buttonbox
    yes = new JButton(); // Create buttons
    no = new JButton();
    cancel = new JButton();
    // Add the buttons to the button box

    // Register listeners for each button
    yes.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        fireEvent(new AnswerEvent(YesNoPanel.this, AnswerEvent.YES));

    no.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        fireEvent(new AnswerEvent(YesNoPanel.this, AnswerEvent.NO));
    cancel.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        fireEvent(new AnswerEvent(YesNoPanel.this, AnswerEvent.CANCEL));

    // Now call property setter methods to set the message and button
    // components to contain the right text

  // Methods to query all of the bean properties.
  public String getMessageText() {
    return messageText;

  public Alignment getAlignment() {
    return alignment;

  public String getYesLabel() {
    return yesLabel;

  public String getNoLabel() {
    return noLabel;

  public String getCancelLabel() {
    return cancelLabel;

  public Font getMessageFont() {
    return message.getFont();

  public Color getMessageColor() {
    return message.getForeground();

  public Font getButtonFont() {
    return yes.getFont();

  // Methods to set all of the bean properties.
  public void setMessageText(String messageText) {
    this.messageText = messageText;

  public void setAlignment(Alignment alignment) {
    this.alignment = alignment;

  public void setYesLabel(String l) {
    yesLabel = l;
    yes.setVisible((l != null) && (l.length() > 0));

  public void setNoLabel(String l) {
    noLabel = l;
    no.setVisible((l != null) && (l.length() > 0));

  public void setCancelLabel(String l) {
    cancelLabel = l;
    cancel.setVisible((l != null) && (l.length() > 0));

  public void setMessageFont(Font f) {

  public void setMessageColor(Color c) {

  public void setButtonFont(Font f) {

  /** This field holds a list of registered ActionListeners. */
  protected List listeners = new ArrayList();

  /** Register an action listener to be notified when a button is pressed */
  public void addAnswerListener(AnswerListener l) {

  /** Remove an Answer listener from our list of interested listeners */
  public void removeAnswerListener(AnswerListener l) {

  /** Send an event to all registered listeners */
  public void fireEvent(AnswerEvent e) {
    // Make a copy of the list and fire the events using that copy.
    // This means that listeners can be added or removed from the original
    // list in response to this event.
    Object[] copy = listeners.toArray();
    for (int i = 0; i < copy.length; i++) {
      AnswerListener listener = (AnswerListener) copy[i];
      switch (e.getID()) {
      case AnswerEvent.YES:
      case AnswerEvent.NO:;
      case AnswerEvent.CANCEL:

  /** A main method that demonstrates the class */
  public static void main(String[] args) {
    // Create an instance of YesNoPanel, with title and message specified:
    YesNoPanel p = new YesNoPanel("Do you really want to quit?");

    // Register an action listener for the Panel. This one just prints
    // the results out to the console.
    p.addAnswerListener(new AnswerListener() {
      public void yes(AnswerEvent e) {

      public void no(AnswerEvent e) {

      public void cancel(AnswerEvent e) {

    JFrame f = new JFrame();


Related examples in the same category

1.Transparent PanelTransparent Panel
2.Swing Panel GroupSwing Panel Group
3.Swing Panel Group 2Swing Panel Group 2
4.Gradient Panel
5.Transfer focus from button to button with help of arrows keys.Transfer focus from button to button with help of arrows keys.
6.A JPanel with a textured background.
7.Time panel shows the current time.
8.Graph Canvas
9.A basic panel that displays a small up or down arrow.
10.HeatMap is a JPanel that displays a 2-dimensional array of data using a selected color gradient scheme.
11.GradientPanel is a class with a gradient background.
12.A simple JPanel with a border and a title
13.Translucent PanelTranslucent Panel
14.Image Panel
15.The class makes it easy to select a numerical value, possibly from a given range