Page 1 of 1

Basic GUI tutorial in Java null layout Rate Topic: ***** 2 Votes

#1 alpha02  Icon User is offline

  • Sexy DIC God
  • member icon

Reputation: 47
  • View blog
  • Posts: 803
  • Joined: 20-May 06

Posted 17 January 2007 - 05:14 PM

*
POPULAR

Introduction

Making GUIs in Java can be quite difficult. Some prefer to use layouts such as BoxLayout, SpringLayout, and more (I will focus in this later). If you are not familiar with these ones, or if you want a really personalized layout, I recommend using the null layout. I will focus on this one in this tutorial. From now on, I assume you have some basic knowledge about Java.

Comparing the layouts

Here are the basic layouts and how they work:

BoxLayout: The components are aligned horizontally.
FlowLayout: The components are aligned vertically.
GridLayout: The components are placed in a grid.
GridBagLayout: More elaborate form of GridLayout. The components are in a grid, but with constraints.
SpringLayout: The components are placed using relationships between all parts.

I am passing some. As you figured out, a bunch of layouts are available and do different things. But how about using the null one? Although absolute positonning may be a problem, it's easy to program your form so the components resize or move. Using this layout, I build a form with resizing bars to adjust the GUI! All is possible, let's dig in!

Creating our form

First of all, we need to create our JFrame. This is simply the window. In this tutorial, we will use a file called gui1.java, so adapt the code for your file. Anyway, here's the basic code:

//Import packages
import javax.swing.*;
import java.awt.*;

//Main class
public class gui1{
	//Declare variables
	static JFrame frame1;
	static Container pane;
	static JButton btnConnect, btnDisconnect;
	static JLabel lblServer, lblUsername, lblPassword, lblPort;
	static JTextField txtServer, txtUsername, txtPassword, txtPort;
	static Insets insets;

	public static void main (String args[]){
		//Create the frame
		frame1 = new JFrame ("Sample GUI Application");
		//Set its size to 800x200 pixels
		frame1.setSize (800,200);
		//Prepare panel
		pane = frame1.getContentPane();
		insets = pane.getInsets();
		//Apply the null layout
		pane.setLayout (null);
	}
}



First, we need to import the Swing and AWT packages, which will be used in our GUI. We start by creating the frame. The constructor takes a string as a parameter, which will be the title of the frame (window). We resize it, and we apply the null layout to it. It is important you fully understand the above code before proceeding.

Creating the controls

We declared the controls, but we did not create them! Don't worry, it's much easier than you think. It is done the same way than in any layout. Look at the code:

btnConnect = new JButton ("Connect");
btnDisconnect = new JButton ("Disconnect");
lblServer = new JLabel ("Remote host:");
lblUsername = new JLabel ("Username:");
lblPassword = new JLabel ("Password:");
lblPort = new JLabel ("Port #:");
txtServer = new JTextField (10);
txtUsername = new JTextField  (10);
txtPassword = new JTextField  (10);
txtPort = new JTextField  (5);


The components are now created. Let's take a look at the constructors:
JButton: String, the text on the button.
JLabel: String, the text on the label.
JTextField: Integer, the size of the text field in characters. This has no influence on the maximum number of characters the user can input.

Note that for a password field you can use JPasswordField, but to keep things simple we will use JTextField.

Creating and placing a component

Placing a component is much easier in the null layout than in any other one. We, of course, add it to the panel, and then we call the method setBounds (x,y,width,height) of this component. We will start by placing the server label:

pane.add (lblServer); //Add component to panel
lblServer.setBounds (insets.left + 5, insets.top + 5, lblServer.getPreferredSize().width, lblServer.getPreferredSize().height);


This may seem complicated, but it is not. First, the pane.add instruction just puts the label in the panel, and the lblServer.setBounds places it. Let's take a look at its parameters:
1) X: The position on the X axis of the component. Remember, insets contains the coordinates of the pane's bounds. We place it at (insets+5), 5 pixels right from the left border.
2) Y: The position on the Y axis of the component. Here we specify 5 pixels down from the top of the pane.
3) Width: The width, in pixels, of the component. The getPreferredSize() method returns an object with the coordinates of its initial size.
4) Height: The height, in pixels, of the component. We do not modify its height as you can see.

