如何在 KeyListener Java 中每 100 毫秒更新一次 SWT 中的 canvas

How to update a canvas in SWT every 100 milliseconds inside a KeyListener Java

我正在编写一个程序,在每次按键后通过重新生成数据结构(立方体)然后将其绘制到 canvas 上来更新 canvas。如果用户输入 'S' 我希望 canvas 每 100 毫秒在每一回合后显示立方体(turn = 程序生成的解决方案字符串的一个字符)并将其重绘到屏幕上,已经尝试了几次不同的方法,但无法让它发挥作用。这是我的 KeyListener 代码:

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);
}

您不能像那样在循环中进行更新,因为您必须让主 SWT Display.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 在此例程中,所有实际绘图都应该在控件上的绘制侦听器中。