views:

81

answers:

4

I am new to the whole Java Swing/AWT dialogs (which explains how amateurish this dialog below looks like, any help in arranging it better is welcome :) and I am struggling to close this popUp window when any of the two JButtons are clicked.

I have already tried options like frame.dispose(), frame.setVisible(false) and even SwingUtilities.getWindowAncestor(this).dispose();

Again, this is a secondary popup window invoked by another main process running, so I just want this particular popUp window to close and not affect the main process. Otherwise I could use System.exit

Like I mentioned, any other suggestions to improve the overall look and feel of the dialog are appreciated.

My entire code is as below:

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class UpgradePopupWindow extends JPanel implements ActionListener {
  public static UpgradePopupWindow mainWindow;

  static final long serialVersionUID = 0;

  final String upgrade = "Continue Upgrade";
  final String restore = "Restore";

  JPanel panels;
  JButton flashMe;
  JButton helpMe;
  JTextArea Message;
  JFrame frame;

  protected JTextArea addText(String text, boolean visible, int fontStyle) {
    JTextArea textArea = new JTextArea(text);

    textArea.setFont(new Font("SansSerif", fontStyle, 12)); //$NON-NLS-1$

    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setEditable(false);
    textArea.setForeground(Color.WHITE);
    textArea.setOpaque(false);
    textArea.setVisible(visible);
    textArea.setAlignmentX(Component.CENTER_ALIGNMENT);

    add(textArea);

    return textArea;
  }

  public UpgradePopupWindow(Object ft) {
    String text = "This is the random text for now. I will bother about the actual content later";
    addLabel(text, Font.PLAIN, 12);

    flashMe = new JButton(upgrade);
    flashMe.setActionCommand("upgrade");
    flashMe.addActionListener(this);
    flashMe.setEnabled(true);
    add(flashMe);


    helpMe = new JButton(restore);
    helpMe.setActionCommand("restore");
    helpMe.addActionListener(this);
    helpMe.setEnabled(true);
    add(helpMe);
  }

  protected JLabel addLabel(String text, int fontStyle, int size) {
    JLabel label = new JLabel(text);
    label.setFont(new Font("SansSerif", fontStyle, size)); 
    label.setAlignmentX(Component.CENTER_ALIGNMENT);
    label.setOpaque(false);
    label.setVisible(true);
    label.setForeground(Color.BLUE);

    add(label);
    return label;
  }

  public void createGUI(Object obj) {
    //Create and set up the frame.
    frame = new JFrame("PopUp Dialog");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //create and setup the content pane
    UpgradePopupWindow popUpContentPane = new UpgradePopupWindow(obj);

    popUpContentPane.setOpaque(true);
    frame.setContentPane(popUpContentPane);

    frame.pack();
    frame.setVisible(true);
  }

  public void actionPerformed(ActionEvent e) {
    if("restore".equals(e.getActionCommand())) {
      System.out.println("restore button selected");
      frame.dispose();
      SwingUtilities.getWindowAncestor(this).dispose();
    } else if ("upgrade".equals(e.getActionCommand())) {
      System.out.println("upgrade button selected");
      frame.dispose();
    }
  }
}
+1  A: 

The problem is that your createGUI method is not static. So I imagine you are creating first a UpgradePopupWindow, calling createGUI on that, which in turn creates a enw UpgradePopupWindow.

Try this instead:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TempTest
{
    public static void main(String[] args)
    {
        UpgradePopupWindow.createGUI(null);
    }
}


class UpgradePopupWindow extends JPanel implements ActionListener {
  public static UpgradePopupWindow mainWindow;

  static final long serialVersionUID = 0;

  final String upgrade = "Continue Upgrade";
  final String restore = "Restore";

  JPanel panels;
  JButton flashMe;
  JButton helpMe;
  JTextArea Message;
    JFrame frame;


