使用图形向下移动矩形

时间:2019-09-10 20:34:49

标签: java graphics 2d

我是Java的新手,我想在JFrame中向下移动一个矩形。我想看看这个动作。

为什么我看不到矩形向下移动?我必须使用其他图书馆还是什么?

import java.awt.Color;
import java.awt.Graphics;

import java.lang.Thread;

import javax.swing.JComponent;

public class Draw extends JComponent {

    public void paintComponent(Graphics g) {
        g.setColor(new Color(0, 128, 128, 128));

        try {
            for(int i = 70; i < 100; i++) {
                g.fillRect(40, i, 100, 70);
                Thread.sleep(10); // To see the moviment.
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

}

import javax.swing.JFrame;

public class Main extends JFrame {
    public Main() {
        setSize(300, 200);

        Draw draw = new Draw();
        add(draw);
    }

    public static void main(String[] args) {
        Main m = new Main();
        m.setVisible(true);
    }
}

2 个答案:

答案 0 :(得分:0)

Swing是单线程的

这意味着,如果您在事件调度线程的上下文中执行任何长时间运行或阻塞的操作,则将阻止Swing使用输入执行任何绘画操作或处理

Swing不是线程安全的

这意味着您永远不要尝试从事件调度线程的上下文之外尝试更新UI或UI依赖的任何状态,这会使您陷入各种怪异和不可预测的状态

有关更多详细信息,请参见Concurrency in Swing

一个简单的解决方案...

例如,可能最简单的解决方案是使用Swing Timer ...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {

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

    public Main() {
        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 Draw());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class Draw extends JPanel {

        private int yPos = 0;

        public Draw() {
            Timer timer = new Timer(10, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent evt) {
                    yPos += 1;
                    repaint();
                }
            });
            timer.start();
        }

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

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(new Color(0, 128, 128, 128));
            g2d.fillRect(40, yPos, 100, 70);
            g2d.dispose();
        }

    }
}

有关更多详细信息,请参见How to Use Swing Timers

  

为什么在JPanel上使用JComponent

为简单起见。 JPanel将自动绘制背景(使用background属性)(如果您调用super.paintComponent),从而省去了

答案 1 :(得分:-1)

您的“时间”注意事项未遵循Swing UI线程化概念。

这样想:Swing有一个Frame,您先绘制内容,然后等待更改,然后再次绘制。

建议可以是一个线程,它每隔x毫秒请求JFrame更新其内容,然后使用repaint()方法。

一个例子:

Draw() {
    new Timer().schedule(new TimerTask() {
    @Override
    public void run() {
        // Move x and y of the desired rectangle and request repaint
        x+=10;
        repaint();
    }}, 50);
}