简体   繁体   中英

Paint in JPanel is painting in the wrong location and size

I'm working on a Java GUI and I have a JFrame thats 600x800 that I want to split into two portions, the top which has checkboxes for settings and is 600 x 200 and the bottom which is the "canvas" which will be painted on that is 600x600. I have a JFrame that has a JPanel that contains two other JPanels (one for the settings, the other for the canvas). I'm testing the "painting" and for some reason when I try to paint a 600x600 black rectangle, it paints a much smaller rectangle in the area that the settings JPanel occupies. Any ideas what's going on? I'm using the repaint method to call paintComponent and I've tried calling repaint in both the constructor of my JFrame and in the JPanel that is to be painted.

HPAProgram

public class HPAProgram {
    public static void main(String[] args) {
        MapWindow map = new MapWindow();        
    }
}

MapWindow

//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();

    }

}

SettingsButtonsPanel

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 == )
    }
}

MapImagePanel

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);
    }
}

The are a number of misconceptions you seem to have...

JPanel , by default uses a FlowLayout . FlowLayout makes use of each of the components preferred size to determine the size of each component. By default, a component has a preferred size of 0x0 .

The layout manager is also responsible for positing the components, so using setBounds and setLocation and setSize is counter productive.

Assuming the size is also not always possible, especially when dealing with text, as this can change size based on differences in the fonts, display drivers, rendering pipelines etc...

This is why Java makes extensive layout managers. Take a look at Laying Out Components Within a Container for more details

Update with simple example

Don't be afaird to mix layouts, using compound components with different layouts, to achieve your desired results, for example...

SimpleLayout

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();
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM