Как мне скопировать часть графика Zest в SWT Canvas

#java #drawing #swt #eclipse-gef #zest

#java #рисование #swt #eclipse-gef #zest

Вопрос:

Я разрабатываю новый подключаемый модуль Eclipse, используя GEF (Draw2d 3.9, Zest 1.5.0) с пользовательскими рисунками для представления некоторых данных. Сейчас я пытаюсь разработать настраиваемый вид объектива. Желаемая функциональность заключается в том, что мышь будет перетаскиваться в главное окно, а «окно просмотра объектива» будет представлять выбранную область.

Для этого я использую окно с SWT canvas для просмотра в объективе. Содержимое главного окна (графика) отображается на холсте lens. Затем я копирую другую область (может находиться за пределами видимой области) холста объектива в точку 0,0 (холста объектива). Проблема в том, что lens canvas игнорирует все, что нарисовано за пределами его видимой области, и когда я копирую вышеупомянутую область, я получаю черный цвет вместо содержимого.

Копирование содержимого графика в изображение и после этого рисование части изображения не является решением, потому что мой график может быть гигантским (> 200000 x 200000).

Ниже вы можете найти часть моего кода:

 import org.eclipse.draw2d.SWTGraphics;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.zest.core.widgets.Graph;

public class LensView {
private final Shell shell;
private final Canvas canvas;

private final Point focalPoint;
private float lensScaleFactor;
private float mainScaleFactor;

public LensView(final Graph graph, Display d) {
    this.visualizer = visualizer;
    focalPoint = new Point(0, 0);

    lensScaleFactor     = 1.0f;
    mainScaleFactor = 1.0f;

    shell = new Shell(d, SWT.SHELL_TRIM);
    shell.setSize(640, 480);
    shell.setLayout(new FillLayout());  
    canvas = new Canvas(shell, SWT.NO_REDRAW_RESIZE);
    canvas.setLayout(new FillLayout());

    canvas.addPaintListener(new PaintListener() {   
        @Override
        public void paintControl(PaintEvent e) {
            Rectangle area  = canvas.getClientArea();
            //Scale the origin to 1.0 and apply our scale factor
            float scale = lensScaleFactor/mainScaleFactor; 

            Point viewLocation = graph.getViewport().getViewLocation();
            int tmpx = normaliseDec(Math.round((focalPoint.x   viewLocation.x) * scale) - Math.round(area.width/2.0f));
            int tmpy = normaliseDec(Math.round((focalPoint.y   viewLocation.y) * scale) - Math.round(area.height/2.0f));

            GC gc = new GC(canvas);
            SWTGraphics graphics = new SWTGraphics(gc);
            graphics.scale(scale);  
            graph.getContents().paint(graphics);                

            e.gc.copyArea(tmpx, tmpy, area.width, area.height, 0, 0);

            graphics.dispose();
            gc.dispose();
        }
    });
}

public void redraw (int x, int y) {
    focalPoint.x = normaliseDec(x);
    focalPoint.y = normaliseDec(y);
    canvas.redraw();
    canvas.update();
}

private int normaliseDec (int i) {
    return i < 0 ? 0 : i;
}

}
  

Ответ №1:

Думаю, все, что вам нужно сделать, это создать объект ScaledGraphics из GC, который поставляется с paintEvent, установить коэффициент масштабирования для графики, установить прямоугольник обрезки, а затем нарисовать свой график. Что-то вроде этого (не тестировал, примерно что-то вроде этого):

 ScaledGraphics graphics = new ScaledGraphics(e.gc);
graphics.scale(scale);
graphics.setClip(new Rectangle(focalPoint, getClientArea().getSize()));
graph.getContents().paint(graphics);
graphics.dispose();
  

Несколько моментов:
— ScaledGraphics должна выполнить масштабирование обтравочного прямоугольника за вас
— Следует рисовать на элементах управления GC, а не создавать новый

Комментарии:

1. Здравствуйте, спасибо за помощь, но, к сожалению, это не сработало. Метод setClip обрезает одну определенную область, но не переносит ее на 0, 0 холста объектива 🙁 .

2. Да, действительно, вам нужно было бы выполнить перевод, прежде чем начинать рисовать. Вызовите graphics.translate(-myX, -myY)

3. Я хотел бы поблагодарить вас за вашу ценную помощь. Метод graphics.translate был решением моей проблемы ;).