gpt4 book ai didi

java - JPanel 由于 componentResize 和长重绘命令而黑屏

转载 作者:行者123 更新时间:2023-12-01 18:13:47 33 4
gpt4 key购买 nike

问题很明显:我有一个很大的绘制命令,带有一个非常大的 for 循环和一个运行绘制命令大量时间的 componentResized,这使得我的 JPanel 黑屏,即使按下x 按钮(我必须在 eclipse 上终止它),如下所示:

package Testing;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class DrawTest extends JPanel implements ComponentListener {
public DrawTest(){
this.addComponentListener(this);
}
@Override
public void paint(Graphics g) {
int gridsize=8;
double width=getWidth()/gridsize;
for(double i=0;i<=getWidth();i+=width){
System.out.println("1");
g.drawLine((int)i,0,(int)i,getHeight());
}

double height=getHeight()/gridsize;
for(double i=0;i<=getHeight();i+=height){
System.out.println("2");
g.drawLine(0,(int)i,getWidth(),(int)i);
}
}
public static void main(String[] args){
JFrame frame=new JFrame("Fill all the squares with Ls");
DrawTest FillSquare=new DrawTest();
frame.add(FillSquare);
frame.setExtendedState( frame.getExtendedState()|frame.MAXIMIZED_BOTH );
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

@Override
public void componentHidden(ComponentEvent e) {
// TODO Auto-generated method stub

}

@Override
public void componentMoved(ComponentEvent e) {
// TODO Auto-generated method stub

}

@Override
public void componentResized(ComponentEvent e) {
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...

System.out.println("Reading SMTP Info.");
}
};
Timer timer = new Timer(100 ,taskPerformer);
timer.setRepeats(false);
timer.start();
repaint();

}

@Override
public void componentShown(ComponentEvent e) {
// TODO Auto-generated method stub

}
}

我用谷歌搜索了这个问题,并在 stackoverthrow 上查找了它,结果是使用 Timer 来防止 componentResize 在用户调整屏幕大小时运行疯狂的次数,但在实现它之后,如代码,它似乎仍然不起作用。不知道是我做错了还是怎么的,我是第一次使用。在玩弄并测试 System.out.println(); 之后,我似乎遇到了另一个问题。在用户移动框架后,绘画命令的第二个循环似乎无限循环。 enter image description here

提前致谢!

最佳答案

四件事:

  • 不要这样做 for(int i=1;i<=100000;i++){里面paint方法。 Paint 方法应该尽快返回,否则,您最终会遇到像现在这样的问题。考虑缓冲输出,这样您就不必重复更新并浪费时间。
  • 调用 super.paint在进行任何自定义绘画之前
  • 覆盖paintComponent而不是paint (并在进行任何自定义绘画之前调用 super.paintComponent)
  • 每次componentResized被调用,您正在创建另一个 Timer ,因此如果它被调用 100 次,您将创建一个 100 Timer s,这不会很好地扩展

作为一种可能的解决方案,您“不需要”使用 ComponentListener ,我倾向于覆盖 invalidate ,但使用任一方法都会得到相似的结果。

您应该使用 BufferedImage代表你想要画的东西,这样,如果 paint由于某种原因调用方法,而不是调整组件大小,您可以只绘制 BufferedImage不用担心必须从头开始重新创建整个状态。

您只需要一个 Timer ,每次通知您组件已更改时都会重新启动。

Timer会触发ActionListener ,您将使当前缓冲区无效并重新生成它。我提供的示例使用 SwingWorker将工作卸载到后台线程,这将允许 UI 在缓冲区更新时保持响应。您可以在 paintComponent 中显示一条小消息当缓冲区为 null 时的方法说明输出已重新生成,作为一个想法

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 java.awt.image.BufferedImage;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DrawTest extends JPanel {

private Timer resizeTimer;
private BufferedImage buffer;
private SwingWorker<BufferedImage, BufferedImage> bufferGenerator;

public DrawTest() {
resizeTimer = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {

buffer = null;

if (bufferGenerator != null) {
bufferGenerator.cancel(true);
}

// Create buffer in background
bufferGenerator = new BufferGeneratorWorker();
bufferGenerator.execute();
}
});
resizeTimer.setRepeats(false);
}

@Override
public void invalidate() {
super.invalidate();
resizeTimer.restart();
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (buffer != null) {
g.drawImage(buffer, 0, 0, this);
}
}

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

protected class BufferGeneratorWorker extends SwingWorker<BufferedImage, BufferedImage> {

@Override
protected BufferedImage doInBackground() throws Exception {
BufferedImage img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
System.out.println("-- Started");
int i = 0;
while (i < 100000 && !Thread.currentThread().isInterrupted()) {
i++;
g2d.drawLine(0, i, getWidth(), i);
}
g2d.dispose();
System.out.println("-- Completed");
return img;
}

@Override
protected void done() {
try {
buffer = get();
repaint();
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
}

}

public static void main(String[] args) {
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("Fill all the squares with Ls");
DrawTest FillSquare = new DrawTest();
frame.add(FillSquare);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}

public class TestPane extends JPanel {

public TestPane() {
}

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

protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}

}
}

看看Painting in AWT and Swing , Performing Custom Painting , How to use Swing TimersWorker Threads and SwingWorker了解更多详情

关于java - JPanel 由于 componentResize 和长重绘命令而黑屏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30971002/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com