java - 将绘画保持在 JPanel 边框内

标签 java swing jpanel border-layout

所以问题是:我的程序到目前为止工作正常,但是这段代码没有按预期工作:

pane2 = (new JPanel(){

        private static final long serialVersionUID = 1L;

        @Override
        public void paintComponent(Graphics g){

            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            Ellipse2D.Double circle = new Ellipse2D.Double(randomX,
                                                           randomY,
                                                           randomW,
                                                           randomH);
            g2d.fill(circle);
        }
    });

    pane2.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(10,10,10,10), new LineBorder(Color.BLACK)));

所以程序应该做的基本上是重新绘制面板的内容,基本上是在每次按下“绘制”按钮时随机化椭圆的绘制位置。它可以工作,但它不会将椭圆保留在面板的边界内。是否可以在不添加某种额外层(例如容器或其他东西)并向容器添加填充的情况下完成这项工作,或者这是唯一的方法(甚至可以这样做)?

按钮代码:

bpaint.addActionListener(new ActionListener(){

                @Override
                public void actionPerformed(ActionEvent e) {

                    randomX = Math.random() * pane2.getHeight();
                    randomY = Math.random() * pane2.getWidth();
                    randomW = Math.random() * 100;
                    randomH = Math.random() * 100;
                    pane2.validate();
                    pane2.repaint();
                }

            });

如果某个地方有重复的问题,我深表歉意。如果有的话,它的措辞肯定不会让我知道它是重复的。

我也尝试过添加全局填充变量,但由于 EmptyBorder(units) 与 Ellipse2D(units) 使用的大小不同,因此添加全局填充变量是一种转变充其量是解决方案,我只能大概估计这个比例。我认为(或者至少希望)有一种更简单的方法可以将它们保持在边界内 - 准确

最佳答案

基本上,JComponent#getInsets将返回组件边框插入。

这是您不应该绘制的每个边缘的空间量,例如将它们视为边距...

因此,有了这些信息,您可以做一些类似的事情......

// Random size, minimum size of 10, maximum size of 50
randomW = 10 + (Math.random() * 40);
randomH = 10 + (Math.random() * 40);

// Get the components insets
Insets insets = getInsets();
// Calculate the available size by subtract the sum of the margins...
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.top + insets.bottom);

// Calculate a postion that is at minimum, the top/left margin
// but less than the available space minus the size of the shape...
randomX = insets.left + (Math.random() * (width - randomW));
randomY = insets.top + (Math.random() * (height - randomH));

抱歉,上面的代码来自以下可运行的示例...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class RandomShape extends JPanel {

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

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

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

    public class TestPane extends JPanel {

        private double randomX;
        private double randomY;
        private double randomW;
        private double randomH;

        public TestPane() {
                setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(10,10,10,10), new LineBorder(Color.BLACK)));
                Timer timer = new Timer(500, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    random();
                }
            });
            timer.start();
        }

        public void random() {

            randomW = 10 + (Math.random() * 40);
            randomH = 10 + (Math.random() * 40);

            Insets insets = getInsets();
            int width = getWidth() - (insets.left + insets.right);
            int height = getHeight() - (insets.top + insets.bottom);

            randomX = insets.left + (Math.random() * (width - randomW));
            randomY = insets.top + (Math.random() * (height - randomH));

            repaint();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            Ellipse2D.Double circle = new Ellipse2D.Double(randomX,
                            randomY,
                            randomW,
                            randomH);
            g2d.fill(circle);
            g2d.dispose();
        }

    }

}

因此您需要将这个概念拼接到您自己的代码中;)

关于java - 将绘画保持在 JPanel 边框内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20807752/

相关文章:

java - 想要创建一个通用的 AsyncTask - 如何?

java - "put"会覆盖现有值吗?

Java服务方法仅用于测试

java - 将 Jfreechart 组件中的点转换为屏幕值

Java游戏编程: JOGL vs LWJGL?

java - 使用 setBounds() 创建 GUI

java - 实现java菜单栏并打开新窗口

java - 如何使用 GridBagLayout 维护 jpanel 的尺寸大小?

java - 如何在 JFrame 中手动设置面板内按钮的位置

java - 在java中的分割 Pane 上添加jpanels