官术网_书友最值得收藏!

Time for action – creating a reusable widget

Although the ClockView shows a single animated clock, creating an independent widget will allow the clock to be reused in other places.

  1. Create a new class in the com.packtpub.e4.clock.ui package, called ClockWidget, that extends Canvas.
  2. Create a constructor that takes a Composite parent and an int style bits parameter, and pass them to the superclass:
    public ClockWidget(Composite parent, int style) {
      super(parent, style);
    }
  3. Move the implementation of the drawClock method from the ClockView to the ClockWidget. Remove the PaintListener references from the ClockView class.
  4. In the ClockWidget constructor, register a PaintListener that delegates the call to the drawClock method:
    addPaintListener(this::drawClock);
  5. Move the TickTock thread from the ClockView to the ClockWidget constructor; this will allow the ClockWidget to operate independently. Change any references for clock to this:
    Runnable redraw = () -> {
      while (!this.isDisposed()) {
        this.getDisplay().asyncExec(() -> this.redraw());
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          return;
        }
      }
    }
    new Thread(redraw, "TickTock").start();
  6. Add a computeSize method to allow the clock to have a square appearance that is the minimum of the width and height. Note that SWT.DEFAULT may be passed in, which has the value -1, so this needs to be handled explicitly:
    public Point computeSize(int w, int h, boolean changed) {
      int size;
      if (w == SWT.DEFAULT) {
        size = h;
      } else if (h == SWT.DEFAULT) {
        size = w;
      } else {
        size = Math.min(w, h);
      }
      if (size == SWT.DEFAULT) {
        size = 50;
      }
      return new Point(size, size);
    }
  7. Finally, change the ClockView to instantiate the ClockWidget instead of the Canvas in the createPartControl method:
    new ClockWidget(parent, SWT.NONE);
  8. Run the target Eclipse instance and the clock should be shown as earlier.

What just happened?

The drawing logic was moved into its own widget, and registered a PaintListener to a method in the ClockWidget to render itself. This allows the Clock to be used as a standalone in any Eclipse or SWT application.

In a real application, the clocks would not have their own thread; it would either be the case that a single Thread would control updates to all Clock instances, or they would be set up with repeating Job instances using the Eclipse jobs framework, which will be covered in Chapter 4, Interacting with the User.

The technique of using a method reference (or anonymous class) to bind a specific listener type to the instance of the class is a common pattern in SWT. When using inner classes, the convention is to use the same method name in the enclosing class; this helps to disambiguate the use.

Tip

Remember to set the listener at startup, as otherwise it can be confusing as to why it's not getting called.

It's also possible for the ClockWidget to implement PaintListener directly; in this case, addPaintListener(this) would be called in the constructor. Modern JITs will optimize the calls to equivalent code paths in any case; it comes down to a style decision as to whether the ClockWidget class should implement the PaintListener interface or not.

Finally, the size can be computed based on the hints. This is called by the layout manager to determine what size the widget should be. For widgets with a fixed size (say, a text string or an image), the size can vary depending on the layout. In this case, it returns a square, based on the minimum size of the supplied width and height hints, or 50, whichever is bigger. The SWT.DEFAULT value is -1, which has to be dealt with specifically.

主站蜘蛛池模板: 元氏县| 政和县| 祁东县| 酉阳| 易门县| 紫云| 内江市| 泰安市| 石家庄市| 汽车| 故城县| 称多县| 明溪县| 罗平县| 武功县| 濮阳市| 赤水市| 彩票| 五家渠市| 四会市| 马公市| 临邑县| 丰顺县| 潼关县| 海淀区| 镇沅| 太湖县| 辛集市| 铁岭县| 连江县| 洞口县| 垦利县| 淄博市| 永丰县| 信丰县| 全州县| 政和县| 宿松县| 明光市| 柞水县| 郴州市|