GIF animado na tabela SWT / célula visualizador de árvore
Pergunta
http://www.java2s.com/Code /Java/SWT-JFace-Eclipse/DisplayananimatedGIF.htm descreve como exibir um GIF animado em SWT - em geral. Enquanto o código funciona e é facilmente compreensível que estou enfrentando problemas sérios exibindo um GIF animado em uma célula visualizador de SWT / table JFace / árvore com essa técnica. -> todo o código abaixo
Essencialmente, eu implementei minha própria OwnerDrawLabelProvider que cria um ImageLoader na pintura (Evento, Object) e inicia um segmento de animação. O problema parece ser que esta discussão animação é não o segmento interface do usuário e eu não sei qual GC ou Exibir instância para uso em seu método run ().
Eu tentei criar uma instância GC separado no construtor do fio - derivado de event.gc - mas o segmento falhar escrevendo para que GC assim que eu sair do depurador ...
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
Como eu preciso para lidar com esta situação?
Abaixo estão as seções de código relevantes:
/* 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
Eu postei o mesmo problema com o SWT newsgroup http: // www.eclipse.org/forums/index.php?t=tree&th=160398
Solução
Depois de muitas horas de tentativa-e-erro frustrante um colega de trabalho veio com uma solução viável. Meus abordagens iniciais para ter isto implementado em um totalmente auto-suficiente LabelProvider falhou miseravelmente.
Uma abordagem que não fez trabalho foi substituir # update LabelProvider () e chamar timerExec (100, new Runnable () {... viewer.update () ... a partir desse método. A "vida" -Ciclo de que é difícil de controlar e ele usa muitos ciclos da CPU (10% no meu MacBook).
Uma das ideias do colega foi implementar um TableEditor personalizado: uma etiqueta com uma imagem (um quadro do GIF animado), mas nenhum texto. Cada instância TableEditor iria começar seu próprio segmento em que ele atualiza a imagem da etiqueta. Isso funciona muito bem, mas há um segmento separado "animação" para cada ícone animado. Além disso, este era um assassino de desempenho, consumiu 25% da CPU no meu MacBook.
A aproximação final tem três blocos de construção
- um OwnerDrawLabelProvider que tintas qualquer imagem estática ou o quadro de um GIF animado
- um segmento de animação (o marca-passo), ele chama redesenho () para a coluna que contém os GIFs animados e também chama update ()
- e provedor de conteúdo do espectador que controla o segmento de animação.
Detalhes no meu blog http://www.frightanic.com/2010/02/09/animated-gif-in-swt-tabletree-viewer-cell/ .
Outras dicas
Você não pode deixar que um retorno LabelProvider diferentes imagens e viewer.update então chamada (...) sobre os elementos que deseja animar. Você pode usar Display.timerExec para obter um retorno de chamada em vez de ter um segmento separado.
Veja a minha resposta aqui para como você pode mudar as cores. Você deve ser capaz de fazer algo semelhante com imagens.