1

I want to place a JPanel with 300,200 size at 100,50 location in a JFrame, but the following code makes the whole JFrame to be filled with the JPanel, where am I wrong? Code:

public class Class1  {
      
    public static void main(String[] args) {
   
         JFrame frame = new JFrame();
         JPanel panel = new JPanel();
         
         frame.setSize(700, 500);              
         panel.setSize(300, 200);
         panel.setBackground(Color.green);
         panel.setCursor(new Cursor(java.awt.Cursor.HAND_CURSOR));
            
         frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);         
         frame.add(panel, BorderLayout.CENTER);                   
         frame.setVisible(true);
         frame.setLocationRelativeTo(null);
    }      
}

If I change BorderLayout.SOUTH or NORTH, the JPanel looks like a thin line at the bottom or top of the JFrame. Also I tried to use preferred size but its still the same result.

c0der
  • 18,467
  • 6
  • 33
  • 65
CuriousGuy
  • 1,545
  • 3
  • 20
  • 42
  • 6
    Read the tutorials on the Swing layout managers to see why this is happening. Understand that a JFrame (actually its contentPane) uses BorderLayout by default. Also know that most layout managers do not respect a components size but rather its preferred sizes. Also know that if you use a `null` layout, you will paint yourself into a corner; so avoid those. – Hovercraft Full Of Eels Jul 18 '15 at 10:39
  • What does the panel contain that would make it's size `300 x 200`? What does the farm contain that make make the panel appear at `100, 50`? – trashgod Jul 18 '15 at 10:51
  • I am afraid the answers given are not going to help the op understand the basics of how Layout Managers work. They will only serve to confuse him further. There is no such thing as a bad Student, only bad Teacher – Constantin Jul 18 '15 at 12:05

3 Answers3

5

You need to understand the basics of Layout Managers before you can attempt anything with Swing.

Study the tutorial here https://docs.oracle.com/javase/tutorial/uiswing/layout/howLayoutWorks.html

If you are trying to construct a form with various Swing controls, never use absolute coordinates to position them. Resizing the window should dynamically reposition your controls according to the type of layout you want to use. If you are using your panel as a drawing canvas (which is what I think you are after), look at my example below.

Try to master a couple of fundamental layouts first such as BorderLayout and GridLayout. Once mastered you can use very few to achieve just about any kind of layout you desire by nesting them together. Also learn the basics of ScrollPane to make efficient use of screen real-estate

As for your original question, I created an example of how BorderLayout works and how to draw to a specific region on a panel. I also added some code so you can set your cursor differently depending on whether you are in the smaller region within a given panel.

Try this:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class FrameDemo extends JFrame {
  private static final long serialVersionUID = 1L;

  public FrameDemo() {
    super("Frame Demo");
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    getContentPane().add(new CustomPanel(Color.RED), BorderLayout.NORTH);
    getContentPane().add(new CustomPanel(Color.GREEN), BorderLayout.SOUTH);
    getContentPane().add(new CustomPanel(Color.BLUE), BorderLayout.EAST);
    getContentPane().add(new CustomPanel(Color.YELLOW), BorderLayout.WEST);
    getContentPane().add(new JScrollPane(new CustomPanel(Color.BLACK)), BorderLayout.CENTER);

    pack();
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JFrame frame = new FrameDemo();
        frame.setVisible(true);
      }
    });
  }
}

class CustomPanel extends JPanel implements MouseMotionListener {
  private static final long serialVersionUID = 1L;

  private static final Dimension PANEL_SIZE = new Dimension(200, 100);
  private static final int HAND_CURSOR_INDEX = 1;
  private static final int DEFAULT_CURSOR_INDEX = 0;
  private static final Cursor[] _cursors = new Cursor[] {
    Cursor.getDefaultCursor(),
    Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
    };

  // I want to place a JPanel with 300,200 size at 100,50 location in a JFrame
  private static final Rectangle _rectangle = new Rectangle(50, 10, 40, 50);

  public CustomPanel(Color color) {
  setBackground(color);
    addMouseMotionListener(this);
  }

  public Dimension getPreferredSize() {
    return PANEL_SIZE;
  }

  public Dimension getMinimumSize() {
    return PANEL_SIZE;
  }

  public Dimension getMaximumSize() {
    return PANEL_SIZE;
  }


  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(Color.WHITE);
    g.fillRect(
        (int)_rectangle.getX(),
        (int)_rectangle.getY(),
        (int)_rectangle.getWidth(),
        (int)_rectangle.getHeight());
  }

  @Override
  public void mouseDragged(MouseEvent e) {
    // TODO Auto-generated method stub

  }

  @Override
  public void mouseMoved(MouseEvent e) {
    int cursorIndex = _rectangle.contains(e.getPoint()) ?
        HAND_CURSOR_INDEX :
        DEFAULT_CURSOR_INDEX;
        setCursor(_cursors[cursorIndex]);
  }
}

enter image description here

Constantin
  • 1,506
  • 10
  • 16
