JPanel - Set Button/Check Box Location

Hi,

I am doing a very basic GUI project for college. I need some quick help. I am use to using C# so I have a visual designer.

I wanted to make my form look a little better then the default so I wanted to arrange my buttons/check boxes etc… into set places on the form. Its not required by the instructor but I want to do it anyway just to learn it.

I have all the buttons and check boxes on the form allready and the form is working. I searched on Google for examples of how to place a control in a set location but the only examples I can find are people saying its impossible to do without a visual designer.

I am required by my instructor to use Notepad++ for this assignment so I do not have access to any drag and drop IDE.

I’m looking for something simple like:


check_OilChange = new JCheckBox("Oil Change");

[B]check_OilChange.setLocation(15,48);[/B]

panel = new JPanel();
panel.add(check_OilChange);


With the 15,48 being the Top and Left position of the control, so I can kind of arrange it to where I want. My form looks really sloppy right now with everything center aligned and running in a line across the form.

I must be looking for the wrong thing because it seems so simple but I can’t find any examples.

Can anyone show me how to set the position manually?

Edit:

I have found something like this but, I can’t get it to work at all for me.

Aye Caramba…

Look into using the GridBagLayout and GridBagConstraints. It might seem weird at first, but GBL and GBC are the way to go.

With GBL/GBC you can place panels inside of panels to get specific behavior you want. If you would like I can put together an example, but it might take me some time to get it done.

Ok, I looked at those this morning but they were confusing me. I tried several variations but either they had no effect at all or I just got a completely blank form.

I will look at them again, if that is how I need to do it. I know that it would be better to use an IDE, but we are not allowed to use it yet because our computers at school only have Notepad++ and we are not allowed to install something new.

My form is ok the way it is, it works and all the code is correct. But it looks like crap. I would like to turn in something that looks a little better.

In the mean time if you have a basic example that would be great! Just with one or two controls on it showing me how to lay them out. I can probably figure it out from there. I seen the GridBagLayout stuff on Sun’s website this morning but for some reason I didn’t understand what they were doing. It didn’t look like mine.

I put two screen shots, one of my current form which is crappy, and one of how I would like it to look in the end.

Then please tell me this is possible with GridBagLayout?

Edit: http://yfrog.com/ht25669820p

So here you go.

First off, GUI development is quite verbose and can be painful to debug. BUT, a consistent plan is followed it isn’t to hard to figure out where things go wrong.

The biggest key with using GridBagLayout and GridBagConstraints is understanding how the different components relate to one another and then group them with panels accordingly.

Here is the code:


package swing;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;

public class JoesAutomotiveMain {
	
	public JoesAutomotiveMain() {
		
		this.init();
	}
	
	
	private void init() {
		
		JFrame jframe = new JFrame();
		
		GridBagLayout gbl = new GridBagLayout();
		
		GridBagConstraints gbc = new GridBagConstraints();
		
		jframe.setLayout(gbl);
		
		jframe.setTitle("Joe's Automtive");
		
		JPanel topjpanel = createTopJPanel();
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.weightx = 1.0;
		gbc.weighty = 1.0;
		jframe.add(topjpanel, gbc);
		
		JPanel totaljpanel = createTotalJPanel();
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.weightx = 1.0;
		gbc.weighty = 0.0;
		jframe.add(totaljpanel, gbc);
		
		JPanel buttonjpanel = createButtonJPanel();
		gbc.gridx = 0;
		gbc.gridy = 2;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.weightx = 1.0;
		gbc.weighty = 0.0;
		jframe.add(buttonjpanel, gbc);
		
		jframe.setSize(400, 300);
		jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jframe.setVisible(true);
	}
	
	
	public static void main(String[] args) {
		
		new JoesAutomotiveMain();
	}
	
	public JPanel createTopJPanel() {
		
		JPanel jpanel = new JPanel();
		
		GridBagLayout gbl = new GridBagLayout();
		
		GridBagConstraints gbc = new GridBagConstraints();
		
		jpanel.setLayout(gbl);
		
		JPanel leftjpanel = createMaintenanceServicesJPanel();
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.weightx = 1.0;
		gbc.weighty = 1.0;
		jpanel.add(leftjpanel, gbc);
		
		JPanel rightjpanel = createTopRightPanel();
		gbc.gridx = 1;
		gbc.gridy = 0;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.weightx = 1.0;
		gbc.weighty = 1.0;
		jpanel.add(rightjpanel, gbc);
		
		return jpanel;
	}
	
	public JPanel createTopRightPanel() {
		
		JPanel jpanel = new JPanel();
		
		GridBagLayout gbl = new GridBagLayout();
		
		GridBagConstraints gbc = new GridBagConstraints();
		
		jpanel.setLayout(gbl);
		
		JPanel miscservicesjpanel = createMiscServicesJPanel();
		gbc.anchor = GridBagConstraints.WEST;
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.weightx = 1.0;
		gbc.weighty = 1.0;
		jpanel.add(miscservicesjpanel, gbc);
		
		JPanel partsandlaborjpanel = createPartsAndServicesJPanel();
		gbc.anchor = GridBagConstraints.WEST;
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.weightx = 1.0;
		gbc.weighty = 1.0;
		jpanel.add(partsandlaborjpanel, gbc);
		
		return jpanel;
	}
	
	public JPanel createMaintenanceServicesJPanel() {
		
		JPanel jpanel = new JPanel();
		
		GridBagLayout gbl = new GridBagLayout();
		
		GridBagConstraints gbc = new GridBagConstraints();
		
		jpanel.setLayout(gbl);
		
		jpanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), "Maintenance Services"));
		
		JCheckBox jcheckBox = new JCheckBox("CheckBox1");
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		gbc.weightx = 1.0;
		jpanel.add(jcheckBox, gbc);
		
		jcheckBox = new JCheckBox("CheckBox2");
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		gbc.weightx = 1.0;
		jpanel.add(jcheckBox, gbc);
		
		jcheckBox = new JCheckBox("CheckBox3");
		gbc.gridx = 0;
		gbc.gridy = 2;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		gbc.weightx = 1.0;
		jpanel.add(jcheckBox, gbc);
		
		return jpanel;
	}
	
	public JPanel createMiscServicesJPanel() {
		
		JPanel jpanel = new JPanel();
		
		GridBagLayout gbl = new GridBagLayout();
		
		GridBagConstraints gbc = new GridBagConstraints();
		
		jpanel.setLayout(gbl);
		
		jpanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), "Misc. Services"));
		
		JLabel jlabel = new JLabel("Total Misc. Services");
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		gbc.weightx = 1.0;
		jpanel.add(jlabel, gbc);
		
		JTextField jtextfield = new JTextField();
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		gbc.weightx = 1.0;
		jpanel.add(jtextfield, gbc);
		
		return jpanel;
	}
	
	public JPanel createPartsAndServicesJPanel() {
		
		JPanel jpanel = new JPanel();
		
		GridBagLayout gbl = new GridBagLayout();
		
		GridBagConstraints gbc = new GridBagConstraints();
		
		jpanel.setLayout(gbl);
		
		jpanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), "Parts and Labor"));
		
		JLabel jlabel = new JLabel("Parts");
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.fill = GridBagConstraints.NONE;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		gbc.weightx = 0.0;
		jpanel.add(jlabel, gbc);
		
		JTextField jtextfield = new JTextField();
		gbc.gridx = 1;
		gbc.gridy = 0;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		gbc.weightx = 1.0;
		jpanel.add(jtextfield, gbc);
		
		jlabel = new JLabel("Labor");
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.fill = GridBagConstraints.NONE;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		gbc.weightx = 0.0;
		jpanel.add(jlabel, gbc);
		
		jtextfield = new JTextField();
		gbc.gridx = 1;
		gbc.gridy = 1;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.anchor = GridBagConstraints.WEST;
		gbc.insets = new Insets(5, 5, 5, 5);
		gbc.weightx = 1.0;
		jpanel.add(jtextfield, gbc);
		
		return jpanel;
	}
	
	public JPanel createTotalJPanel() {
		
		JPanel jpanel = new JPanel();
		
		GridBagLayout gbl = new GridBagLayout();
		
		GridBagConstraints gbc = new GridBagConstraints();
		
		jpanel.setLayout(gbl);
		
		JLabel jlabel = new JLabel("Total JPanel");
		gbc.gridx = 0;
		gbc.gridy = 0;
		jpanel.add(jlabel, gbc);
		
		return jpanel;
	}
	
	public JPanel createButtonJPanel() {
		
		JPanel jpanel = new JPanel();
		
		GridBagLayout gbl = new GridBagLayout();
		
		GridBagConstraints gbc = new GridBagConstraints();
		
		jpanel.setLayout(gbl);
		
		JLabel jlabel = new JLabel("Button JPanel");
		gbc.gridx = 0;
		gbc.gridy = 0;
		jpanel.add(jlabel, gbc);
		
		return jpanel;
	}
}

