0

I'm trying to close a JFrame from a button on a JPanel which is in my JFrame. I searched around and everything I tried doesn't work.

Here is my code in my JPanel:

public class warningPanel extends JPanel{

    //Klassen
    warning warningClass = new warning();
    loginGeneral loginGen = new loginGeneral();

    //Buttons
    buttons btnOk;

    //JLabels
    JLabel lblText;

    public warningPanel(){
        setLayout(null);

        this.setBounds(0, 0, 300, 150);

        btnOk = new button.buttons(110, 100, 60, 30, "000003006", "120090040", "255255255");
        btnOk.setText("OK");
        btnOk.setFont(new Font("default", Font.BOLD, 12));      

        add(btnOk);


        btnOk.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {                
                warningClass.close();
            }

            public void mouseEntered(MouseEvent e) {
                btnOk.setBackground(loginGen.clGold);
            }

            public void mouseExited(MouseEvent e) {
                btnOk.setBackground(loginGen.clDarkBlue);
            }
        });

    }
}

Then here's my JFrame

public class warning extends JFrame{

    public void warningMessage(String warningtext){

        this.setSize(300, 150);
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        this.setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2);     
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.getContentPane().setBackground(new Color(1, 10, 19));
        this.setUndecorated(true);          

        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);


        warningPanel panel = new warningPanel();
        panel.setOpaque(false);
        panel.setBounds(0, 0, 300, 150);

        this.setVisible(true);
        this.add(panel);
    }       

    public void close(){
        this.setVisible(false);
        this.dispose();
    }

}

I really have no idea why this doesn't work

  • 3
    The instance of warning frame is not the same instance which is been displayed – MadProgrammer Jan 23 '17 at 19:15
  • 1
    You want to use [SwingUtilities.getWindowAncestor](https://docs.oracle.com/javase/8/docs/api/javax/swing/SwingUtilities.html#getWindowAncestor-java.awt.Component-) – MadProgrammer Jan 23 '17 at 19:18
  • 3
    *"Closing JFrame with button inside JPanel"* Why? What's wrong with the little `X` button in the top-right of the window (& that the user is used to)? This reeks of 'the tail wagging the dog' if the panel is the tail and the frame is the dog. – Andrew Thompson Jan 23 '17 at 19:21
  • 1
    Java naming conventions suggest that your class names should be in CamelCase, this makes your code easier to read by others. Null layouts are a bad idea in modern ui design, managing GUI layouts is a complex, difficult and time consuming, this is why there is an existing layout management API, I'd recommend using it – MadProgrammer Jan 23 '17 at 19:22
  • 1
    In relation to Andrews comment, if you want to know when the window is closed, either use a JDialog or WindowListenet – MadProgrammer Jan 23 '17 at 19:23
  • I actually used this to make a custom warning window. Like a JOptionPane with more style. – Mauritz Raes Jan 23 '17 at 19:24
  • I got it working btw, thanks MadProgrammer! – Mauritz Raes Jan 23 '17 at 19:24
  • And @MadProgrammer I appreciate the info. I'm still in high school and I do this for fun, so I can't teach myself everything. – Mauritz Raes Jan 23 '17 at 19:42
  • @MauritzRaes You'd be surprised ;) – MadProgrammer Jan 23 '17 at 19:45
  • 2
    Next time you're working with swing buttons, you may want to look into `ActionListener` or [actions](https://docs.oracle.com/javase/tutorial/uiswing/misc/action.html) as opposed to using `MouseAdapter`. As for teaching yourself everything, I'm completely self taught. Google, Wiki, etc... Learning is pretty simple now a days. Exposure is important, as you can't study something you don't know exists! – Vince Jan 23 '17 at 20:46
  • 1
    1) `setLayout(null);` Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). 2) `this.setSize(300, 150);` If using layouts, `pack()` on the top level container will make the GUI the exact size it needs to be. .. – Andrew Thompson Jan 23 '17 at 20:56
  • .. 3) `this.setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2);` Well `this.setLocationRelativeTo(null);` can achieve that much more easily. 4) Please learn common Java nomenclature (naming conventions - e.g. `EachWordUpperCaseClass`, `firstWordLowerCaseMethod()`, `firstWordLowerCaseAttribute` unless it is an `UPPER_CASE_CONSTANT`) and use it consistently. .. – Andrew Thompson Jan 23 '17 at 20:57
  • .. 5) @VinceEmigh *"Next time you're working with swing buttons, you may want to look into `ActionListener` or actions as opposed to using `MouseAdapter`"* 'Right now' is better than next time. An action listener will respond to both mouse **and** keyboard input. 6) `this.setVisible(true); this.add(panel);` Setting a GUI visible should be done **after** adding all the components. – Andrew Thompson Jan 23 '17 at 20:57

