簡體   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