如何在KeyListener Java中每100毫秒更新SWT中的画布

问题描述 投票:0回答:1

我正在编写一个程序,通过重新生成数据结构(立方体)然后将其绘制到画布上,在每次按键后更新画布。如果用户输入'S',我希望画布每隔100转后显示一个立方体(转换=程序生成的解字符串中的一个字符),并将其重新绘制到屏幕上,尝试了几种不同的方法但不能让它工作。这是我的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);
}
java canvas swt sleep redraw
1个回答
1
投票

你不能在这样的循环中进行更新,因为你必须让主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,所有实际绘图都应该在控件上的绘图监听器中。

© www.soinside.com 2019 - 2024. All rights reserved.