【问题标题】:Randomly Generating a shape随机生成形状
【发布时间】:2013-10-08 03:31:49
【问题描述】:

我正在开发一个 Java 屏幕保护程序项目,到目前为止我已经完成了很多工作。我需要代码在随机位置生成随机颜色的随机形状。我相信我已经处理了所有随机方面,但现在我只需要使用计时器以 500 毫秒的间隔创建这些形状。我还需要创建一个计数器来计算 30 个形状,然后清除屏幕并重新开始。 (我为项目的其他部分添加了背景和 keylistener,但它们工作得很好,以防有人想知道他们为什么在那里)。

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

public class ScreenSaver1 extends JPanel implements ActionListener {
    private JFrame frame = new JFrame("FullSize");
    private Rectangle rectangle;
    Timer t;
    int x1, y1;
    boolean full;

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int shape;
        shape = (int)(Math.random() * 4);
    }

    ScreenSaver1() {
        t = new Timer(500, this);
        t.setDelay(500);
        t.start();
        // Remove the title bar, min, max, close stuff
        frame.setUndecorated(true);
        // Add a Key Listener to the frame
        frame.addKeyListener(new KeyHandler());
        // Add this panel object to the frame
        frame.add(this);
        // Get the dimensions of the screen
        rectangle = GraphicsEnvironment.getLocalGraphicsEnvironment()
        .getDefaultScreenDevice().getDefaultConfiguration().getBounds();
        // Set the size of the frame to the size of the screen
        frame.setSize(rectangle.width, rectangle.height);
        frame.setVisible(true);
        // Remember that we are currently at full size
        full = true;
    }


// This method will run when any key is pressed in the window
class KeyHandler extends KeyAdapter {
    public void keyPressed(KeyEvent e) {
        // Terminate the program.
        if (e.getKeyChar() == 'x') {
            System.out.println("Exiting");
            System.exit(0);
        }
        else if (e.getKeyChar() == 'r') {
            System.out.println("Change background color");
            setBackground(new Color((int)(Math.random() * 256), (int)(Math.random() * 256), (int)(Math.random() * 256)));
            repaint();
        }
        else if (e.getKeyChar() == 'z') {
            System.out.println("Resizing");
            frame.setSize((int)rectangle.getWidth() / 2, (int)rectangle.getHeight());
        }
    }

}

private void makeLine(Graphics g) {
    int x = (int)(Math.random() * rectangle.getWidth());
    int y = (int)(Math.random() * rectangle.getHeight());
    int x1 = (int)(Math.random() * 100);
    int y1 = (int)(Math.random() * 100);
    g.setColor(new Color((int)(Math.random() * 256), (int)(Math.random() * 256), (int)(Math.random() * 256) ));
    g.drawLine(x, y, x1, y1);
}

private void makeRect(Graphics g) {
    int x = (int)(Math.random() * rectangle.getWidth());
    int y = (int)(Math.random() * rectangle.getHeight());
    int width = (int)(Math.random() * 100);
    int height = (int)(Math.random() * 100);
    g.setColor(new Color((int)(Math.random() * 256), (int)(Math.random() * 256), (int)(Math.random() * 256) ));
    g.drawRect(x, y, width, height);
}

private void makeOval(Graphics g) {
    int x = (int)(Math.random() * rectangle.getWidth());
    int y = (int)(Math.random() * rectangle.getHeight());
    int width = (int)(Math.random() * 100);
    int height = (int)(Math.random() * 100);
    g.setColor(new Color((int)(Math.random() * 256), (int)(Math.random() * 256), (int)(Math.random() * 256) ));
    g.drawOval(x, y, width, height);
}

private void makeRoundRect(Graphics g) {
    int x = (int)(Math.random() * rectangle.getWidth());
    int y = (int)(Math.random() * rectangle.getHeight());
    int width = (int)(Math.random() * 100);
    int height = (int)(Math.random() * 100);
    int arcWidth = (int)(Math.random() * width);
    int arcHeight = (int)(Math.random() * height);
    g.setColor(new Color((int)(Math.random() * 256), (int)(Math.random() * 256), (int)(Math.random() * 256) ));
    g.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
}

public static void main(String[] args) {
        ScreenSaver1 obj = new ScreenSaver1();
    }
}

