2016-03-07 69 views
0

編輯:爲了使這個更具體一點,我想知道如何創建在圖像中看到的超時效果。我知道如何繪製圖像等,但我不瞭解超時效果背後的邏輯,因此是一個問題。如何在Java中創建「冷卻矩形」效果?


我一直在做一些研究,這種「冷卻矩形」的效果,它似乎是在許多其他語言是可行的,但到目前爲止,我還沒有看到關於Java的許多解決方案。基本上我想創建一個功能,在圖像上產生這樣的效果。

Cooldown Rectangle 1

我已經知道了覆蓋圖像的基礎知識,我遇到一類做這樣的事情,但在通常稱爲「循環」版本。

我的確發現了this tutorial,它解釋瞭如何使用GameMaker創建上述效果。但我不確定如何將這些知識轉移到Java。

任何幫助,將不勝感激,謝謝。

+0

也許從[併發在Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/),[如何使用Swing定時器](http://docs.oracle.com)開始。 com/javase/tutorial/uiswing/misc/timer.html)和[2D圖形](http://docs.oracle.com/javase/tutorial/2d/) – MadProgrammer

回答

3

所以,你需要的是...

  • 一些方式來加載圖像
  • 一些方法來繪製圖像
  • 某種方式在圖像上畫一個超時的效果
  • 以某種定期更新用戶界面的方式,計算剩餘時間和更新UI

也許開頭爲:

例如...

Timeout

import java.awt.AlphaComposite; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        try { 
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
         ex.printStackTrace(); 
        } 

        TimeOutPane tp = new TimeOutPane(); 
        tp.addMouseListener(new MouseAdapter() { 
         @Override 
         public void mouseClicked(MouseEvent e) { 
          tp.executeTimeout(); 
         } 
        }); 

        JFrame frame = new JFrame("Testing"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.add(tp); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 
       } catch (IOException ex) { 
        ex.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public class TimeOutPane extends JPanel { 

     private BufferedImage background; 
     private float progress = 0; 
     private long startedAt; 
     private int timeout = 5000; 

     private Timer timer; 

     public TimeOutPane() throws IOException { 
      background = ImageIO.read(new File("/Volumes/Disk02/Dropbox/Ponies/url.png")); 
     } 

     public void setTimeout(int timeout) { 
      this.timeout = timeout; 
     } 

     public int getTimeout() { 
      return timeout; 
     } 

     public void setProgress(float progress) { 
      this.progress = progress; 
      repaint(); 
     } 

     public float getProgress() { 
      return progress; 
     } 

     public void executeTimeout() { 
      if (timer == null) { 
       timer = new Timer(40, new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         long diff = System.currentTimeMillis() - startedAt; 
         float progress = diff/(float) timeout; 
         if (diff >= timeout) { 
          progress = 1f; 
          timer.stop(); 
         } 
         setProgress(progress); 
        } 
       }); 
      } else if (timer.isRunning()) { 
       timer.stop(); 
      } 

      startedAt = System.currentTimeMillis(); 
      timer.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight()); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (background != null) { 
       Graphics2D g2d = (Graphics2D) g.create(); 
       applyQualityRenderingHints(g2d); 
       int x = (getWidth() - background.getWidth())/2; 
       int y = (getHeight() - background.getHeight())/2; 
       g2d.drawImage(background, x, y, this); 

       g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f)); 
       g2d.setColor(Color.BLACK); 

       int radius = Math.max(getWidth(), getHeight())/2; 

       g2d.fillArc(-radius, -radius, radius * 4, radius * 4, 90, (int) (360f * (1f - progress))); 

       g2d.dispose(); 
      } 
     } 

     public void applyQualityRenderingHints(Graphics2D g2d) { 
      g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); 
      g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 
      g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
      g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
      g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); 
     } 

    } 

} 
+0

哇這是一個非常乾淨和簡潔的解釋,謝謝。我主要想知道如何畫超時效果,我知道前兩個。謝謝你包括這一切。 –

+0

由於問題用Java 8標記,因此'Runnable'和'ActionListener'都可以用lambda表達式(或通過方法引用訪問的'Test'中的命名方法)替換。由於它是關於動畫的,因此您應該使用'System.nanoTime()'而不是'System.currentTimeMillis()'來知道*逝去的時間*而不是掛鐘時間。例如。如果系統在運行動畫時通過NTP更新其時鐘,則在使用'System.currentTimeMillis()'時可能會出現口吃或卡住,而基於System.nanoTime()的動畫不會受到影響。 – Holger

+0

@Holger給出這樣一個事實,即OP似乎沒有一個想法,我使用長手形式,因爲它定義了合同背後的含義並提高了整體的可讀性(對文檔的需求很少),除了添加一些額外的代碼行,沒有什麼壞處 – MadProgrammer