Frage

So here is the problem: My program so far works okay, but this snippet of code does not work as intended:

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

So what the program is supposed to do is basically repaint the contents of the panel, basically randomizing where the Ellipse is painted each time with each press of the Paint button. It works, but it does not keep the ellipses within the borders of the panel. Is it possible to make that work without adding some sort extra layer like a Container or something and adding padding to the container, or is that the only way (is it even viable to do that)?

The button code:

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

            });

I apologize if there is a duplicate of this question somewhere. If there was, it certainly wasn't worded in a way where I would have known it was a duplicate.

I did also try to add a global padding variable, but since the EmptyBorder(units) are not based on the same size that Ellipse2D(units) use, adding a global padding variable is a shifty solution at best, and I can only approximate what the ratio may be. I think (or at least hope) that there is a much simpler way I can keep them within the border -- accurately.

War es hilfreich?

Lösung

Basically, JComponent#getInsets will return the components border insets.

This is the amount of space from each edge that you should not paint in, think of them as the margins for example...

So with that information in hand, you could do something like...

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

Apologies, the above code comes from the following, runnable example...

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

    }

}

So you'll need to splice the concept into your own code ;)

Andere Tipps

I don't think this is a huge issue. Just change the way you calculate the values.

randomW = Math.random() * 100;
randomH = Math.random() * 100;
randomX = Math.random() * (pane2.getHeight() - randomW) + randomW/2;
randomY = Math.random() * (pane2.getWidth() - randomH) + randomH/2;

Hope this works for you.

Edit : Changed the equations..

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top