From 1dddda6599f7a7d97cd57ceb6de9f54c01d7a952 Mon Sep 17 00:00:00 2001 From: draxdyn Date: Wed, 1 Jun 2016 21:02:22 +0200 Subject: [PATCH] Fix broken threading in CardPanel The current code is broken, can't touch the UI in a thread pool thread, UI.invokeLater must be used to get back on the UI thread. Also, it must check whether the card has been changed again before setting the image and do nothing in that case. --- .../java/org/mage/card/arcane/CardPanel.java | 76 +++++++++---------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java index 480249f9bf6..50aa63e61d4 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java @@ -311,37 +311,19 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti String cardType = getType(newGameCard); tooltipText.setText(getText(cardType, newGameCard)); - Util.threadPool.submit(new Runnable() { - @Override - public void run() { - try { - tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0; - flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0; - if (!loadImage) { - return; - } - BufferedImage srcImage; - if (gameCard.isFaceDown()) { - srcImage = getFaceDownImage(); - } else { - srcImage = ImageCache.getImage(gameCard, getCardWidth(), getCardHeight()); - } - if (srcImage != null) { - hasImage = true; - setText(gameCard); - setImage(srcImage); - } - if (gameCard.isTransformed()) { - toggleTransformed(); - } - setText(gameCard); - } catch (Exception e) { - LOGGER.fatal("Problem during image animation", e); - } catch (Error err) { - LOGGER.error("Problem during image animation", err); - } - } - }); + tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0; + flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0; + + if (!loadImage) { + return; + } + + if (gameCard.isTransformed()) { + // this calls updateImage + toggleTransformed(); + } else { + updateImage(); + } } private void setTypeIcon(BufferedImage bufferedImage, String toolTipText) { @@ -389,7 +371,10 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti private void setImage(Image srcImage) { synchronized (imagePanel) { - imagePanel.setImage(srcImage); + if(srcImage != null) + imagePanel.setImage(srcImage); + else + imagePanel.clearImage(); repaint(); } doLayout(); @@ -734,15 +719,21 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti return cardYOffset; } + private int updateImageStamp; + @Override public void updateImage() { + tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0; + flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0; + + final CardView gameCard = this.gameCard; + final int stamp = ++updateImageStamp; + Util.threadPool.submit(new Runnable() { @Override public void run() { try { - tappedAngle = isTapped() ? CardPanel.TAPPED_ANGLE : 0; - flippedAngle = isFlipped() ? CardPanel.FLIPPED_ANGLE : 0; - BufferedImage srcImage; + final BufferedImage srcImage; if (gameCard.isFaceDown()) { srcImage = getFaceDownImage(); } else if (cardWidth > THUMBNAIL_SIZE_FULL.width) { @@ -750,11 +741,16 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti } else { srcImage = ImageCache.getThumbnail(gameCard); } - if (srcImage != null) { - hasImage = true; - setText(gameCard); - setImage(srcImage); - } + UI.invokeLater(new Runnable() { + @Override + public void run () { + if(stamp == updateImageStamp) { + hasImage = srcImage != null; + setText(gameCard); + setImage(srcImage); + } + } + }); } catch (Exception e) { e.printStackTrace(); } catch (Error err) {