2

If you want the panel to occupy part of the JFrame (contentpane) you can use other layout managers. He is an example using GroupLayout:

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class Class1  {

    public static void main(String[] args) {

         JFrame frame = new JFrame();
         JPanel panel = new JPanel();

         frame.getContentPane().setPreferredSize(new Dimension(700, 500) );
         panel.setPreferredSize(new Dimension(300, 200));
         panel.setBackground(Color.green);
         panel.setCursor(new Cursor(java.awt.Cursor.HAND_CURSOR));

         frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
         GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
         groupLayout.setHorizontalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addGap(104)
                    .addComponent(panel, GroupLayout.PREFERRED_SIZE, 493, GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(103, Short.MAX_VALUE))
         );
         groupLayout.setVerticalGroup(
            groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup()
                    .addGap(100)
                    .addComponent(panel, GroupLayout.PREFERRED_SIZE, 301, GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(99, Short.MAX_VALUE))
         );
         frame.getContentPane().setLayout(groupLayout);
         frame.pack();
         frame.setVisible(true);
         frame.setLocationRelativeTo(null);
    }


}

output: enter image description here

Another example using BorderLayout with 4 additional "place holder" or feeler panels :

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;

public class Class1  {

    public static void main(String[] args) {

        JFrame frame = new JFrame();

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new BorderLayout(0, 0));

        JPanel centerPanel = new JPanel();
        centerPanel.setPreferredSize(new Dimension(300, 200));
        centerPanel.setBackground(Color.green);
        centerPanel.setCursor(new Cursor(java.awt.Cursor.HAND_CURSOR));
        frame.getContentPane().add(centerPanel);

        JPanel northPanel = new JPanel();
        northPanel.setBackground(Color.RED);
        northPanel.setForeground(Color.BLACK);
        northPanel.setPreferredSize(new Dimension(0, 150));
        frame.getContentPane().add(northPanel, BorderLayout.NORTH);

        JPanel westPanel = new JPanel();
        westPanel.setBackground(Color.MAGENTA);
        westPanel.setPreferredSize(new Dimension(200, 0));
        frame.getContentPane().add(westPanel, BorderLayout.WEST);

        JPanel southPanel = new JPanel();
        southPanel.setBackground(Color.YELLOW);
        southPanel.setPreferredSize(new Dimension(0, 150));
        frame.getContentPane().add(southPanel, BorderLayout.SOUTH);

        JPanel eastPanel = new JPanel();
        eastPanel.setBackground(Color.BLUE);
        eastPanel.setPreferredSize(new Dimension(200, 0));
        frame.getContentPane().add(eastPanel, BorderLayout.EAST);

        frame.pack();
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
    }


}

output : enter image description here

c0der
  • 18,467
  • 6
  • 33
  • 65
  • Given the op's confusion about the basics of Layout Managers, do you actually think your code is really going to help him get there? Let us try to understand what he is trying to achieve, otherwise you are going to confuse him even more than he already is :) – Constantin Jul 18 '15 at 11:57
  • Thnks for the comment @ Constantin, To my opinion examples are the best way to clarify. It does work for me better than any documentation or explanation. Let's see (0: – c0der Jul 18 '15 at 12:21
  • Your second example is much better. Using complex layout managers are completely unnecessary. I can create the most complex layouts simply using BorderLayout and GridLayout by nesting them but it requires full mastery through understanding. Examples are fine provided the Student understands the theory behind them. – Constantin Jul 18 '15 at 12:25
1
import javax.swing.*;
import java.awt.*;
public class Class1  {

    public static void main(String[] args) {

         JFrame frame = new JFrame();
         JPanel panel = new JPanel();
         JPanel another = new JPanel();
         JPanel emptyPanel = new JPanel();
         emptyPanel.setPreferredSize(new Dimension(700, 50));
         frame.setSize(700, 500); 


         panel.setMaximumSize(new Dimension(300, 200));
         panel.setMinimumSize(new Dimension(300, 200));
         panel.setPreferredSize(new Dimension(300, 200));
         panel.setBackground(Color.green);
         panel.setCursor(new Cursor(java.awt.Cursor.HAND_CURSOR));

         frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

         another.add(emptyPanel, BorderLayout.NORTH);
         another.add(panel, BorderLayout.CENTER);         
         
         frame.add(another);
         frame.setVisible(true);
         frame.setLocationRelativeTo(null);
    }


}

The created image looks like below enter image description here

It looks to me that immediate child container of the JFrame is resized to the size of the JFrame, the top level container, itself.

Community
  • 1
  • 1
sakthisundar
  • 3,278
  • 3
  • 16
  • 29
  • 1
    If the op is actually trying to place Swing controls on a form, which is highly unlikely, this approach will do the trick and is the correct answer. If, however, the op is trying to draw something in a particular region on the screen, your example is definitely not the right approach. Unless the op explains what his intention is, we cannot know – Constantin Jul 18 '15 at 12:36