Frage

http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/DisplayananimatedGIF.htm beschreibt, wie ein animiertes GIF in SWT - im Allgemeinen.Während der code funktioniert und ist einfach verständlich ist, ich bin vor schwere Probleme anzeigen eines animierten GIF in a SWT/JFace table/tree viewer Zelle mit dieser Technik.-> alle code unten

Im Grunde ist mir umgesetzt meinem eigenen OwnerDrawLabelProvider das schafft ein ImageLoader in der Farbe(Event, Object) und startet eine animation thread.Das problem scheint zu sein, dass diese animation thread nicht der UI-thread und ich weiß nicht, was GC-oder Display-Instanz für die Verwendung in seiner run () - Methode.

Ich habe versucht, das erstellen einer separaten GC Instanz in der thread-Konstruktor - abgeleitet von Veranstaltung.gc - aber der thread fehl schreiben, dass, GC, sobald ich einen Schritt aus der debugger...

Sat Jan  9 22:11:57 192.168.1.6.local.home java[25387] : CGContextConcatCTM: invalid context 0x0
2010-01-09 22:12:18.356 java[25387:17b03] It does not make sense to draw an image when [NSGraphicsContext currentContext] is nil.  This is a programming error. Break on _NSWarnForDrawingImageWithNoCurrentContext to debug.  This will be logged only once.  This may break in the future.
Sat Jan  9 22:12:41 192.168.1.6.local.home java[25387] : CGContextConcatCTM: invalid context 0x0 

Wie tun ich müssen, um mit dieser situation umzugehen?
Unten sind die relevanten code-Teile:

/* Called by paint(Event, Object). */
private void paintAnimated(final Event event, final ImageLoader imageLoader) {
    if (imageLoader == null || ArrayUtils.isEmpty(imageLoader.data)) {
      return;
    }
    final Thread animateThread = new AnimationThread(event, imageLoader);
    animateThread.setDaemon(true);
    animateThread.start();
  }

  private class AnimationThread extends Thread {

    private Display display;

    private GC gc;

    private ImageLoader imageLoader;

    private Color background;

    public AnimationThread(final Event event, final ImageLoader imageLoader) {
      super("Animation");
      this.display = event.display;
      /*
       * If we were to simply reference event.gc it would be reset/empty by the time it's being used
       * in run().
       */
      this.gc = new GC(event.gc.getDevice());
      this.imageLoader = imageLoader;
      this.background = getBackground(event.item, event.index);
    }

    @Override
    public void run() {
      /*
       * Create an off-screen image to draw on, and fill it with the shell background.
       */
      final Image offScreenImage =
          new Image(this.display, this.imageLoader.logicalScreenWidth,
              this.imageLoader.logicalScreenHeight);
      final GC offScreenImageGC = new GC(offScreenImage);
      offScreenImageGC.setBackground(this.background);
      offScreenImageGC.fillRectangle(0, 0, this.imageLoader.logicalScreenWidth,
          this.imageLoader.logicalScreenHeight);
      Image image = null;
      try {
        /* Create the first image and draw it on the off-screen image. */
        int imageDataIndex = 0;
        ImageData imageData = this.imageLoader.data[imageDataIndex];
        image = new Image(this.display, imageData);
        offScreenImageGC.drawImage(image, 0, 0, imageData.width, imageData.height, imageData.x,
            imageData.y, imageData.width, imageData.height);

        /*
         * Now loop through the images, creating and drawing each one on the off-screen image before
         * drawing it on the shell.
         */
        int repeatCount = this.imageLoader.repeatCount;
        while (this.imageLoader.repeatCount == 0 || repeatCount > 0) {
          switch (imageData.disposalMethod) {
            case SWT.DM_FILL_BACKGROUND:
              /* Fill with the background color before drawing. */
              offScreenImageGC.setBackground(this.background);
              offScreenImageGC.fillRectangle(imageData.x, imageData.y, imageData.width,
                  imageData.height);
              break;
            case SWT.DM_FILL_PREVIOUS:
              // Restore the previous image before drawing.
              offScreenImageGC.drawImage(image, 0, 0, imageData.width, imageData.height,
                  imageData.x, imageData.y, imageData.width, imageData.height);
              break;
          }

          imageDataIndex = (imageDataIndex + 1) % this.imageLoader.data.length;
          imageData = this.imageLoader.data[imageDataIndex];
          image.dispose();
          image = new Image(this.display, imageData);
          offScreenImageGC.drawImage(image, 0, 0, imageData.width, imageData.height, imageData.x,
              imageData.y, imageData.width, imageData.height);

          // Draw the off-screen image.
          this.gc.drawImage(offScreenImage, 0, 0);

          /*
           * Sleeps for the specified delay time (adding commonly-used slow-down fudge factors).
           */
          try {
            int ms = imageData.delayTime * 10;
            if (ms 

Ich habe das gleiche problem, um das SWT-newsgroup http://www.eclipse.org/forums/index.php?t=tree&th=160398

War es hilfreich?

Lösung

Nach vielen Stunden der frustrierenden trial and error-ein Kollege kam mit, eine machbare Lösung.Meine erste Ansätze zu haben, diese umgesetzt in eine vollständig selbst-enthalten LabelProvider kläglich gescheitert.

Ein Ansatz, der nicht funktioniert hat, war zu überschreiben LabelProvider#update() und der Aufruf timerExec(100, new Runnable () {...- viewer.update()...in dieser Methode.Die "Lebens"-Zyklus, der schwer zu kontrollieren und es benutzt zu viele CPU-Zyklen (10% (auf meinem MacBook).

Einer der Kollegen Ideen war die Implementierung einer benutzerdefinierten TableEditor:ein Etikett mit einem Bild (einen frame der animierten GIF-Datei), aber keinen text.Jeder TableEditor Instanz würden starten Sie Ihren eigenen thread, in dem es updates the label ' s image.Das funktioniert ganz gut, aber es gibt eine separate "animation" Gewinde für jede animierte Symbol.Auch dies war ein performance-killer, verbraucht 25% CPU auf meinem MacBook.

Der Letzte Ansatz hat drei Bausteine

  • ein OwnerDrawLabelProvider die Farben entweder ein statisches Bild oder den frame eines animierten GIF
  • ein animation thread (der pace maker), ruft es redraw () " für die Spalte, die das enthält, animierte GIFs und es auch ruft update()
  • und der Zuschauer ist content-Anbieter, der die animation steuert thread.

Details in meinem blog http://www.frightanic.com/2010/02/09/animated-gif-in-swt-tabletree-viewer-cell/.

Andere Tipps

Können Sie nicht ein LabelProvider Rückkehr verschiedene Bilder lassen und dann Anruf viewer.update (...) auf die Elemente, die Sie animieren möchten. Sie können Display.timerExec verwenden, um einen Rückruf zu erhalten, anstatt einen eigenen Thread zu haben.

Siehe meine Antwort href="https://stackoverflow.com/questions/1920718/swt-and-blinking">, wie Sie Farben ändern können. Sie sollten in der Lage sein, etwas ähnliches mit Bildern zu tun.

scroll top