在面板上绘制图形

时间:2019-02-21 20:46:33

标签: java swing layout jframe jpanel

我正在尝试在面板上绘制图形,但是我不确定该怎么做。

我尝试创建一个类来扩展JPanel并覆盖paintComponent和其他一些方法,但是什么都没有呈现。

这是我的代码:

edit:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Lesson1 extends JFrame {

    private static final long serialVersionUID = -198253288329146091L;
    private JPanel contentPane;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Lesson1 frame = new Lesson1();
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public Lesson1() {

        contentPane = new JPanel();
        setContentPane(contentPane);

        JPanel panel = new JPanel() {

            private static final long serialVersionUID = -5974584127539186578L;

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.GREEN);
                g.fillRect(0, 0, 500, 500);
            }

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

        };

        contentPane.add(panel);

        JPanel panel_1 = new JPanel() {

            private static final long serialVersionUID = 123456789L;

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.PINK);
                g.fillRect(0, 0, 200, 200);
            }

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

        };

        panel.setLayout(new BorderLayout());
        panel_1.setLayout(new BorderLayout());
        panel.add(panel_1);

    }

}

我不确定我在做什么错,但是我已经尽力了。谢谢!

1 个答案:

答案 0 :(得分:0)

错误#1

contentPane.setLayout(null);

panel.setLayout(null);

在执行其他任何操作之前,您需要学习并了解布局管理器的实际操作以及为什么null布局过于幼稚而不推荐使用(特别是在您只是在学习时)。

首先花一些时间进行Laying Out Components Within a Container

删除contentPane.setLayout(null);并将panel.setLayout(null);更改为panel.setLayout(new BorderLayout());,您将立即看到更改。

实际上,您确实不需要panel,因为contentPane的默认JFrame已设置为使用BorderLayout

这意味着您可以摆脱panel.setBounds(73, 52, 231, 143);

错误#2

好的,这更多是一个疏忽,但是,当您开始自定义组件时,您需要提供大小调整提示,这使布局管理器可以根据与其他组件的关系以及基于这是自己的内部规则。

为此,您至少应该重写getPreferredSize方法(避免使用setXxxSize方法,因为如果使用不正确,这些方法会导致意外结果)

添加...

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

panel_1

这现在意味着您可以做更多类似的事情...

Lesson1 frame = new Lesson1();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);

,窗口将自动将其打包在组件周围(并位于屏幕中央),您可以摆脱setBounds(100, 100, 450, 300);

  

好吧,无论如何我都尝试过但没有运气,所以我可以将面板设置在特定位置:/

GUI环境中的布局管理既是科学,又是巫毒,又是黑魔法

像素的完美定位是现代UI开发中的一种幻觉。有很多因素决定着组件应如何“放置”在单个平台上,跨多个平台,您将花费剩余的时间不断添加“ hacks”以解决无限可能边缘情况。

这就是为什么任何体面的UI框架都会抽象该概念,Swing为此使用布局管理器API,iOS(和MacOS)使用自动布局等的原因。

Example

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Lesson1 {

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        new Lesson1();
    }

    public Lesson1() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.NORTHWEST;

            add(new RectPane(), gbc);

            gbc.gridx = 2;
            gbc.anchor = GridBagConstraints.NORTHEAST;
            add(new RectPane(), gbc);

            gbc.gridx = 1;
            gbc.gridy = 1;
            gbc.anchor = GridBagConstraints.CENTER;
            gbc.weightx = 1;
            gbc.weighty = 1;
            add(new RectPane(), gbc);

            gbc.weightx = 0;
            gbc.weighty = 0;
            gbc.gridx = 0;
            gbc.gridy = 2;
            gbc.anchor = GridBagConstraints.SOUTHWEST;
            add(new RectPane(), gbc);

            gbc.gridx = 2;
            gbc.anchor = GridBagConstraints.SOUTHEAST;
            add(new RectPane(), gbc);
        }

        // This is just to demonstrate how the layout works when the avaliable
        // space is larger then the desired space, you don't need this
        // and should get rid of it and just let the layout manager calculate
        // it's desired size based on it's content
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 500);
        }

    }

    public class RectPane extends JPanel {

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.GREEN);
            g.fillRect(0, 0, 100, 100);
        }

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

    }

}

了解,GridBagLayout是标准API中最复杂的布局管理器,但它是最灵活的。您也不仅限于单个布局管理器,还可以使用复合布局来创建非常高级的界面