I didn’t write everything for you, but this should give you a reasonable start.

Now depending on how you have to handle getting values you might want to look at the law do demeter. You might consider extending JPanel and adding getters for the different possible values of the components in that specific panel. You could use inner classes to accomplish that behavior if you wanted.

Also, how to handle button clicks? I always extend JButton with a class called ExtendedJButton that is a listener of itself and then use an anonymous inner class to handle the button click by overriding the handleEvent method…


package swing;

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

import javax.swing.JButton;

public class ExtendedJButton extends JButton implements ActionListener {
	
	// Override all constructors and call super with the correct arguments but add this as a listener of itself...
	public ExtendedJButton() {
		
		super();
		this.addActionListener(this);
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println(this + " actionPerformed method needs to be overrided!");
		// You could also consider throwing a org.apache.commons.lang.NotImplementExcetpion but you would have to use the apache commons library.
	}
}

Then use the above button the following way:


JButton jbutton = new ExtendedJButton() {
	public void actionPerformed(ActionEvent e) {
		// your code here...  most likely delegating to a method in your JFrame class or a Service.
	}
};
// Do your GridBagConstraint work here.

And there you go.

Like I said before GUI programming is quite verbose and it takes a lot of work to get everything just right.

Others on this site might disagree with the above code and statements, but I’ve seen the above work for production systems and have absolutely blown away some serious java haters with how nice the gui can look/behave in java.

Also, to debug what some of the panels/components are doing consider using the setBackground(Color color) method.

Set the backgrounds of your different panels to different colors to see exactly how they are reacting with the weightx and fill options of GridBagConstraints.

Finally, notice that I use a different instance of GridBagConstraints for each panel, but then re-use the GridBagConstraints for each component in the panel. USE WITH CARE. When you set a value on GridBagConstraints that value is set until it is replaced with another value and can lead to confusion. When setting a value for GridBagConstraints with a set of components I ALWAYS set all the GridBagCosntraint values for each component, even if the value is just the default value.

Best of Luck.

Thanks, I got it all working now. I turned it in this morning.

I think if I ever did a real application in Java I would use an IDE or something to make a better interface, but this was a simple assignment, and we don’t have access to it.

I think next semester we are using IDE but in the intro class the instructor probably thinks that learning an IDE and lanauge at the same time will be too much.

I don’t think the other students will have this problem because I went a little more into it then I was supposed to. It was simply supposed to be a static form that displayed a few labels with some information in it about a pretend service on your car.

I went farther and made it so that there were check boxes and buttons so that you could actually calculate your services instead of just having static services. But when I added so many controls, it got messy.

I’m glad everything worked out and I hope you do well on your assignment.

I personally don’t like to use IDE visual tools for building GUIs in Java. I’ve found the code to be hard to read and bloated. Yes, even more then what was written above…

So that class could have really been simplified, but I feel it is easier to see everything together in one big class instead of having to open many different classes.

However, it is easier to divide and conqueror in the long run…

There are many different ways of getting the data from the different panels, but the way I prefer is to actually have a business object (Customer, RequestedService, etc…) be updated by the forms as the forms are updated. This is a little advanced and required a very good understanding of events and listeners (or observe and observable).

But then your calculate button would have to go to every panel to get the info needed, just the business object…

Event driven programming is the key to high cohesion, low coupling programming and is useful on both client and server side programming.