- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题很明显:我有一个很大的绘制命令,带有一个非常大的 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(); 之后,我似乎遇到了另一个问题。在用户移动框架后,绘画命令的第二个循环似乎无限循环。
提前致谢!
最佳答案
四件事:
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 Timers和 Worker Threads and SwingWorker了解更多详情
关于java - JPanel 由于 componentResize 和长重绘命令而黑屏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30971002/
我是一名优秀的程序员,十分优秀!