Gathik Jindal
Gathik Jindal

Reputation: 47

JButton is not appearing at its set location

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

Answers (1)

Thomas
Thomas

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:

  • Users will have a variety of screen sizes and resolutions, so high res screens might require larger components if the screen itself is small.
  • Operating systems come with a variety of look and feels (PLAF = platform look and feel) and those can vary greatly.
  • Nowadays UIs often ate multilingual and almost every language has a different run-length.

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:

  • You might want to familiarize yourself with the various options available.
  • Have a look at the various versions of 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.
  • You can define a preferred size for your components (as well as min/max) to have some influence on the layout. Many layout managers will try to conform to your wishes as well as possible.
  • If you really want to position your components yourself you need to set the 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):

  • More space than your UI is using is available and your UI doesn't put all available information on screen. Could you change your layout to make additional information available if there is extra space?
  • Less space than your UI would need is available. Would it still be possible to easily access all relevant parts, e.g. by scrolling?

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 thisrefers 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

Related Questions