SWT Java:Canvas 上的图像矩形选择,无需快速重绘

SWT Java: Rectangular Selection over Image on Canvas without rapid repaint

我在 canvas 上有一张图片:

    canvas = new Canvas(top, SWT.V_SCROLL | SWT.H_SCROLL | SWT.NO_REDRAW_RESIZE);
    GridData canvasGridData = new GridData(GridData.VERTICAL_ALIGN_FILL);
    canvasGridData.verticalSpan = 15;
    canvasGridData.horizontalAlignment = GridData.FILL;
    canvasGridData.verticalAlignment = GridData.FILL;
    canvasGridData.grabExcessHorizontalSpace = true;
    canvasGridData.grabExcessVerticalSpace = true;
    canvas.setLayoutData(canvasGridData);
    canvas.addPaintListener(new PaintListener() {
        public void paintControl(PaintEvent e) {
            if (buttonPressed) {
                GC gc = e.gc;
                image = GetMyImagetoDisplay();
                gc.drawImage(image, 10, 10);
            }
        }
    });

按下 GUI 按钮时,调用 reDraw() 并加载图像。

我还有一个用于获取矩形选区的鼠标事件。他们在图像上绘制一个矩形选区: canvas.addListener(SWT.MouseDown, new Listener() {

        @Override
        public void handleEvent(Event event) {
            startX = event.x;
            startY = event.y;

            drag = true;
        }
    });

    canvas.addListener(SWT.MouseUp, new Listener() {

        @Override
        public void handleEvent(Event event) {
            endX = event.x;
            endY = event.y;

            drag = false;

            canvas.redraw();
        }
    });

    canvas.addListener(SWT.MouseMove, new Listener() {

        @Override
        public void handleEvent(Event event) {


            if(drag)
            {
                endX = event.x;
                endY = event.y;


                canvas.redraw();
            }
        }
    });

    canvas.addListener(SWT.Paint, new Listener() {

        @Override
        public void handleEvent(Event event) {
            if(drag)
            {
                GC gc = event.gc;

                //gc.setBackground(top.getDefault().getSystemColor(SWT.COLOR_BLACK));
                gc.setAlpha(128);

                int minX = Math.min(startX, endX);
                int minY = Math.min(startY, endY);

                int maxX = Math.max(startX, endX);
                int maxY = Math.max(startY, endY);

                int width = maxX - minX;
                int height = maxY - minY;

                gc.fillRectangle(minX, minY, width, height);
            }
        }
    });

问题是,当我拖动鼠标时,图像一直在闪烁。

你能提出修复建议吗?

更新:

通过将 SWT.DOUBLE_BUFFERED 传递给 Canvas 构造函数,它启用了双缓冲!!!

imageCanvas = new Canvas(top, SWT.V_SCROLL | SWT.H_SCROLL | SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED);

看起来您正在向同一个 Canvas 添加两个 SWT.Paint 侦听器,并且他们正在相互竞争。

您的第一个听众绘制 "background",第二个听众绘制 "foreground"。你看到的闪烁,很有可能是他们两个在交替作画。

考虑这样的事情,只有一个绘画监听器:

canvas.addListener(SWT.Paint, new Listener() {
    @Override
    public void handleEvent(Event event)
    {
        // paint background

        if(drag)
        {
            // paint foreground
        }
    }
});

如果这没有任何改变,请尝试使用 SWT.DOUBLE_BUFFERED 作为 Canvas 的样式。

回答这个问题很简单!!!通过将 SWT.DOUBLE_BUFFERED 传递给 Canvas 构造函数,它启用了双缓冲!!!

imageCanvas = new Canvas(top, SWT.V_SCROLL | SWT.H_SCROLL | SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED);

这完全消除了闪烁效果