繁体   English   中英

使用 repaint() 在添加到 JFrame 的 JPanel 上绘图

[英]Using repaint() to draw on JPanel which is added to JFrame

试图在屏幕上实时水平绘制我的矩形。 当我运行它时,我只得到 JFrame。 我不确定除了某种类型的线程冻结以重绘形状之外我还缺少什么?

public class ScreenTest extends JFrame {
    
    int rectY = 50;
    
    public ScreenTest()
    {
        setSize(300,200);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
        
    }
    
    private class DrawPanel extends JPanel {
        
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.GREEN);
            g.fillRect(80, rectY, 50, 50);
       }
    }
    
    public void Draw()
    {
        DrawPanel test = new DrawPanel();
        add(test);
        
        while (rectY < 200)
        {
            rectY = rectY + 10;
            test.repaint();
        }

    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ScreenTest myWindow = new ScreenTest(); 
        myWindow.Draw();
    }
    
}

Swing 是单线程的,不是线程安全的。

这意味着,您不应在“事件调度线程”中执行任何类型的长时间运行或阻塞操作,因为这将阻止 UI 被绘制或响应新事件。

这也意味着您不应从事件调度线程的上下文之外更新 UI 或 UI 所依赖的任何 state。

您的代码“正在”工作,但是因为while-loop可以运行得如此之快,所以它在 window 在屏幕上实现之前完成(可见且可更新)。 Swing 也进行了优化,因此所有repaint调用都可能合并到一个重绘通道中。

更好的解决方案可能从 Swing `Timer 开始,它充当伪重复循环,但在事件调度线程的上下文中调用。

首先查看Swing 中的并发以及如何使用 Swing 计时器以了解更多详细信息。

可运行示例

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

public class ScreenTest extends JFrame {

    public ScreenTest() {
        setSize(300, 200);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

    }

    private class DrawPanel extends JPanel {

        int rectY = 50;
        private Timer timer;

        // This is just convince 
        @Override
        public void addNotify() {
            super.addNotify();
            timer = new Timer(25, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    rectY += 1;
                    repaint();
                }
            });
            // Otherwise it disappears to fast
            timer.setInitialDelay(1000);
            timer.start();
        }

        @Override
        public void removeNotify() {
            super.removeNotify();
            timer.stop();
            timer = null;
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.GREEN);
            g.fillRect(80, rectY, 50, 50);
        }
    }

    public void Draw() {
        DrawPanel test = new DrawPanel();
        add(test);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                ScreenTest myWindow = new ScreenTest();
                myWindow.Draw();
            }
        });
    }

}

它正在工作,但速度太快以至于你看不到它,你需要使改变 Y 坐标的循环变慢并延迟。 为了解决这个问题,我在 while 循环中使用了 Thread.sleep():

package paquete;

import javax.swing.*;
import java.awt.*;

public class ScreenTest extends JFrame {

    int rectY = 50;

    public ScreenTest()
    {
        setSize(300,200);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

    }

    private class DrawPanel extends JPanel {

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.GREEN);
            g.fillRect(80, rectY, 50, 50);
        }
    }

    public void Draw() throws InterruptedException {
        DrawPanel test = new DrawPanel();
        add(test);

        while (rectY < 200)
        {
            rectY = rectY + 10;
            Thread.sleep(100);
            test.repaint();
        }

    }

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        ScreenTest myWindow = new ScreenTest();
        myWindow.Draw();
    }

}

我希望这对您有所帮助,您可以更改持续时间,更改 Thread.sleep() 参数中的数字

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM