如何在KeyListener Java中每隔100毫秒更新SWT中的画布
我正在编写一个程序,每次按键后更新画布,方法是重新生成数据结构(立方体),然后将其绘制到画布上。如果用户每100毫秒输入“S”,我希望画布在每次旋转(旋转=程序生成的解决方案字符串的一个字符)后显示立方体,并将其重新绘制到屏幕上,我尝试了几种不同的方法,但无法使其工作。这是我的KeyListener代码:如何在KeyListener Java中每隔100毫秒更新SWT中的画布,java,canvas,swt,sleep,redraw,Java,Canvas,Swt,Sleep,Redraw,我正在编写一个程序,每次按键后更新画布,方法是重新生成数据结构(立方体),然后将其绘制到画布上。如果用户每100毫秒输入“S”,我希望画布在每次旋转(旋转=程序生成的解决方案字符串的一个字符)后显示立方体,并将其重新绘制到屏幕上,我尝试了几种不同的方法,但无法使其工作。这是我的KeyListener代码: canvas.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEve
canvas.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
GC gc = new GC(canvas);
Rectangle rect = canvas.getClientArea();
String alg = ""+e.character;
cube.performAlgorithm(alg, false);
drawCube(rect,gc);
if(e.character=='S'){
Cube cube2 = new Cube(cube);
String solution = Solutions.longsolve(cube2, "Fridrich", false);
String[] moves = new String[solution.length()];
moves = solution.split("(?!^)");
for(String move : moves){
cube.performAlgorithm(move, false);
try {
drawCube(rect,gc);
canvas.redraw();
canvas.update();
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//System.out.println(solution);
}
gc.dispose();
}
});
还有我的drawFace和drawCube代码,请注意这可能不是解决我问题的好方法,但我对使用SWT非常陌生
private static void drawFace(GC gc, int startwidth, int startdepth, int celldim, Color[] colour, byte[][] Face){
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
int x = startwidth;
int y = startdepth;
//draw face of the cube
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
Rectangle rect = new Rectangle(x, y, celldim, celldim);
gc.setBackground(colour[Face[i][j]]);
gc.fillRectangle(rect);
gc.drawRectangle(rect);
x += celldim;
//only draw a box
}
x = startwidth;
y+=celldim;
}
}
private static void drawCube(Rectangle clientArea, GC gc){
int startdepth = 10;
int celldim = (((clientArea.height)-(startdepth*2))/12);
int startwidth = (int) ((int)(clientArea.width/2)-(1.5*celldim));
Color[] colours = {gc.getDevice().getSystemColor(SWT.COLOR_GREEN),gc.getDevice().getSystemColor(SWT.COLOR_RED),
gc.getDevice().getSystemColor(SWT.COLOR_BLUE),gc.getDevice().getSystemColor(SWT.COLOR_GRAY),
gc.getDevice().getSystemColor(SWT.COLOR_BLACK),gc.getDevice().getSystemColor(SWT.COLOR_YELLOW)};
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
int x = startwidth;
int y = startdepth;
drawFace(gc, x, y, celldim,colours,cube.Uface);
y += (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Fface);
x -= (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Lface);
x += (6*celldim);
drawFace(gc, x, y, celldim,colours,cube.Rface);
x -= (3*celldim);
y += (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Dface);
y += (3*celldim);
drawFace(gc, x, y, celldim,colours,cube.Bface);
}
private static void drawFace(GC-GC、int-startwidth、int-startdepth、int-celldim、Color[]Color、byte[]Face){
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_-WHITE));
int x=起始宽度;
int y=起始深度;
//画立方体的面
对于(int i=0;i您不能在这样的循环中进行更新,因为您必须让主SWT显示。readAndDispatch
循环运行,因为这是实际更新屏幕的内容
而是使用Display.timerExec
每100ms执行一个循环步骤:
Display.getDefault().timerExec(100, new Runnable() {
@Override
public void run() {
canvas.redraw();
// Run again - TODO add logic to stop after correct number of moves
Display.getDefault().timerExec(100, this);
}
});
您只需调用redraw
,在这个例程中,所有实际的绘图都应该在控件的绘制侦听器中。当前它执行整个for循环、sleep和all,但不更新画布,然后在完成后重新绘制(因此没有中间步骤)谢谢你的回答,那么这个Display.timerExec可以进入我的密钥侦听器吗?是的,你可以在侦听器中调用它。嘿,很抱歉再次打扰,但我尝试了这个,但仍然没有运气,它仍然执行完整的解算,然后重新绘制多维数据集。也就是说,不按移动更新移动。我使用额外的行Display.getDefault().timerExec进行了尝试(1000,这个);但这导致了同样的事情发生,然后在.for(String move:moves){Display.getDefault().timerExec(1000,new Runnable(){@Override public void run(){GC GC=new GC(canvas);cube.performAlgorithm(move,false);drawCube(rect,GC);canvas.redraw();System.out.println(move);}})之后进入无限循环您在keylistener中调用timerExec一次。当延迟代码运行时,您将在最后再次调用它,直到完成移动数-您必须将代码添加到我的示例中以跟踪移动数。我还告诉过您只需进行重绘
。您必须使用PaintListener进行实际绘制。非常感谢您的帮助,现在就让它工作吧!