使用JComboBox生成具有随机尺寸的特定形状以选择形状

时间:2015-09-23 21:21:40

标签: java swing jcombobox paintcomponent repaint

我正在尝试创建一个使用包含特定形状(圆形,方形,椭圆形,矩形)的JComboBox的程序。用户单击指定的形状后,Panel将以随机尺寸和位置显示该形状的20个。

我在如何使形状具有随机尺寸和位置方面遇到麻烦。到目前为止,这是我的代码。任何建议或来源,将不胜感激。

谢谢。

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.awt.event.*;

public class HW1b extends JFrame 
{


public HW1b()
{

    super("Shapes"); 

    final ComboPanel comboPanel = new ComboPanel();
    String[] shapeItems = {"Circle", "Square", "Oval", "Rectangle"}; 

    JComboBox shapeBox = new JComboBox<String>(shapeItems); 
    shapeBox.addItemListener(new ItemListener()
    {

        public void itemStateChanged(ItemEvent ie)
        {

            if (ie.getStateChange() == ItemEvent.SELECTED)
            {
                String item = (String)ie.getItem(); 

                if(shapeBox.getSelectedItem().equals("Circle"))
                    comboPanel.makeCircles(); 

                if(shapeBox.getSelectedItem().equals("Square"))
                    comboPanel.makeSquares(); 

                if(shapeBox.getSelectedItem().equals("Oval"))
                    comboPanel.makeOvals(); 

                if(shapeBox.getSelectedItem().equals("Rectangle"))
                    comboPanel.makeRectangles();
            }

        }

    });


    JPanel southPanel = new JPanel(); 
    southPanel.add(shapeBox);   
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    getContentPane().add(comboPanel, "Center");
    getContentPane().add(southPanel, "South"); 

    setSize( 400, 400 );
        setLocation( 200, 200 );
        setVisible( true );

}


private class ComboPanel extends JPanel
{
    int w, h;
    Random rand; 

    static final int OVAL = 0; 
    static final int RECTANGLE = 1; 
    int shapeType = -1; 

    public ComboPanel()
    {
        rand = new Random(); 
        setBackground(Color.white); 

    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g); 

        Graphics2D g2d = (Graphics2D) g; 
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                     RenderingHints.VALUE_ANTIALIAS_ON);

        int width = getWidth(); 
        int height = getHeight(); 
        int x, y; 

        Shape s = null;


        for (int i = 0; i < 20; i++)
        {
            x = rand.nextInt(width - w); 
            y = rand.nextInt(width - h); 

            switch(shapeType)
            {

                case OVAL: s = new Ellipse2D.Double(x,y,w,h); 
                    break; 

                case RECTANGLE: s = new Rectangle2D.Double(x,y,w,h); 
                    break;
            }

            if (shapeType > -1) 
                g2d.draw(s); 
        }

    }

    public void makeCircles()
    {
        shapeType = OVAL; 
        w = 75; 
        h = 75; 
        repaint(); 
    }

    public void makeSquares()
    {
        shapeType = RECTANGLE; 
        w = 50; 
        h = 50; 
        repaint(); 
    }

    public void makeOvals()
    {
        shapeType = OVAL; 
        w = 80; 
        h = 60; 
        repaint(); 
    }

    public void makeRectangles()
    {
        shapeType = RECTANGLE; 
        w = 80; 
        h = 40; 
        repaint(); 
    }

}


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

    }

}

1 个答案:

答案 0 :(得分:4)

您在代码中对wh进行了硬编码,因此您的形状无法改变。不要这样做,而是使用随机变量rand来选择在某个所需范围内的随机wh值。我自己,我不会在paintComponent方法中创建我的形状,因为绘画不完全在我的控制之下,并且可以在我不想要的时候发生。例如,在代码中,如果调整GUI大小,您的形状会有很大差异。相反,我会创建一个集合,例如ArrayList<Shape>,并在需要时用创建的Shape对象(即我的圆圈的Ellipse2D)填充它,然后在paintComponent方法中迭代遍历该集合,绘制形状。

例如......

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.*;

public class SomeShapes extends JPanel {
    private ShapePanel shapePanel = new ShapePanel();
    private JComboBox<MyShape> myShapeCombo = new JComboBox<>(MyShape.values());

    public SomeShapes() {
        myShapeCombo.setSelectedIndex(-1);
        myShapeCombo.addItemListener(new ComboListener());

        JPanel bottomPanel = new JPanel();
        bottomPanel.add(myShapeCombo);

        setLayout(new BorderLayout());
        add(shapePanel, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.PAGE_END);
    }

    private class ComboListener implements ItemListener {
        @Override
        public void itemStateChanged(ItemEvent e) {
            MyShape myShape = (MyShape) e.getItem();
            shapePanel.drawShapes(myShape);
        }
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("SomeShapes");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new SomeShapes());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

enum MyShape {
    OVAL("Oval"), RECTANGLE("Rectangle"), SQUARE("Square"), CIRCLE("Circle");
    private String name;

    private MyShape(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return getName();
    }

}

class ShapePanel extends JPanel {
    private static final int PREF_W = 600;
    private static final int PREF_H = PREF_W;
    private static final Color SHAPE_COLOR = Color.BLUE;
    private static final int SHAPE_COUNT = 20;
    private static int MIN = 5;
    private static int MAX = 200;
    private List<Shape> shapeList = new ArrayList<>();
    private Random random = new Random();

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    public void drawShapes(MyShape myShape) {
        shapeList.clear();  // empty the shapeList
        switch (myShape) {
        case OVAL:
            drawOval();
            break;
        case RECTANGLE:
            drawRectangle();
            break;
            // etc...

        default:
            break;
        }
        repaint();
    }

    private void drawOval() {
        // for loop to do this times SHAPE_COUNT(20) times.
        for (int i = 0; i < SHAPE_COUNT; i++) {
            // first create random width and height
            int w = random.nextInt(MAX - MIN) + MIN;
            int h = random.nextInt(MAX - MIN) + MIN;

            // then random location, but taking care so that it 
            // fully fits into our JPanel
            int x = random.nextInt(getWidth() - w);
            int y = random.nextInt(getHeight() - h);

            // then create new Shape and place in our shapeList.
            shapeList.add(new Ellipse2D.Double(x, y, w, h));
        }
    }

    private void drawRectangle() {
        // .... etc
    }

    //.. .. etc

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;

        // set rendering hints for smooth ovals
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setColor(SHAPE_COLOR);
        // iterate through the shapeList ArrayList
        for (Shape shape : shapeList) {
            g2d.draw(shape);  // and draw each Shape it holds
        }            
    }
}