0

so I've found multiple ways of implementing a swing GUI in java but don't know what each does and my teacher isn't able to help me. One method of creating a JFrame is:

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

public class UI extends JFrame{

    public UI() {

        initaliseGUI();
    }

    private void initaliseGUI(){
        setTitle("My Title");
        setBackground(Color.red);
        setSize(800,500);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);



}
public static void main(String[] args){
    EventQueue.invokeLater(new Runnable(){

        @Override
        public void run(){
            UI M = new UI();
            M.setVisible(true);

        }   
    }); 
}

But another way of implementing it is:

import javax.swing.*;
import java.awt.*;
public class Main{
    public static void main(String[] args){

        JFrame window = new JFrame();
        window.setSize(500,500);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container c = window.getContentPane();
        c.setBackground(Color.red); 
        window.setBackground(Color.red);        
        window.setTitle("main");
        JLabel message = new JLabel("JLabel");
        window.add(message);
        window.setVisible(true);
    }
}

what is the difference between how each one works and when should I use one over the other and how does the runnable work in this context?

thankyou!

Jack
  • 1
  • 2
  • It looks like you need to study the difference between an `interface` and a `class`. – Code-Apprentice Feb 02 '16 at 23:18
  • @jheimbouch There are more differences than just the `invokeLater()`. I think the more fundamental difference is between extending `JFrame` and creating the `JFrame` in `main()` (or a thread initialized in `main()`). – Code-Apprentice Feb 02 '16 at 23:19
  • Personally I prefer extending `JFrame` and creating my UI elements in a constructor rather than setting up everything from `main()` directly. – Code-Apprentice Feb 02 '16 at 23:20
  • 1
    @Jack usually it is preferred not to extends a JFrame, but a container like JPanel. We seldom need a customized JFrame and of course there are dozen other reasons for not doing so. Take a look at here: http://stackoverflow.com/questions/22003802/extends-jframe-vs-creating-it-inside-the-the-program – user3437460 Feb 02 '16 at 23:27
  • Histroically, some swing based apps were causing thread deadlocks (way back in the early days), the Swing engineers simple said, use EventQueue.invokeLater to make sure the code is started in the EDT, which solved these problems. Generally speaking, you don't know when a component might become display able or start responding to events from the EDT, so you need to get your code into the EDT – MadProgrammer Feb 02 '16 at 23:55
  • 2
    As general rule of thumb, you should avoid extending from top level containers like JFrame for a number of reasons, you're not actually adding any new features to the class, you're locking you're self into a single use case, reducing the reusability of your class and a few others. Instead star with a JPanel and simply add that to what ever container you want. As a general concept, you should look up composition over inheritance – MadProgrammer Feb 03 '16 at 00:01

1 Answers1

2

Your first example calls the EventQueue invokeLater method, but extends a JFrame.

Your second example puts everything in the static method main, and doesn't run the invokeLater method.

Here's one way I start a Swing application.

public class TryingProject2 implements Runnable {

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

    @Override
    public void run() {
        JFrame frame = new JFrame("Color Gradient Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createMainPanel());
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createMainPanel() {
        JPanel panel = new JPanel();
        // Add your Swing components here
        return panel;
    }
}

I don't extends Swing components. I use Swing components. The only time you extend a Swing component, or any Java class, is when you want to override one of the class methods.

The SwingUtilities invokeLater method is the same as the EventQueue invokeLater method. This method puts the creation and updates of all Swing components on the Event Dispatch thread.

I implement Runnable because it makes the invokeLater method parameter an instance of the class.

I create the main panel in a method to keep the JFrame code separate from the JPanel(s) code.

Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111