2

Here is my code:

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

public class Main extends JFrame implements ActionListener {
    private JPopupMenu popup;
    private JMenuItem red, green, blue, resetBtn;
    private JButton btn = new JButton("Button");
    private Container c;

    public Main() {
        super("Test JPopupMenu");

        c = getContentPane();
        c.setBackground(Color.white);

        // Right Click Popup Menu       
        popup = new JPopupMenu();

        popup.add(red = new JMenuItem("Red"));
        red.addActionListener(this);

        popup.add(green = new JMenuItem("Green"));
        green.addActionListener(this);

        popup.add(blue = new JMenuItem("Blue"));
        blue.addActionListener(this);

        popup.addSeparator();

        popup.add(resetBtn = new JMenuItem("Reset"));
        resetBtn.addActionListener(this);

        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent evt) {
                if ( evt.isPopupTrigger() ) {
                    popup.show(evt.getComponent(), evt.getX(), evt.getY());
                }
            }

            public void mouseReleased(MouseEvent evt){
                if ( evt.isPopupTrigger() ) {
                    popup.show(evt.getComponent(), evt.getX(), evt.getY());
                }
            }
        });

        JPanel jpane = new JPanel();
        jpane.add(btn);

        c.add(jpane);
    }

    public void actionPerformed(ActionEvent evt) {
        if ( evt.getSource() == btn ) {
            JOptionPane.showMessageDialog(null, "You pressed the button!");
        }

        if ( evt.getSource() == red ) {
            c.setBackground(Color.red);
        }

        if ( evt.getSource() == green ) {
            c.setBackground(Color.green);
        }

        if ( evt.getSource() == blue ) {
            c.setBackground(Color.blue);
        }

        if ( evt.getSource() == resetBtn ) {
            c.setBackground(Color.white);
        }

        repaint();
    }

    public static void main(String[] args) {
        Main app = new Main();
        app.setDefaultCloseOperation(EXIT_ON_CLOSE);
        app.setSize(300,300);
        app.setVisible(true);
        app.setResizable(false);
    }
}

The jpanel covers the whole jframe of mine. What can I do to make it only cover the top-left 200px square? I tried setSize for the jpanel but it doesn't works. How can I solve it?

Any help will be appreciated. Thanks for your help.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
user3585169
  • 35
  • 1
  • 3

2 Answers2

4

Start by having a read through Laying Out Components Within a Container to understand how Swing controls the size and positioning of your components

The main problem you have is JFrame by default uses a BorderLayout, which allows the CENTER component to occupy the entire remaining space available to the container.

You will need to do two things...

  1. Override the getPreferredSize method of the JPanel to return the size you would prefer and...
  2. Change layout managers to something that will give you more control...

For example...

example layout

JPanel jpane = new JPanel(new GridBagLayout()) {

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

};
jpane.add(btn);

c.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.NORTHWEST;
c.add(jpane, gbc);

FYI: You can assign a JPopupMenu to a JComponent using the setComponentPoupMenu method. This means you don't need to play around with the mouse listener ;)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I forgot to add `BorderLayout.PAGE_START` to the `c.add(...)`. Thank you for your help! I wil accept your answer once I could. – user3585169 Aug 14 '14 at 03:10
0

Swing uses layout managers to position UI elements. By default most swing components use a BorderLayout layout manager. Different layout managers use different heuristics and properties of UI Elements to work out how they should be sized and positioned. The BorderLayout, for example, has 5 distinct regions that correspond to North, South, East, West and Center (these are now called PAGE_START, PAGE_END, LINE_START, LINE_END and CENTER (see http://docs.oracle.com/javase/tutorial/uiswing/layout/border.html)

Border layout will automatically resize anything in the CENTER position to fill any remaining space. Elements in the 'border' positions (East, South etc) will attempt to honor the 'preferredSize' dimensions.

So with some slight tweaks to your code:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class TestMain extends JFrame implements ActionListener {

    private JPopupMenu popup;
    private JMenuItem red, green, blue, resetBtn;
    private JButton btn = new JButton("Button");
    private Container c;

    public TestMain() {
        super("Test JPopupMenu");

        c = getContentPane();
        c.setBackground(Color.white);

        // Right Click Popup Menu       
        popup = new JPopupMenu();

        popup.add(red = new JMenuItem("Red"));
        red.addActionListener(this);

        popup.add(green = new JMenuItem("Green"));
        green.addActionListener(this);

        popup.add(blue = new JMenuItem("Blue"));
        blue.addActionListener(this);

        popup.addSeparator();

        popup.add(resetBtn = new JMenuItem("Reset"));
        resetBtn.addActionListener(this);

        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent evt) {
                if ( evt.isPopupTrigger() ) {
                    popup.show(evt.getComponent(), evt.getX(), evt.getY());
                }
            }

            public void mouseReleased(MouseEvent evt){
                if ( evt.isPopupTrigger() ) {
                    popup.show(evt.getComponent(), evt.getX(), evt.getY());
                }
            }
        });

        JPanel jpane = new JPanel();
        jpane.setPreferredSize(new Dimension(200,200));
        jpane.add(btn);

        c.add(jpane, BorderLayout.NORTH);
    }

    public void actionPerformed(ActionEvent evt) {
        if ( evt.getSource() == btn ) {
            JOptionPane.showMessageDialog(null, "You pressed the button!");
        }

        if ( evt.getSource() == red ) {
            c.setBackground(Color.red);
        }

        if ( evt.getSource() == green ) {
            c.setBackground(Color.green);
        }

        if ( evt.getSource() == blue ) {
            c.setBackground(Color.blue);
        }

        if ( evt.getSource() == resetBtn ) {
            c.setBackground(Color.white);
        }

        repaint();
    }

    public static void main(String[] args) {
        TestMain app = new TestMain();
        app.setDefaultCloseOperation(EXIT_ON_CLOSE);
        app.setSize(300,300);
        app.setVisible(true);
        app.setResizable(false);
    }
}

Things I've changed:

  • When adding the JPanel, I tell the layout manager (via the add method), which position I want the JPanel to occupy (North)
  • Set a preferred size. Note that the North position only will allows the user to specify a height, as width is automatic, and vice versa for East and West

Hope this helps!

David
  • 511
  • 4
  • 14
  • *"By default most swing components use a BorderLayout layout manager"* is erroneous, as `JFrame` uses a `BorderLayout`, but `JPanel` uses a `FlowLayout` and `JScrollPane` has it's own layout manager ... The left/right positions will honour the preferred width and the top/bottom will honour the preferred width, there other dimensions will be at least equal to the center components preferred size... – MadProgrammer Aug 14 '14 at 06:07
  • FYI: [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?](http://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi) – MadProgrammer Aug 14 '14 at 06:08