Domanda

So I wrote a program that depending upon a given 'model' it generates a horizontal 'timeline' bar with a height of 50 pixels and a length of approx 84600 pixels. Each pixel represents a second since it is modelling events in seconds over a 24hr period.

The problem is, after 32768 pixels the bar is cut off.

I've read solutions such as using the ScrolledComposite to only display part of the canvas and make that scroll while new data is shown as the scrollbar is dragged done via buffering but I'm not familiar with how to do this at all.

Another solution I saw was without using the ScrolledComposite but just using the canvas.scroll, if my source code is run (test program to illustrate my problem) the problem is apparent that the Scrollbar does not scroll to allow the entire canvas to be displayed, the test program for this 'solution' is shown below. Please help!

package canvas;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Image;
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.Display;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Event;

public class Test {
static int shellStyle = SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND | SWT.H_SCROLL;
static int canvasStyle = SWT.NO_REDRAW_RESIZE;// | SWT.H_SCROLL | SWT.V_SCROLL;

public static void main(String[] args) {
    final Display display = new Display();
    final Shell shell = new Shell(display, shellStyle);
    shell.setLayout(new FillLayout());
    shell.setBackground(display.getSystemColor((SWT.COLOR_CYAN)));
    shell.setText("Canvas Test");
    Image image;

    final Canvas canvas = new Canvas(shell, canvasStyle);       
    canvas.setLayout(new FillLayout());
    canvas.setBackground(display.getSystemColor(SWT.COLOR_WHITE));

    final Point origin = new Point(0,0);
    final ScrollBar hBar = shell.getHorizontalBar();
    Rectangle size = canvas.getBounds();
    hBar.setMaximum(size.width);
    hBar.setMinimum(0);

    // Create a paint handler for the canvas
    canvas.addPaintListener(new PaintListener() {
      public void paintControl(PaintEvent e) {
        // Do some drawing
          e.gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_YELLOW));
          e.gc.fillRectangle(100, 200, 100, 200);

          e.gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_CYAN));
          e.gc.fillRectangle(900, 200, 600, 200);

          e.gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_MAGENTA));
          e.gc.fillRectangle(500, 200, 300, 200);   

          e.gc.setBackground(display.getSystemColor(SWT.COLOR_GRAY));
          e.gc.fillRectangle(1600, 200, 300, 200);  
      }

    });

 // The below event handlers allow for horizontal scrolling functionality
    hBar.addListener(SWT.Selection, new Listener() {
        public void handleEvent(Event e) {
            int x = 0;
            int hSelection = hBar.getSelection();
            int destX = -hSelection - origin.x;
            Rectangle rect = shell.getBounds();
            canvas.scroll(destX, 0, x, 0, rect.width, rect.height, false);
            origin.x = -hSelection;     
            x = destX;
        }

    });

    shell.addListener(SWT.Resize, new Listener() {
        public void handleEvent(Event e) {
          Rectangle rect = canvas.getClientArea();
          Rectangle client = shell.getClientArea();
          hBar.setMaximum(rect.width);
          hBar.setThumb(Math.min(rect.width, client.width));
          int hPage = rect.width - client.width;
          int hSelection = hBar.getSelection();
          if (hSelection >= hPage) {
            if (hPage <= 0)
              hSelection = 0;
            origin.x = -hSelection;
          }
          shell.redraw();
        }
      });

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

}
}

EDIT: Hey thanks p12t! Just a question...this line: final Point timelineSize = new Point(84600, 50);

So does this mean that there is a "Point" for every x-axis pixel but 50 y-axis pixels down? Such as: ++++++++++

. . . . . . . . . .

So each "+ sign" is a horizontal x-axis pixel, and the 84600 'Points' are the 'periods' as shown 50 y-axis pixels down. Is my understanding on this correct? (BTW the example I shown above is illustrating 10 points)

Also in your opinion what was I doing wrong? Or I implemented it wrongly..

È stato utile?

Soluzione

Using Canvas#scroll(..) is definitely the way to go. I fixed your example to draw a scale from 0 to 84600, so it's above the "physical" limit of 32k.

import org.eclipse.swt.SWT;
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.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;

public class Test {
static int canvasStyle = SWT.NO_REDRAW_RESIZE | SWT.H_SCROLL; // | SWT.V_SCROLL;

public static void main(String[] args) {
    final Display display = new Display();
    final Shell shell = new Shell(display);
    shell.setLayout(new FillLayout());
    shell.setBackground(display.getSystemColor((SWT.COLOR_CYAN)));
    shell.setText("Canvas Test");

    final Canvas canvas = new Canvas(shell, canvasStyle);       
    canvas.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
    canvas.setBackground(display.getSystemColor(SWT.COLOR_WHITE));

    final Point timelineSize = new Point(84600, 50);
    final Point offset = new Point(0,0);
    final ScrollBar hBar = canvas.getHorizontalBar();

    // Create a paint handler for the canvas
    canvas.addPaintListener(new PaintListener() {
      public void paintControl(PaintEvent e) {
        for (int x = 100; x < timelineSize.x; x += 100)
        {
          e.gc.drawLine(x + offset.x, 0, x + offset.x, 20);
          e.gc.drawText(Integer.toString(x), x + offset.x, 30, true);
        }
      }
    });

 // The below event handlers allow for horizontal scrolling functionality
    hBar.addListener(SWT.Selection, new Listener() {
        public void handleEvent(Event e) {
            int hSelection = hBar.getSelection();
            int destX = -hSelection - offset.x;
            canvas.scroll(destX, 0, 0, 0, timelineSize.x, timelineSize.y, false);
            offset.x = -hSelection;     
        }
    });

    canvas.addListener(SWT.Resize, new Listener() {
        public void handleEvent(Event e) {
          Rectangle client = canvas.getClientArea();
          hBar.setMaximum(timelineSize.x);
          hBar.setThumb(Math.min(timelineSize.x, client.width));
          int hPage = timelineSize.y - client.width;
          int hSelection = hBar.getSelection();
          if (hSelection >= hPage) {
            if (hPage <= 0)
              hSelection = 0;
            offset.x = -hSelection;
          }
          shell.redraw();
        }
      });

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

  }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top