Расположение холста SWT - PullRequest
1 голос
/ 02 мая 2009

Я использую самую последнюю стабильную версию SWT.

У меня есть оболочка, содержащая панель инструментов, ScrolledComposite и Canvas. Canvas устанавливается как содержимое ScrolledComposite (например, scrolledComposite.setContent (canvas)). Холст создается с определенным размером, который никогда не изменяется (скажем, 400 x 400). Принимая во внимание, что ScrolledComposite постоянно увеличивается или уменьшается, чтобы заполнить клиентскую область доступной родительской оболочки.

У меня есть прослушиватель изменения размера, подключенный к родительской оболочке, который пытается сделать следующее: а) увеличить ScrolledComposite, как описано выше, и б) центрировать холст по горизонтали и вертикали в ScrolledComposite (см. Пример кода ниже).

Это работает точно так же, как и в Mac OS X, однако в Windows происходит событие resize, и новые местоположения рассчитываются правильно, но в конечном итоге Canvas возвращается к 0,0. Еще одна небольшая информация заключается в том, что если вы постоянно изменяете размер окна, вы можете видеть мерцание холста, и он выглядит так, как будто он ненадолго рисуется в правильном месте.

_shell.addListener (SWT.Resize, new Listener () {
    public void handleEvent (Event e)
    {
        int toolBarOffset = _toolBar.getSize().y;

        Rectangle clientArea = _shell.getClientArea();

        _scrollComposite.setBounds(0, toolBarOffset, clientArea.width, clientArea.height - toolBarOffset);

        Point canvasSize = _canvas.getSize();

        int canvasX = Math.max(0, (clientArea.width / 2) - (canvasSize.x / 2));
        int canvasY = Math.max(0, ((clientArea.height - toolBarOffset) / 2) - (canvasSize.y / 2));

        _canvas.setLocation(canvasX, canvasY);
    }
});

1 Ответ

1 голос
/ 26 августа 2009

Не уверен, что вы уже поняли это, но проблема в том, что ScrolledComposite всегда устанавливает содержимое в 0/0, когда оно изменяется. Я не уверен, почему ваш подход работает на OS X, и я не проверял мой пример, поскольку у меня нет Mac здесь.

Решение состоит в том, чтобы использовать композитный наполнитель, который всегда по крайней мере такой же большой, как клиентская область из ScrolledComposite. В этом наполнителе вы можете правильно центрировать холст.

Я привел небольшой пример, в качестве дополнительного бонуса он также центрирует холст, если клиентская область SC меньше, чем холст (потому что я сначала подумал, что это был ваш вопрос :))

Возможно, вам придется внести некоторые незначительные изменения, я думаю, что в OS X есть некоторые глюки с этим кодом ...

package test;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Test {

    public static void main(final String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);

        shell.setLayout( new FillLayout() );

        final ScrolledComposite sComp = new ScrolledComposite( shell, SWT.H_SCROLL | SWT.V_SCROLL );
        final Composite fillComp = new Composite( sComp, SWT.NONE );

        sComp.setLayout( new FillLayout() );

        final Canvas c = new Canvas( fillComp, SWT.DOUBLE_BUFFERED );
        c.addPaintListener( new PaintListener() {
            public void paintControl(PaintEvent e) {
                Point p = c.getSize();
                e.gc.setBackground( display.getSystemColor( SWT.COLOR_RED ));
                e.gc.fillRectangle( 0, 0, p.x, p.y );

                e.gc.setBackground( display.getSystemColor( SWT.COLOR_BLUE ));
                e.gc.fillRectangle( p.x / 2 - 10, p.y / 2 - 10, 20, 20 );
            }
        });

        c.setSize( 400, 400 );
        sComp.setContent( fillComp );

        sComp.addControlListener( new ControlAdapter() {
            @Override
            public void controlResized(ControlEvent e) {
                Rectangle clientArea = sComp.getClientArea();

                Point cSize = c.getSize();
                int fillX = Math.max( clientArea.width, cSize.x );
                int fillY = Math.max( clientArea.height, cSize.y );
                fillComp.setSize( fillX, fillY );

                int cX = ( clientArea.width - cSize.x ) / 2;
                int cY = ( clientArea.height - cSize.y ) / 2;

                sComp.setOrigin( -cX, -cY );

                int locX = Math.max( cX, 0 );
                int locY = Math.max( cY, 0 );
                c.setLocation( locX, locY );
            }
        });

        shell.open();
        shell.pack();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }   
    }
}
...