Before we continue, you need to understand some other methods used to retrieve coordinates: getX(), getY(), getWidth() and getHeight(). They all return an integer. We will use them later. Make sure you understand all the previous stuff before proceeding.

Placing all components

Now that you know how to place a component, I will show you the full code to place them:

//Add all components to panel
pane.add (lblServer);
pane.add (lblUsername);
pane.add (lblPassword);
pane.add (lblPort);
pane.add (txtServer);
pane.add (txtUsername);
pane.add (txtPassword);
pane.add (txtPort);
pane.add (btnConnect);
pane.add (btnDisconnect);

//Place all components
lblServer.setBounds (insets.left + 5, insets.top + 5, lblServer.getPreferredSize().width, lblServer.getPreferredSize().height);
txtServer.setBounds (lblServer.getX() + lblServer.getWidth() + 5, insets.top + 5, txtServer.getPreferredSize().width, txtServer.getPreferredSize().height);

lblUsername.setBounds (txtServer.getX() + txtServer.getWidth() + 5, insets.top + 5, lblUsername.getPreferredSize().width, lblUsername.getPreferredSize().height);
txtUsername.setBounds (lblUsername.getX() + lblUsername.getWidth() + 5, insets.top + 5, txtUsername.getPreferredSize().width, txtUsername.getPreferredSize().height);

lblPassword.setBounds (txtUsername.getX() + txtUsername.getWidth() + 5, insets.top + 5, lblPassword.getPreferredSize().width, lblPassword.getPreferredSize().height);
txtPassword.setBounds (lblPassword.getX() + lblPassword.getWidth() + 5, insets.top + 5, txtPassword.getPreferredSize().width, txtPassword.getPreferredSize().height);

lblPort.setBounds (txtPassword.getX() + txtPassword.getWidth() + 5, insets.top + 5, lblPort.getPreferredSize().width, lblPort.getPreferredSize().height);
txtPort.setBounds (lblPort.getX() + lblPort.getWidth() + 5, insets.top + 5, txtPort.getPreferredSize().width, txtPort.getPreferredSize().height);

btnConnect.setBounds (txtPort.getX() + txtPort.getWidth() + 5, insets.top + 5, btnConnect.getPreferredSize().width, btnConnect.getPreferredSize().height);

//Place disconnect button (start a new line!)
btnDisconnect.setBounds (insets.left + 15, lblServer.getY() + lblServer.getHeight() + 5, btnDisconnect.getPreferredSize().width, btnDisconnect.getPreferredSize().height);


This used only methods you already know, there is nothing new here.

Finishing the layout

We are almost finished. If you run the program now, nothing shows. We need a last line:

frame1.setVisible (true);


Now run the program. All controls are placed! However, the Java default style is used. It is different depending on your version of JVM (Java Virtual Machine). To use the correct style, we must use Look and Feel.

Look and Feel

Look and Feel, also known as L&F, sets the style of your form to the one of your operating system. Don't forget that Java is cross-platform! This way, Windows users will have the Windows style, and Mac OS users will have their own style. Put these lines in your code:

//Set Look and Feel
try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}
catch (ClassNotFoundException e) {}
catch (InstantiationException e) {}
catch (IllegalAccessException e) {}
catch (UnsupportedLookAndFeelException e) {}


This does all the job. Now what about actions and getting the input from the GUI? This is not quite a hard thing, so let's give it a shot:

Registering actions

Import the package java.awt.event.*, it will be used (I assume you know how to import a package). Now, we must add an action to the Connect button to make it do something. Use:

btnConnect.addActionListener(new btnConnectAction()); //Register action


The addActionListener method takes a ActionListener as a parameter. We must create a class which will inherit all attributes from that superclass:

public static class btnConnectAction implements ActionListener{

}


Since we create an interface (with the "implements" keyword), we absolutly need to create some methods inherited from the super interface:

public static class btnConnectAction implements ActionListener{
	public void actionPerformed (ActionEvent e){
		//Do something..
	}
}


Add any instructions you want in that method, they will be executed when you will click the button. Example, if you want to know what the user entered in the User name field, use:

