1

My program is supposed to launch a second JFrame and print a statement when the button is clicked, but it always launches three JFrames and prints three statements. I need it to only print out one statement and launch one Jframe. Here is the code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

@SuppressWarnings("serial")
public class Test extends JPanel implements ActionListener {
    JButton button = new JButton();
    String buttonString = "Buttontext";

    public Test() {
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        button.setText("Buttontext");
        button.setCursor(Cursor.getDefaultCursor());
        button.setMargin(new Insets(0, 0, 0, 0));
        button.setBounds(700, 400, 100, 20);
        button.setActionCommand(buttonString);
        button.addActionListener(this);
        this.add(button);
    }

    public static void createandshowGUI() {
        JFrame frame = new JFrame("Frame");
        frame.getContentPane().setBackground(Color.white);
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        frame.setSize(dim.width, dim.height);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new Test());
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createandshowGUI();
            }
        });
    }

    public void actionPerformed(ActionEvent e) {
        if (buttonString.equals(e.getActionCommand())) {
            System.out.println("creating a new frame");
            newframe();
        }
    }

    public void newframe() {
        JFrame frame2 = new JFrame();
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        frame2.setSize(dim.width / 2, dim.height / 2);
        frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame2.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame2.setVisible(true);
    }
}
hpopiolkiewicz
  • 3,281
  • 4
  • 24
  • 36

4 Answers4

2

You keep adding an ActionListener to your button in your paintComponent(Graphics) method. That means each time this method is invoked, you add another ActionListener to your button. Therefore, each time the button is pressed, it will do the same thing however many times that method is invoked before you press the button.

Josh M
  • 11,611
  • 7
  • 39
  • 49
2

First see The Use of Multiple JFrames, Good/Bad Practice? - The popular answer here is BAD.

A much cleaner approach would be to use CardLayout to switch between different JPanels. The below runnable example can be see here. Also see How to Use CardLayout

enter image description here


Another approach is to use a modal JDialog. The below runnable example can be seen here. Also see How to Use Make Dialogs

enter image description here

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
2

paintComponent() is called every time the panel is asked to paint itself. That request happens for a lot of reasons - including repainting the panel if another window has moved on top of it, or if the panel is resized. Any code in paintComponent() should only be used for painting the component.

So, this is not the right place for button.addActionListener(). In fact, all of your button code, including this.add(button), should happen somewhere else, probably in createandshowGUI.

Your program does not need to override paintComponent(). You can rely on a JPanel to paint all of the components that have been added to it (in fact, super.paintComponent() does exactly that). You only need to override paintComponent() if you're doing something unique in drawing the panel (for example, putting a background image in the panel). In your case, you just have to add the button to the panel and you're done.

David Koelle
  • 20,726
  • 23
  • 93
  • 130
0

If you want to create multiple windows, use a JDesktopPane. Add JInternalFrames to them as needed. That way you will have a single, top-level window with child windows inside.

An SO User
  • 24,612
  • 35
  • 133
  • 221