Java JPanel中的油漆位置和尺寸错误

Java JPanel中的油漆位置和尺寸错误,java,swing,jpanel,paintcomponent,repaint,Java,Swing,Jpanel,Paintcomponent,Repaint,我正在开发一个Java GUI,我有一个JFrame,它是600x800,我想分为两部分,顶部有设置复选框,是600 x 200,底部是“画布”,将在其上绘制600x600。我有一个JFrame,它有一个JPanel,其中包含另外两个JPanel(一个用于设置,另一个用于画布)。我正在测试“绘制”,出于某种原因,当我尝试绘制一个600x600黑色矩形时,它在设置JPanel占据的区域中绘制了一个小得多的矩形。知道发生了什么事吗?我正在使用repaint方法调用paintComponent,我已经

我正在开发一个Java GUI,我有一个JFrame,它是600x800,我想分为两部分,顶部有设置复选框,是600 x 200,底部是“画布”,将在其上绘制600x600。我有一个JFrame,它有一个JPanel,其中包含另外两个JPanel(一个用于设置,另一个用于画布)。我正在测试“绘制”,出于某种原因,当我尝试绘制一个600x600黑色矩形时,它在设置JPanel占据的区域中绘制了一个小得多的矩形。知道发生了什么事吗?我正在使用repaint方法调用paintComponent,我已经尝试在JFrame的构造函数和要绘制的JPanel中调用repaint

HPA程序 地图窗口 设置按钮面板
问题是你似乎有很多误解

JPanel
,默认情况下使用
FlowLayout
<代码>FlowLayout使用每个组件的首选大小来确定每个组件的大小。默认情况下,组件的首选大小为
0x0

布局管理器还负责放置组件,因此使用
setBounds
setLocation
setSize
会适得其反

假设大小也不总是可能的,尤其是在处理文本时,因为这可能会根据字体、显示驱动程序、渲染管道等的不同而改变大小

这就是Java制作广泛布局管理器的原因。请查看以了解更多详细信息

使用简单示例更新

不要害怕混合布局,使用具有不同布局的复合组件,以实现您想要的结果,例如

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SimpleLayout100 {

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

    public SimpleLayout100() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JPanel header = new JPanel();
                header.add(new JLabel("Hello, I'm the header"));

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(header, BorderLayout.NORTH);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.GREEN);
            g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
            g2d.setColor(Color.RED);
            g2d.fillRect(150, 50, 300, 100);
            g2d.dispose();
        }
    }

}


使用适当的布局管理器。不要使用setBounds,而是覆盖getPreferredSize以向布局管理器提供适当的大小提示我不明白为什么在这个实例中使用getPreferredSize。我确切地知道我需要什么尺寸,而且它们不会改变,为什么我要覆盖getPreferredSize?抱歉,如果我太过密集:请根据@MadProgrammer的建议进行扩展。javagui可能必须在许多平台上工作,在不同的屏幕分辨率上&使用不同的plaf。因此,它们不利于部件的精确放置。为了组织一个健壮的GUI组件,可以使用布局管理器,或者与布局填充和边框一起使用。“我确切地知道我需要什么尺寸……”Hmmm。。“JPanel中的绘画是在错误的位置和尺寸上进行的。”这可能意味着你没有你想象的那么清楚。O_o@AndrewThompson是不是他确实知道,但他不能让自己的代码遵守这些约束?那么你的意思是我应该放弃将每个面板设置为特定大小的想法,让布局经理做自己的事情?我会试试看,如果它能修复我的油漆,我会告诉你的issue@zaloo虽然我也建议您阅读布局管理器并广泛使用它们,您还可以将
JPanel
的布局管理器设置为null,并使用
setBounds
等。我真的很困惑如何使用布局管理器使面板变小或变大。我希望我的顶部面板尽可能小,但我不知道如何做到这一点检查答案和更新中的可用链接example@mostruash我甚至只考虑使用<代码> null >代码>布局管理器,如果我正在动画组件或正在复制我自己的窗口系统。否则,
null
管理者会引入大量的复杂性和管理开销。。。
//import java.awt.*;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.*;

import javax.swing.*;  //notice javax
public class MapWindow extends JFrame
{
    private static final int WIDTH = 600, HEIGHT = 800;

    JPanel panel = new JPanel();
    SettingsButtonsPanel button_panel = new SettingsButtonsPanel();
    MapImagePanel map_panel = new MapImagePanel();
    public MapWindow()
    {

        setLocationRelativeTo(null);
        setTitle("HPA* Test");
        setSize(WIDTH, HEIGHT);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        add(panel);
        panel.setBounds(0, 0, 600, 800);
        //panel.setLayout(new GridBagLayout());
        /*GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 0;
        c.gridy = 0;*/

        panel.add(button_panel);

        /*c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 0;
        c.gridy = 1;*/

        panel.add(map_panel);

        button_panel.setLocation(0,0);
        /*map_panel.setLocation(0,200);
        map_panel.setSize(600,600);*/
        map_panel.repaint();

    }

}
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class SettingsButtonsPanel extends JPanel implements ItemListener{
    private static final int WIDTH = 600, HEIGHT = 200;
    private static final int NUM_MAP_TYPE = 2;

    private JCheckBox[] map_type;

    JPanel panel = new JPanel();

    public SettingsButtonsPanel(){

        this.setLayout(new GridBagLayout());

        GridBagConstraints c = new GridBagConstraints();

        this.setBounds(0,0,WIDTH, HEIGHT);

        map_type = new JCheckBox[NUM_MAP_TYPE];

        map_type[0] = new JCheckBox("Sparse");
        map_type[0].setSelected(true);
        //map_type[0].setSize(100,100);


        map_type[1] = new JCheckBox("Maze");
        map_type[1].setSelected(false);
        //map_type[1].setSize(100,100);

        for(int i = 0; i < NUM_MAP_TYPE; i++)
        {
            map_type[i].addItemListener(this);
            c.fill = GridBagConstraints.HORIZONTAL;
            c.gridx = 0;
            c.gridy = i;
            this.add(map_type[i], c);
        }
    }

    public void itemStateChanged(ItemEvent e)
    {
        Object source = e.getItemSelectable();
        //if(source == )
    }
}
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class MapImagePanel extends JPanel{
    public MapImagePanel()
    {
        this.setBounds(0,200, 600,600);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.fillRect(0,0,600,600);
    }
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SimpleLayout100 {

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

    public SimpleLayout100() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JPanel header = new JPanel();
                header.add(new JLabel("Hello, I'm the header"));

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(header, BorderLayout.NORTH);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.GREEN);
            g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
            g2d.setColor(Color.RED);
            g2d.fillRect(150, 50, 300, 100);
            g2d.dispose();
        }
    }

}