public static class btnConnectAction implements ActionListener{
	public void actionPerformed (ActionEvent e){
		System.out.println("You entered "+txtUsername.getText());
	}
}


Feel free to explore the methods of the text fields, radio buttons, checkboxes, and more to find out how you can get user input. It is often a simple thing.

Putting it all together

If you followed this tutorial correcty, you should have this:

//Import packages
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

//Main class
public class gui1{
	//Declare variables
	static JFrame frame1;
	static Container pane;
	static JButton btnConnect, btnDisconnect;
	static JLabel lblServer, lblUsername, lblPassword, lblPort;
	static JTextField txtServer, txtUsername, txtPassword, txtPort;
	static Insets insets;

	public static void main (String args[]){
		//Set Look and Feel
		try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}
		catch (ClassNotFoundException e) {}
		catch (InstantiationException e) {}
		catch (IllegalAccessException e) {}
		catch (UnsupportedLookAndFeelException e) {}

		//Create the frame
		frame1 = new JFrame ("Sample GUI Application");
		frame1.setSize (800,200);
		pane = frame1.getContentPane();
		insets = pane.getInsets();
		pane.setLayout (null);

		//Create controls
		btnConnect = new JButton ("Connect");
		btnDisconnect = new JButton ("Disconnect");
		lblServer = new JLabel ("Remote host:");
		lblUsername = new JLabel ("Username:");
		lblPassword = new JLabel ("Password:");
		lblPort = new JLabel ("Port #:");
		txtServer = new JTextField (10);
		txtUsername = new JTextField  (10);
		txtPassword = new JTextField  (10);
		txtPort = new JTextField  (5);

		//Add all components to panel
		pane.add (lblServer);
		pane.add (lblUsername);
		pane.add (lblPassword);
		pane.add (lblPort);
		pane.add (txtServer);
		pane.add (txtUsername);
		pane.add (txtPassword);
		pane.add (txtPort);
		pane.add (btnConnect);
		pane.add (btnDisconnect);

		//Place all components
		lblServer.setBounds (insets.left + 5, insets.top + 5, lblServer.getPreferredSize().width, lblServer.getPreferredSize().height);
		txtServer.setBounds (lblServer.getX() + lblServer.getWidth() + 5, insets.top + 5, txtServer.getPreferredSize().width, txtServer.getPreferredSize().height);
		lblUsername.setBounds (txtServer.getX() + txtServer.getWidth() + 5, insets.top + 5, lblUsername.getPreferredSize().width, lblUsername.getPreferredSize().height);
		txtUsername.setBounds (lblUsername.getX() + lblUsername.getWidth() + 5, insets.top + 5, txtUsername.getPreferredSize().width, txtUsername.getPreferredSize().height);
		lblPassword.setBounds (txtUsername.getX() + txtUsername.getWidth() + 5, insets.top + 5, lblPassword.getPreferredSize().width, lblPassword.getPreferredSize().height);
		txtPassword.setBounds (lblPassword.getX() + lblPassword.getWidth() + 5, insets.top + 5, txtPassword.getPreferredSize().width, txtPassword.getPreferredSize().height);
		lblPort.setBounds (txtPassword.getX() + txtPassword.getWidth() + 5, insets.top + 5, lblPort.getPreferredSize().width, lblPort.getPreferredSize().height);
		txtPort.setBounds (lblPort.getX() + lblPort.getWidth() + 5, insets.top + 5, txtPort.getPreferredSize().width, txtPort.getPreferredSize().height);
		btnConnect.setBounds (txtPort.getX() + txtPort.getWidth() + 5, insets.top + 5, btnConnect.getPreferredSize().width, btnConnect.getPreferredSize().height);
		btnDisconnect.setBounds (insets.left + 15, lblServer.getY() + lblServer.getHeight() + 5, btnDisconnect.getPreferredSize().width, btnDisconnect.getPreferredSize().height);

		//Set frame visible
		frame1.setVisible (true);

		//Button's action
		btnConnect.addActionListener(new btnConnectAction()); //Register action
	}

	public static class btnConnectAction implements ActionListener{
		public void actionPerformed (ActionEvent e){
			System.out.println("You entered "+txtUsername.getText());
		}
	}
}