1 Answers1

1

To answer the question:

The instance of warning frame is not the same instance which is been displayed, meaning when you try and close it, it's not the one on the screen.

can't teach myself everything

Okay, a little lesson then ;)

What responsibility does your warningPanel have to close the window (or change the window at all)? None. It's only responsibility is to present information from your program to the user and get information from the user for your program.

I've lost count of the situations where I've developed, had a colleague develop or wanted to use a 3rd party component, which is been presented in a dialog in a large UI and had it contain the "okay" and "cancel" buttons ... well, so much for reuse :P

In most cases, it's not the responsibility of the component (warningPanel in your case) to even deal with these things. Let it focus on the single job it has to do, that's probably hard enough.

So, in your case warningPanel does one job, shows a message...

public class WarningPanel extends JPanel {

    //JLabels
    private JLabel lblText;

    public WarningPanel(String text) {
        setLayout(new GridBagLayout());
        add(new JLabel(text));
    }
}

That's it.

Every now and again, I might have a special case, where it's obvious that the panel should be shown in a dialog, when this occurs, I usually provide some utility method to generate the dialog and wrap up the management into a simple to use method, for example...

public class WarningPanel extends JPanel {

    //JLabels
    private JLabel lblText;

    public WarningPanel(String text) {
        setLayout(new GridBagLayout());
        add(new JLabel(text));
    }

    public enum DialogAction {
        OK, CANCEL, CLOSED
    }

    public static DialogAction showDialog(JComponent parent, String title, String message) {
        JDialog dialog = new JDialog(parent == null ? null : SwingUtilities.windowForComponent(parent));
        dialog.setTitle(title);
        WarningPanel pane = new WarningPanel(message);
        pane.setBorder(new EmptyBorder(4, 4, 4, 4));
        dialog.add(pane);

        JPanel buttonPane = new JPanel(new GridBagLayout());
        buttonPane.setBorder(new EmptyBorder(4, 4, 4, 4));

        State state = new State();

        JButton okBtn = new JButton("Ok");
        JButton cancelBtn = new JButton("Cancel");

        buttonPane.add(okBtn);
        buttonPane.add(cancelBtn);

        dialog.add(buttonPane, BorderLayout.SOUTH);

        DialogAction action = DialogAction.CLOSED;

        okBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                state.setState(DialogAction.OK);
                dialog.dispose();
            }
        });
        cancelBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                state.setState(DialogAction.CANCEL);
                dialog.dispose();
            }
        });

        dialog.pack();
        dialog.setLocationRelativeTo(parent);
        dialog.setVisible(true);

        return state.getState();
    }
}

Which allows you to use it something like this...

switch (WarningPanel.showDialog(null, "Warning", "Something wicked this way comes")) {
    case OK:
        // Everything is okay
        break;
    case CANCEL:
        // User cancelled
    case CLOSED:
        // Window was closed
        break;

}

Now, this is a demonstration of an idea, personally, I typically fall back to JOptionPane as it basically does the same thing

You might want to have a look at:

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366