![](/img/trans.png)
[英]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.