Run the program. Everything should be fine.

Conclusion

Java is a powerful language, and therefore it can create impressive GUIs. I recommend using the null layout, it is not harder than the others and you can create really nice things. I managed to make splitter bars to move all parts of my GUI, and it works fine! If you have questions, do not hesitate to contact me!

This post has been edited by JackOfAllTrades: 20 January 2011 - 03:33 PM
Reason for edit:: Incorporated feedback from post #9


Is This A Good Question/Topic? 10
  • +

Replies To: Basic GUI tutorial in Java

#2 Shinilolz  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 8
  • View blog
  • Posts: 238
  • Joined: 30-November 06

Posted 24 January 2007 - 01:00 PM

Very nice, it helps :)
Was This Post Helpful? 0
  • +
  • -

#3 Snooty_Head  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 15-February 07

Posted 07 September 2007 - 11:11 AM

Very nice, easy to follow tutorial. Although, I'm getting a "void is an invalid type for the variable main" error, and a "Syntax error on token ")", ; expected" on the same line. I put the code together as follows:

//Import packages
import javax.swing.*;
import java.awt.*;

//Main class
public class gui1{
	//Declare variables
	JFrame frame1;
	Container pane;
	JButton btnConnect, btnDisconnect;
	JLabel lblServer, lblUsername, lblPassword, lblPort;
	JTextField txtServer, txtUsername, txtPassword, txtPort;
	Insets insets;
	{
	
	btnConnect = new JButton ("Connect");
	btnDisconnect = new JButton ("Disconnect");
	lblServer = new JLabel ("Remote host:");
	lblUsername = new JLabel ("Username:");
	lblPassword = new JLabel ("Password:");
	lblPort = new JLabel ("Port #:");
	txtServer = new JTextField (10);
	txtUsername = new JTextField  (10);
	txtPassword = new JTextField  (10);
	txtPort = new JTextField  (5);
	
//  Add all components to panel
	pane.add (lblServer);
	pane.add (lblUsername);
	pane.add (lblPassword);
	pane.add (lblPort);
	pane.add (txtServer);
	pane.add (txtUsername);
	pane.add (txtPassword);
	pane.add (txtPort);
	pane.add (btnConnect);
	pane.add (btnDisconnect);

//	Place all components
	lblServer.setBounds (insets.left + 5, insets.top + 5, lblServer.getPreferredSize().width, lblServer.getPreferredSize().height);
	txtServer.setBounds (lblServer.getX() + lblServer.getWidth() + 5, insets.top + 5, txtServer.getPreferredSize().width, txtServer.getPreferredSize().height);

	lblUsername.setBounds (txtServer.getX() + txtServer.getWidth() + 5, insets.top + 5, lblUsername.getPreferredSize().width, lblUsername.getPreferredSize().height);
	txtUsername.setBounds (lblUsername.getX() + lblUsername.getWidth() + 5, insets.top + 5, txtUsername.getPreferredSize().width, txtUsername.getPreferredSize().height);

	lblPassword.setBounds (txtUsername.getX() + txtUsername.getWidth() + 5, insets.top + 5, lblPassword.getPreferredSize().width, lblPassword.getPreferredSize().height);
	txtPassword.setBounds (lblPassword.getX() + lblPassword.getWidth() + 5, insets.top + 5, txtPassword.getPreferredSize().width, txtPassword.getPreferredSize().height);

	lblPort.setBounds (txtPassword.getX() + txtPassword.getWidth() + 5, insets.top + 5, lblPort.getPreferredSize().width, lblPort.getPreferredSize().height);
	txtPort.setBounds (lblPort.getX() + lblPort.getWidth() + 5, insets.top + 5, txtPort.getPreferredSize().width, txtPort.getPreferredSize().height);

	btnConnect.setBounds (txtPort.getX() + txtPort.getWidth() + 5, insets.top + 5, btnConnect.getPreferredSize().width, btnConnect.getPreferredSize().height);

//	Place disconnect button (start a new line!)
	btnDisconnect.setBounds (insets.top + 15, lblServer.getY() + lblServer.getHeight() + 5, btnDisconnect.getPreferredSize().width, btnDisconnect.getPreferredSize().height);

	frame1.setVisible (true);
	
	public static void main(String[] args){
		
		//Create the frame
		frame1 = new JFrame ("Sample GUI Application");
		//Set its size to 800x200 pixels
		frame1.setSize (800,200);
		//Prepare panel
		pane = frame1.getContentPane();
		insets = pane.getInsets();
		//Apply the null layout
		pane.setLayout (null);
	}
  }
}



