SWT Canvas 无法在 Windows 上重绘,但可以在 Linux 上运行

SWT Canvas fails to redraw on Windows but works on Linux

this.canvas = new Canvas(shell, SWT.NO_BACKGROUND);

我正在使用 PaintListener:

this.canvas.addPaintListener(new PaintListener() {

    @Override
    public void paintControl(PaintEvent e) {
        // Draw images
        synchronized (imageMarks) {
            for (ImageMark mark : Whiteboard.this.imageMarks)
            {
                Image image = Whiteboard.this.getImage(mark.id);
                Point position = ScaledPoint.toSWTPoint(Whiteboard.this.getCanvasSize(), mark.getPosition());
                Point bounds = mark.getUnscaledBoundaries(Whiteboard.this.getCanvasSize());
                e.gc.drawImage(image, 0, 0, image.getBounds().width, image.getBounds().height, position.x, position.y, 
                        bounds.x, bounds.y);
            }
        }

        // Draw pencil marks
        synchronized (pencilMarks) {
            e.gc.setLineWidth(LINE_WIDTH);
            for (double[] line : Whiteboard.this.pencilMarks)
            {
                Point lastPosPoint = ScaledPoint.toSWTPoint(Whiteboard.this.getCanvasSize(), new ScaledPoint(line[0], line[2]));
                Point newPosPoint = ScaledPoint.toSWTPoint(Whiteboard.this.getCanvasSize(), new ScaledPoint(line[1], line[3]));
                e.gc.drawLine(lastPosPoint.x, lastPosPoint.y, newPosPoint.x, newPosPoint.y);
            }
        }

        // Draw pointer, assuming it's there
        if (pointerMark != null)
        {
            synchronized (pointerMark) {
                Point pos = ScaledPoint.toSWTPoint(Whiteboard.this.getCanvasSize(), pointerMark.getPosition());
                if (pointerMark.isFlipped())
                    e.gc.drawImage(Whiteboard.pointerImageFlipped, pos.x, pos.y);
                else
                    e.gc.drawImage(Whiteboard.pointerImage, pos.x, pos.y);
            }
        }
    }
});

并通过 canvas.redraw() 调用重绘 canvas。在 64 位 Linux 上,这似乎没有任何问题,但奇怪的是,在 64 位 Windows 上,没有任何东西最终被擦除或重绘。例如,如果调整屏幕大小,铅笔标记也不会调整大小,它们最终会被剪切出屏幕。当添加新标记时(换句话说,当再次调用绘制侦听器时),重新定位的标记将在未随 window 缩放的旧标记之上重新绘制。换句话说,我相信 canvas 没有在 canvas.redraw() 上被清除。有解决办法吗?

您正在指定 SWT.NO_BACKGROUND,这会停止在每次绘制之前清除 Canvas。

如果您使用 SWT.NO_BACKGROUND,则绘制方法负责绘制 Canvas 的每个像素。

SWT.NO_BACKGROUNDJava文档:

By default, before a widget paints, the client area is filled with the current background. When this style is specified, the background is not filled, and the application is responsible for filling every pixel of the client area. This style might be used as an alternative to "double-buffering" in order to reduce flicker. This style does not mean "transparent" - widgets that are obscured will not draw through.