[英]Can not draw using paintComponent if added to Jpanel but works fine in JFrame
[英]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.