user7547456
user7547456

Reputation:

Java - My action event doesn't work

I'm learning Java and Swing, but my JButton doesn't work.

import javax.swing.JFrame;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Programma {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }

        catch (Exception e){
            e.printStackTrace();
        }


        JFrame frame = new JFrame("DIG");
        JPanel panel = new JPanel();
        JButton button = new JButton("Click Me");

        frame.setSize(400, 400);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        button.setBounds(100, 100, 130, 35);

        panel.add(button);
        frame.add(panel);

        button.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub

                JLabel label = new JLabel("Hello World");
                label.setVisible(true);
                panel.add(label);

            }
        });

    }
}
  1. The frame and button are visible, nut when I click it, the label doesn't appear. How can I fix this?

  2. Do I write this before the other component like JPanel, JButton, etc., or do I write this at the end of code:

    frame.setVisible(true);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

What is the difference ?

By the way, button.setBounds(100, 100, 130, 35) doesn't work, either.

Upvotes: 1

Views: 1426

Answers (2)

Frakcool
Frakcool

Reputation: 11153

I see some issues in your code:

  1. button.setBounds(100, 100, 130, 35); that line will be ignored and you shouldn't be manually be determining the position of the components. See Null layout is evil and Why is it frowned upon to use a null layout in swing? altough you're not using null layout, there is explained why you shouldn't be manually determining the positions of the components.

  2. You're running everything in your program in the main method, that will be hard to maintain later.

  3. You're calling frame.setVisible(true) before you've added all your elements to it, that will cause you random issues.

  4. You're not running your program on the Event Dispatch Thread (EDT), you can solve this by starting your program with the following code, which places it in the EDT. It's recommended as Swing is not thread safe.

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //Your constructor here
            }
        });
    }
    
  5. You're setting the size of the JFrame with setSize(...), instead call frame.pack() and override the getPreferredSize() method of the JPanel.


After all the above has been said, you need to call revalidate() and repaint() on your ActionListener so your program paints its new state.

This program follows all the above recommendations and produces the following outputs (before clicking and after clicking the button 3 times), I on purpose to not make the images so large, made the GUI shorter (200 x 200 instead of 400 x 400)

enter image description here enter image description here

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class Programma {

    private JFrame frame;
    private JPanel panel;
    private JButton button;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Programma().createAndShowGui();
            }
        });
    }

    public void createAndShowGui() {
        frame = new JFrame("DIG");
        panel = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 400);
            }
        };
        button = new JButton("Click Me");

        panel.add(button);

        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JLabel label = new JLabel("Hello World");
                panel.add(label);

                panel.revalidate();
                panel.repaint();
            }
        });

        frame.add(panel);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Do i write this before the other componente like JPanel,JButton... or do i write this at the end of code ?

frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

What is the difference ?

Altough I answered this on the recommendations, the difference is that if you call setVisible before adding all your elements to the frame, then you'll find yourself with some random issues where the components are not all visible until you pass your mouse over them (or where they should be). frame.pack() and setVisible should be the last ones to be called in your program, and frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); can be at the start or the end, it doesn't affects, but I prefer to have it at the end too.

button.setBounds(100, 100, 130, 35); doesn't work too.

Well, that's because of you're using a layout manager (and that's the right way to do your GUIs) instead of a null-layout (which you shouldn't be using anyway) (See point #1).


Edit

What is the difference between frame.setSize(); and frame.setpack() ?

If you read the docs for pack():

Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. The resulting width and height of the window are automatically enlarged if either of dimensions is less than the minimum size as specified by the previous call to the setMinimumSize method.

So, it will calculate the minimum size for your JFrame where all the elements are visible and in their preferred size while setSize will only set the window size, but if you place a JScrollBar inside it for example this will reduce the window size, because of that, that's why you should override the getPreferredSize(...) method of your container, so it will calculate its preferred size including the width of the JScrollBar or some other elements that could modify its size. See Should I avoid the use of setPreferred|Maximum|MinimumSize in Swing? (the general consensus says yes)

Upvotes: 4

Jayesh Doolani
Jayesh Doolani

Reputation: 1233

When you add components dynamically to panel, you need to repain it.

Do this

panel.revalidate(); 

after

panel.add(label);

Upvotes: 0

Related Questions