Jonathan Allen Grant
Jonathan Allen Grant

Reputation: 3648

How can I move my JButton to the right side of my JPanel?

For a programming class, I was asked to create a replica of an iCalendar app. I'm using JAVA to code it, and JFrame and JPanel to draw it. Here is a SSCCEE of my problem:

import java.awt.*;

import javax.swing.*;

public class Mainie extends JFrame {
    private JButton back = new TriangleButton(true),
            front = new TriangleButton(false);
    public Mainie(){
        super();
        setSize(800, 400);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel months = new JPanel();
        final JPanel days = new JPanel();
        JLabel one = new JLabel("Hallo");
        one.setHorizontalAlignment(JLabel.CENTER);
        back.setHorizontalAlignment(SwingConstants.LEFT);
        front.setHorizontalAlignment(SwingConstants.RIGHT);
        months.setLayout(new BorderLayout());
        months.add(back, BorderLayout.WEST);
        months.add(one, BorderLayout.CENTER);
        months.add(front, BorderLayout.EAST);

        days.setLayout(new GridLayout(1,1));
        days.add(new JButton("Meister Camickr"));

        months.setAlignmentX(CENTER_ALIGNMENT);
        add(months, BorderLayout.NORTH);
        add(days, BorderLayout.CENTER);

        setVisible(true);
    }

    public static void main(String[] args){
        new Mainie();
    }
}

class TriangleButton extends JButton {
    private Shape triangle = createTriangle();

    public void paintBorder(Graphics g) {
        ((Graphics2D) g).draw(triangle);
    }

    public void paintComponent(Graphics g) {
        ((Graphics2D) g).fill(triangle);
    }

    public Dimension getPreferredSize() {
        return new Dimension(200, 100);
    }

    public boolean contains(int x, int y) {
        return triangle.contains(x, y);
    }

    public TriangleButton(boolean pointLeft) {
        super();
        if (!pointLeft)
            this.triangle = createRTriangle();
    }

    private Shape createTriangle() {
        Polygon p = new Polygon();
        p.addPoint(0, 20);
        p.addPoint(20, 0);
        p.addPoint(20, 40);
        return p;
    }

    private Shape createRTriangle() {
        Polygon p = new Polygon();
        p.addPoint(20, 20);
        p.addPoint(0, 0);
        p.addPoint(0, 40);
        return p;
    }
}

If you compile this, you can see that my JButton is too far to the left. How can I move it to the right?

Upvotes: 2

Views: 1604

Answers (2)

camickr
camickr

Reputation: 324108

The problem is your random preferred size doesn't represent the real size of the triangle.

You can do something like:

public Dimension getPreferredSize() {
//return new Dimension(200, 100);
Rectangle bounds = triangle.getBounds();
return new Dimension(bounds.width, bounds.height);
}

You still have other problems because you will still have painting artifacts. You should always invoke super.paintComponent() when you override the method:

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    ((Graphics2D) g).fill(triangle);
}

However, this still doesn't really work because the button does other painting as well. So the real problem is that you should not be trying to do custom painting of the button. What you really want to do is custom painting of an Icon. Then you can just add the Icon to the button.

You may want to check out Playing With Shapes. You can use the ShapeIcon class to create your icons. This will provide a more flexible solution since I'm guess all shapes are not represented by an ascii character.

Upvotes: 0

Andrew Thompson
Andrew Thompson

Reputation: 168825

The basic problem with those buttons is that the button is very wide and the visual indicator is to the left. Put a border around them and it becomes obvious.

OTOH I would use an entirely different approach, using text for the buttons and a factory method to make them look as expected.

enter image description here enter image description here

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

public class CustomPointerButtons {

    JPanel ui;

    CustomPointerButtons() {
        initUI();
    }

    private final void initUI() {
        ui = new JPanel(new BorderLayout(4, 4));

        JPanel topPanel = new JPanel(new BorderLayout(4, 4));

        ui.add(topPanel, BorderLayout.PAGE_START);
        ui.add(new JButton("Mister Mix")); //will default to CENTER

        topPanel.add(new JLabel("Blah, Blah.."));
        JButton back = getMinimalButton(new String(Character.toChars(9668)));
        topPanel.add(back, BorderLayout.LINE_START);

        JButton forward = getMinimalButton(new String(Character.toChars(9658)));
        topPanel.add(forward, BorderLayout.LINE_END);
    }

    public JButton getMinimalButton(String text) {
        JButton b = new JButton(text);
        b.setFont(b.getFont().deriveFont(40f));

        b.setMargin(new Insets(0,0,0,0));
        b.setContentAreaFilled(false);
        b.setBorder(null);

        return b;
    }

    public final JComponent getUI() {
        return ui;
    }


    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame("Custom Pointer Buttons");
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setContentPane(new CustomPointerButtons().getUI());
                f.pack();
                f.setLocationByPlatform(true);
                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

Upvotes: 3

Related Questions