在侦听器方法中使用 GC

Use GC in listener method

我使用 this 教程创建了自定义视图。我可以在 paintControl() 方法中绘制我想要的所有内容。我想要做的是在我的 PaintListener 之外有一个 MouseMoveListener,它应该在鼠标悬停时绘制一些额外的东西:

@Override
public void createPartControl(Composite parent) {

    canvas = new Canvas(parent, SWT.NONE);
    canvas.addPaintListener(new PaintListener() {
        public void paintControl(PaintEvent e) {
            // draw something
        }
    });

    canvas.addMouseMoveListener(new MouseMoveListener() {
        @Override
        public void mouseMove(MouseEvent e) {
            system.out.println(e.x + ", e.y");
            // draw something
        }
    });
}

是否可以在 mouseMove() 方法中使用 GC,在 paintControl() 中创建的现有形状之外绘制形状?我试图将 GC 设置为实例变量并将其设置在 paintControl() 中以在 mouseOver() 中重用它,但不幸的是在这一点上它是 null

正如@Kuba 所说,您不能在 PaintEvent 之外的 GC 上绘制。

要重绘 canvas,请从鼠标事件调用其 redraw 方法,如下所示:

canvas.addMouseMoveListener( new MouseMoveListener() {
    @Override
    public void mouseMove( MouseEvent event ) {
      canvas.redraw();
    }
} );

要绘制任何控件(即可绘制的,扩展 Drawable),您需要创建 GC 的实例并使用它来绘制您需要的任何内容。不要忘记处理 GC 实例。

我已经修改了 Snippet10 来展示如何做到这一点:

private static boolean mouseDown = false;

public static void main(String[] args) {
    final Display display = new Display();
    final Shell shell = new Shell(display);
    shell.setText("Advanced Graphics");
    FontData fd = shell.getFont().getFontData()[0];
    final Font font = new Font(display, fd.getName(), 60, SWT.BOLD | SWT.ITALIC);
    final Image image = new Image(display, 640, 480);
    final Rectangle rect = image.getBounds();
    GC gc = new GC(image);
    gc.setBackground(display.getSystemColor(SWT.COLOR_RED));
    gc.fillOval(rect.x, rect.y, rect.width, rect.height);
    gc.dispose();
    shell.addListener(SWT.Paint, new Listener() {
        public void handleEvent(Event event) {
            GC gc = event.gc;               
            Transform tr = new Transform(display);
            tr.translate(50, 120);
            tr.rotate(-30);
            gc.drawImage(image, 0, 0, rect.width, rect.height, 0, 0, rect.width / 2, rect.height / 2);
            gc.setAlpha(100);
            gc.setTransform(tr);
            Path path = new Path(display);
            path.addString("SWT", 0, 0, font);
            gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN));
            gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE));
            gc.fillPath(path);
            gc.drawPath(path);
            tr.dispose();
            path.dispose();
        }           
    });
    shell.addMouseListener(new MouseListener() {
        @Override
        public void mouseUp(MouseEvent e) {
            mouseDown = false;
        }

        @Override
        public void mouseDown(MouseEvent e) {
            mouseDown = true;
        }

        @Override
        public void mouseDoubleClick(MouseEvent e) {}
    });
    shell.addMouseMoveListener(new MouseMoveListener() {
        @Override
        public void mouseMove(MouseEvent e) {
            if (!mouseDown)
                return;

            GC gc = new GC(shell);
            gc.drawPoint(e.x, e.y);
            gc.dispose();
        }
    });

    shell.setSize(shell.computeSize(rect.width / 2, rect.height / 2));
    shell.open();
    while (!shell.isDisposed()) {
        if (!display.readAndDispatch())
            display.sleep();
    }
    image.dispose();
    font.dispose();
    display.dispose();
}

注意:无论何时在控件上触发绘画事件,您的自定义绘图都会丢失。所以也许最好在图像上绘图。然后在控件上调用重绘,它始终假定它必须绘制背景,然后在背景上绘制该图像。这样,在每次重绘时,您都可以保持鼠标绘图。