    protected JTextArea addText(String text, boolean visible, int fontStyle) {
    JTextArea textArea = new JTextArea(text);

    textArea.setFont(new Font("SansSerif", fontStyle, 12)); //$NON-NLS-1$

    textArea.setLineWrap(true);
    textArea.setWrapStyleWord(true);
    textArea.setEditable(false);
    textArea.setForeground(Color.WHITE);
    textArea.setOpaque(false);
    textArea.setVisible(visible);
    textArea.setAlignmentX(Component.CENTER_ALIGNMENT);

    add(textArea);

    return textArea;
  }

  public UpgradePopupWindow(JFrame frm, Object ft2) {
    String text = "This is the random text for now. I will bother about the actual content later";
    addLabel(text, Font.PLAIN, 12);
      frame = frm;
    flashMe = new JButton(upgrade);
    flashMe.setActionCommand("upgrade");
    flashMe.addActionListener(this);
    flashMe.setEnabled(true);
    add(flashMe);


    helpMe = new JButton(restore);
    helpMe.setActionCommand("restore");
    helpMe.addActionListener(this);
    helpMe.setEnabled(true);
    add(helpMe);
  }

  protected JLabel addLabel(String text, int fontStyle, int size) {
    JLabel label = new JLabel(text);
    label.setFont(new Font("SansSerif", fontStyle, size));
    label.setAlignmentX(Component.CENTER_ALIGNMENT);
    label.setOpaque(false);
    label.setVisible(true);
    label.setForeground(Color.BLUE);

    add(label);
    return label;
  }

  public static void createGUI(Object obj) {
    //Create and set up the frame.
    JFrame frame = new JFrame("PopUp Dialog");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //create and setup the content pane
    UpgradePopupWindow popUpContentPane = new UpgradePopupWindow(frame, obj);

    popUpContentPane.setOpaque(true);
    frame.setContentPane(popUpContentPane);

    frame.pack();
    frame.setVisible(true);
  }

  public void actionPerformed(ActionEvent e) {
    if("restore".equals(e.getActionCommand())) {
      System.out.println("restore button selected");
      frame.dispose();
      SwingUtilities.getWindowAncestor(this).dispose();
    } else if ("upgrade".equals(e.getActionCommand())) {
      System.out.println("upgrade button selected");
      frame.dispose();
    }
  }

}

The main change is that the createUI is static, and the UpgradePopupWindow takes the frame in the constructor.

mdma
The mods to have constructor both the Object and the frame as part of the signature helps. But I still dont see the dispose() or SwingUtilities...dispose() working yet. Although, as per one the suggestions, I tried just plain setVisible(false) which just clears the dialog, but does not the dialog exit
LambeauLeap
Not sure why you aren't seeing the frame closed. I actually ran the code and the frame was closed when the button was clicked. Did you copy and paste the code?
mdma
never mind, there were some missing pieces. it works fine now. Thanks again!Btw, do you have any pointers for me in beautifying the generated dialog box. currently it renders the two buttons at the end of the line of text. I am looking at 4line paragraph to replace it and I want the the two buttons to be ideally below that text, with probably a reasonable fixed size window. any comments appreciated.
LambeauLeap
I must admit I'm still prefer my solution which is the same as this one except it doesn't require you to pass in the frame as a parameter when creating the custom panel. Using methods like SwingUtilities.getWindowAncestor(...) are easy ways to make custom components that can be added to any frame and then resolve the frame reference at run time.
camickr
guys, any ideas how and where I can give my dialog a fixed size(dimension). As you might have noticed it looks wonky right now with the two buttons at the end of the sentence. However, when I replaced that line with a short 4line paragraph, the dialog looks even weirder stretching across my entire monitor. Just looking a sensible dialog with a few lines of text below which the two buttons are arranged side by side in a reasonable sized window :(
LambeauLeap
@LambeuLeap - I think you will be best served by creating a new question. Do you know about JOptionPane? This creates multi-line text, with icons and dismiss buttons. If it fits your needs, it might save you a lot of work. Also, the JIDE Common Components library (open source) has various types of popup dialog.
mdma
@camickr - I think it's quite natural for you to prefer and favor your own solution, Getting the ancestor is a nice ancilliary touch, but it's a little abrasive that you write a comment touting your not so humble opinion on the awesomeness of your own solution to me. The both solve the problem at hand.
mdma
@mdma, sorry for being abrasive, I guess I should have added a wink ;), I was attempting to point out to the original poster the subtle difference between the two solutions.
camickr
A: 

