Reputation: 47
I am facing this issue where the JButton wouldn't go to its set location........ My code:
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUI implements ActionListener {
private int clickCount = 0;
private JFrame frame;
private JPanel panel;
private JButton button;
private JLabel label;
private Dimension buttonDim;
public GUI() {
frame = new JFrame();
panel = new JPanel();
button = new JButton("Click me");
label = new JLabel("Number of clicks 0");
button.addActionListener(this);
button.setBorder(null);
button.setLocation(0, 0);
panel.setBorder(BorderFactory.createEmptyBorder(300/2, 300, 300/2, 300));
panel.setLayout(new GridLayout(0, 1));
panel.add(button);
panel.add(label);
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Our GUI");
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new GUI();
}
@Override
public void actionPerformed(ActionEvent e) {
clickCount++;
label.setText("Number of clicks " + clickCount);
}
}
And if you guys don't really mind could you tell me that how does my button know about the ActionListener
with just the this
keyword? I started java like a week ago.
Upvotes: 0
Views: 38
Reputation: 88707
On Layouts
Note that although you could position your components manually by setting their location and size it is rarely useful to do so. You'd not do this in web based UIs nor Apps nor Swing UIs for several reasons:
All those reasons make it hard if not impossible to create a pixel-perfect layout that fits all needs and that's rarely even necessary. So in contrast each system has their own way of laying out components with Swing using layout managers like GridLayout
, BorderLayout
, etc.
In your case you've used GridLayout
for the panel that should contain the button and since you passed rows = 0
and cols = 1
to the constructor you effectively created a layout with any number of rows and one column. If you now add the button to the panel the GridLayout
manager will adjust the button's position accordingly.
In addition your panel has a border which also affects the content area of that panel, i.e. where position 0/0 for content would be.
Thus button.setLocation(0, 0);
won 't have the expected effect since the layout manager will reposition (and resize) the button according to the available content area.
A few more hints on layout managers:
add(Component, ...)
which allow you to also pass "constraints" that influence the layout. The type of those constraints depends on the layout manager you used.null
layout manager. But be warned that you'll have to deal with a lot of things yourself and often you actually don't want to do that. Often the perceived need to use a null
layout comes from the feeling that the built-in layout managers are lacking. In that case you might explore some 3rd party layout managers. One that I found particularly useful in the past (it even comes with a debug view) is MiG layout.Finally some hints on how to design a layout:
Draw out the intended layout on paper or in some app at the minimum size your UI should have. If you want to make it resizable (e.g. by increasing width) then think about how the additional space you gain should be used.
Also put yourself into the position of a user confronted with the following scenarios (there might be more):
On ActionListeners
You can set an action listener for many components which then is called when some action is performed (e.g. a button is clicked). To create an action listener you implement the ActionListener
interface and its void actionPerformed(ActionEvent)
method - like your GUI
is already doing.
Hence in button.addActionListener(this);
you set the current enclosing instance of GUI
which this
refers to as the button's action listener.
Note that normally you'd either have explicit classes which implement ActionListener
or create anonymous classes or lambdas, e.g. like this:
//pre-Java 8 way
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("button clicked");
}
});
//using lambdas (ActionListener meets the requirements for functional interfaces)
button.addActionListener(actionEvent -> System.out.println("button clicked") );
Acknowledgements: thanks to Andrew Thompson for providing valuable input :)
Upvotes: 1