【问题讨论】:

    标签: java timer count


    【解决方案1】:

    你不会喜欢我的,但我建议你稍微支持一下……

    首先,Java 提供了一个非常好的基本Shape 接口,它定义了应该如何呈现“形状”(以及其他内容),因此我建议您从这个完全重新发明轮子开始。

    接下来,您需要某种对象来包装Shape(具有位置和大小信息)和Color,例如...

    public class RandomShape {
    
        private final Color color;
        private final Shape shape;
    
        public RandomShape(Color color, Shape shape) {
            this.color = color;
            this.shape = shape;
        }
    
        public Color getColor() {
            return color;
        }
    
        public Shape getShape() {
            return shape;
        }
    
        public void paint(Graphics2D g2d) {
            g2d.setColor(color);
            g2d.draw(shape);
            g2d.fill(shape);
        }
    
    }
    

    这甚至有自己绘画的能力。

    接下来,我将创建一个List 来包含这些形状...

    private List<RandomShape> shapes;
    

    这不仅可以作为您的计数器,还可以让更新屏幕变得异常简单。当 shapes List 包含 30 个或更多项目时,您只需将其清除并重新绘制屏幕...

    接下来,你需要一个javax.swing.Timer,用于触发更新...

    这个计时器应该...

    检查shapes列表是否需要清除...

    随机生成Color...

    int r = (int) (Math.random() * 255);
    int g = (int) (Math.random() * 255);
    int b = (int) (Math.random() * 255);
    Color color = new Color(r, g, b);
    

    随机生成形状的大小和位置...

    int width = 10 + (int) (Math.random() * 40);
    int height = 10 + (int) (Math.random() * 40);
    int x = (int) (Math.random() * (getWidth() - width));
    int y = (int) (Math.random() * (getHeight() - height));
    

    随机生成底层基本形状...

    Shape shape = null;
    switch (whichShape) {
        case 0:
            shape = new Line2D.Double(x, y, x + width, y + height);
            break;
        case 1:
            shape = new Rectangle2D.Double(x, y, width, height);
            break;
        case 2:
            shape = new Ellipse2D.Double(x, y, width, height);
            break;
    }
    

    创建RandomShape,将其添加到列表中并重新绘制组件...

    RandomShape randomShape = new RandomShape(color, shape);
    shapes.add(randomShape);
    repaint();
    

    简单;)

    现在,当您需要绘制组件时,您只需遍历形状列表...

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        for (RandomShape shape : shapes) {
            shape.paint(g2d);
        }
        g2d.dispose();
    }
    

    看看How to use Swing TimersWorking with Geometry

    【讨论】:

    • 我不会恨​​你试图帮助我。到目前为止,我相信你也帮助了我几次。唯一的问题是你使用了一个开关,这是一个循环,我不允许使用循环。
    • switch 不是循环,它是一种条件分支,例如 if。事实上,如果你想把它写出来,你可以将switch 改为if 语句。循环包括fordowhile。坦率地说,如果没有至少一个循环,您将无法完成此操作
    • 我不知道我是怎么开始认为 switch 和 if-else 是循环的。
    • 啊哈@MadProgrammer,他依赖于现有的AWT事件调度循环和定时器/处理程序..所以他不需要任何自己的循环!不过你是对的,因为 switch 不是循环并且是完全允许的。 MadProgrammer 的建议是OO 方法,绝对是可行的方法。 +1。
    • @ThomasW 此示例在 paintComponent 方法中使用 1 个循环。我对如何摆脱它有一个“想法”,但这比我提供的要复杂得多,而且灵活性较低;)
    【解决方案2】:

    查看Playing With Shapes,了解一种允许您将形状用作真实组件的方法。然后您只需将组件添加到面板中,您就不必担心自定义绘画。

    【讨论】:

      【解决方案3】:

      您可以在不使用这样的循环的情况下绘制所有形状

      private void paintAllShapes(Graphics g, int n) {
          if(n < shapes.size()) {
              shapes.get(n).paint((Graphics2D)g);
              paintAllShapes(g, n+1);
          }
      }
      
      protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          paintAllShapes(g, 0);
      }
      

      【讨论】:

        猜你喜欢
        • 2017-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-30
        • 1970-01-01
        • 1970-01-01
        • 2010-09-07
        相关资源
        最近更新 更多