The problem is that you have two instances of your UpgradePopupWindow class. First you need to create an instance so you can invoke the createGUI() method. Then in the createGUI method you create another instance of the class. I'm sure is not what you intended.

One solution is to make the createGUI() method static. I removed the "frame" variable from the class and made the following changes:

  public static void createGUI(Object obj) {
    //Create and set up the frame.
    JFrame frame = new JFrame("PopUp Dialog");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //create and setup the content pane
    UpgradePopupWindow popUpContentPane = new UpgradePopupWindow(obj);

    popUpContentPane.setOpaque(true);
    frame.setContentPane(popUpContentPane);

    frame.pack();
    frame.setVisible(true);
  }

  public void actionPerformed(ActionEvent e) {
    if("restore".equals(e.getActionCommand())) {
      System.out.println("restore button selected");
//      frame.dispose();
      SwingUtilities.getWindowAncestor(this).dispose();
    } else if ("upgrade".equals(e.getActionCommand())) {
      System.out.println("upgrade button selected");
//      frame.dispose();
      SwingUtilities.getWindowAncestor(this).dispose();
    }
  }

    public static void main(String[] args)
    {
        UpgradePopupWindow.createGUI(null);
    }
camickr
+2  A: 

Your createGUI() method is a little confused, it creates ANOTHER instance of this class and you end up with one instance with a frame and one instance without. Minimal change to get it working is to change your createGUI method:

  public void createGUI(Object obj) {
    //Create and set up the frame.
    frame = new JFrame("PopUp Dialog");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//    //create and setup the content pane
//    UpgradePopupWindow popUpContentPane = new UpgradePopupWindow(obj);

    setOpaque(true);
    frame.setContentPane(this);

    frame.pack();
    frame.setVisible(true);
  }
jowierun
+1. And, @LambeauLeap: Your close mechanism ought to need nothing more forceful than setVisible, too.
Noel Ang
A: 

Inside the createGUI() method, you're instantiating the frame variable and setting its content pane to another instance of UpgradePopupWindow. But you don't instantiate the frame variable of that second instance. When the Restore or Upgrade buttons are clicked, it is invoking the actionPerformed() method of that second instance, so frame.dispose() and frame.setVisible(false) won't work because frame is null.

I would suggest having your UpgradePopupWindow class extend JFrame instead of JPanel. That way, you can call the dispose() method directly. Plus, it just makes more sense to have one class == one window (a JPanel isn't a window, just a grouping of GUI widgets). Then, create a JPanel in the constructor and add the widgets to that. You can also get rid of that nasty mainWindow static variable.

Also, I don't think JFrame.EXIT_ON_CLOSE is what you want to use here. You want to close the window, not terminate the entire application. JFrame.DISPOSE_ON_CLOSE will dispose just the window when it is closed.

You can also more finely-tune the way your dialog reacts to window events by implementing the WindowListener interface.

The look and feel looks OK to me. Simple and straight forward.

public class Main{
  public static void main(String args[]){
    //display the window from your main window
    UpgradePopupWindow upw = new UpgradePopupWindow(obj);
    upw.setVisible(true);
  }
}

public class UpgradePopupWindow extends JFrame implements ActionListener, WindowListener {
  //...

  public UpgradePopupWindow(Object ft) {
    super("PopUp Dialog");
    JPanel panel = new JPanel();
    //...
    setContentPane(panel);
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    pack();
  }

  public void actionPerformed(ActionEvent e) {
    if("restore".equals(e.getActionCommand())) {
      System.out.println("restore button selected");
      dispose();
    } else if ("upgrade".equals(e.getActionCommand())) {
      System.out.println("upgrade button selected");
      dispose();
    }
  }

  public void windowClosed(WindowEvent e) { 
    System.out.println("Window closed!");
  }
  //other WindowListener methods
}
Michael Angstadt