I'm using Eclipse.

Also, when I take out that third curly brace, which looks like it's not necessary to me, it gives me a ton of errors.

Any clues? :)

Thanks in advance. :D
Was This Post Helpful? 0
  • +
  • -

#4 alpha02  Icon User is offline

  • Sexy DIC God
  • member icon

Reputation: 47
  • View blog
  • Posts: 803
  • Joined: 20-May 06

Posted 07 September 2007 - 12:43 PM

This tutorial has been tested throughly and works fine. You used:

Insets insets;
{


which makes absolutely no sense. Just copy and paste the code without forgetting anything!
Was This Post Helpful? 0
  • +
  • -

#5 PennyBoki  Icon User is offline

  • system("revolution");
  • member icon

Reputation: 53
  • View blog
  • Posts: 2,334
  • Joined: 11-December 06

Posted 11 October 2007 - 02:52 PM

Hi alpha02, I just tried your "Putting it all together" code but it doesn't compile.
Please check. All of them are referencing a non-static variable from a static context.
Was This Post Helpful? 0
  • +
  • -

#6 Chopster  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 134
  • Joined: 29-March 08

Posted 29 March 2008 - 10:28 AM

Brilliant Tutorial, Thanks alot, i understand Gui's alot better now
Was This Post Helpful? 0
  • +
  • -

#7 Zubb  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 10
  • Joined: 18-September 09

Posted 19 September 2009 - 02:35 AM

Very Informative :D Im Gonna read This now.
Was This Post Helpful? 0
  • +
  • -

#8 ajn142  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 30-June 10

Posted 01 July 2010 - 12:37 PM

You said that you had someway of moving the components once the Gui was running? What is this? I was thinking that I could use this to make a mockup GUI for a game, then reposition everything, print the location for everything, then use the location of everything to set up the actual GUI attatched to the game. If you have any suggestions on how to do this, I'm all ears. In the mean time, I'll take a shot at it myself.
Was This Post Helpful? 0
  • +
  • -

#9 peanot  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 23
  • Joined: 17-January 11

Posted 20 January 2011 - 12:26 PM

Found 2 small faults:

@ Creating and placing a component

Quote

This may seem complicated, but it is not. First, the pand.add instruction just puts the label in the panel, and the lblServer.setBounds places it. Let's take a look at its parameters:


Should be pane.


This one drove me a bit crazy:
@ Placing all components
Line 29 of the code:

Quote

btnDisconnect.setBounds (insets + 15, lblServer.getY() + lblServer.getHeight() + 5, btnDisconnect.getPreferredSize().width, btnDisconnect.getPreferredSize().height);


When I took a look @ Putting it all together line 65", it says: insets.left.
When you don't have the .left you will get an error:

Quote

operator + cannot be applied to java.awt.Insets,int


MOD EDIT: Fixed, thanks for the feedback!

This post has been edited by JackOfAllTrades: 20 January 2011 - 03:32 PM

Was This Post Helpful? 0
  • +
  • -

#10 Guest_Bart*


Reputation:

Posted 25 January 2011 - 02:30 AM

I love these tutorials very well done and easy to follow for newbies. I would just add this line to the block of the Frame, so it terminates the program when you click the red X.

frame1.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

Was This Post Helpful? 0

#11 daniel_poobalan  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 16
  • Joined: 26-November 11

Posted 27 November 2011 - 08:49 AM

View PostBart, on 25 January 2011 - 02:30 AM, said:

I love these tutorials very well done and easy to follow for newbies. I would just add this line to the block of the Frame, so it terminates the program when you click the red X.

frame1.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

I was about to ask the same question on where is the JFrame.EXIT_ON_CLOSE command so that it will terminate the application properly. Nice spot-on, buddy!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1