问题很明显:我有一个很大的绘制命令,有一个非常大的for循环和一个componentResized运行paint命令大量的时间,这使我的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();进行游戏并进行测试后,我似乎遇到了另一个问题。用户移动框架后,paint命令的第二个循环似乎无限地进行。
提前致谢!
答案 0 :(得分:4)
四件事:
for(int i=1;i<=100000;i++){
方法中执行paint
。绘画方法应尽快返回,否则,您最终会遇到类似于现在的问题。考虑缓冲输出,这样你就不会反复更新它并浪费时间。super.paint
paintComponent
而不是paint
(并在进行任何自定义绘画之前调用super.paintComponent
)componentResized
时,您都会创建另一个Timer
,因此,如果它被调用了100次,那么您将创建一个100 Timer
,这不会规模很好作为一种可能的解决方案,您不需要使用ComponentListener
,我倾向于覆盖invalidate
,但您可以使用其中任何一种获得类似的结果。
您应该使用BufferedImage
来表示您想要绘制的内容,这样,如果由于某种原因而调用了paint
方法,则只需调整组件的大小,您可以只绘制{{1并且不用担心必须从头开始重建整个状态。
您只需要一个BufferedImage
,每当您收到有关该组件已更改的通知时,都会重新启动。{/ p>
当Timer
触发Timer
时,您将使当前缓冲区无效并重新生成它。我提供的示例使用ActionListener
将工作卸载到后台线程,这将允许UI在缓冲区更新时保持响应。当缓冲区为SwingWorker
表明输出已重新生成时,您可以在paintComponent
方法中显示一条消息
null
查看Painting in AWT and Swing,Performing Custom Painting,How to use Swing Timers和Worker Threads and SwingWorker了解详情