2014-10-22 4 views
4

Я пытаюсь отобразить изображение высокой ширины в Java Swing (скажем, 2000x100, как полоса частот сердечных сокращений). Мне нужно показать только окно шириной 500, пока оно слегка движется влево. Мой текущий код (немного сложный, он также имеет ненужные анимации) делает это, но функция, которую мне нужно добавить, заключается в следующем: конец изображения должен быть конкатенирован с началом изображения. Поэтому он всегда повторяется снова и снова.Показать движущееся изображение в Java Swing

Короче говоря, мне нужно присоединиться к двум концам изображения! Как я могу это сделать?

enter image description here

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.LinearGradientPaint; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.geom.Point2D; 
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 SlidingAnimation { 

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

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

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       JPanel j = new JPanel(); 
       j.add(new AnimatedBar(true)); 
       frame.add(j); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 

class AnimatedBar extends JPanel { 

    private BufferedImage img; 

    private Timer timer; 
    private long startTime = -1; 
    private int playTime = 4000; 
    private int window = 500; 
    private int moveX=0; 
    public static boolean keepRunning=true; 

    private float progress; 

    public AnimatedBar(boolean x) { 
     try { 
      if(x) 
       img = ImageIO.read(new File("strip2.jpg")); 
      else 
       img=null; 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
     if(x){ 
      timer = new Timer(40, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        if (startTime == -1) { 
         startTime = System.currentTimeMillis(); 
        } else { 
         long currentTime = System.currentTimeMillis(); 
         long diff = currentTime - startTime; 

         if (diff >= playTime) { 
          diff = 0; 
          startTime = -1; 
         } 
         progress = diff/(float) playTime; 
        } 

        repaint(); 
       } 
      }); 
      timer.start(); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return img == null ? new Dimension(50, 50) : new Dimension(img.getWidth()/3, img.getHeight()); 
    } 

    protected BufferedImage generateImage() { 

     BufferedImage buffer = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2d = buffer.createGraphics(); 
     g2d.setBackground(new Color(0, 0, 0, 0)); 
     g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight()); 
     //   g2d.drawImage(img, 500, 0, this); 
     g2d.drawImage(img,0,0,500,100,(moveX++),0,window+moveX,100,this); 


     float startAt = progress- 0.05f; 
     float endAt = progress + 0.05f; 

     if (endAt <= 0.1f) { 
      startAt = 0; 
      endAt = Math.max(0.1f, progress); 
     } else if (endAt >= 1f) { 
      endAt = 1f; 
      startAt = progress; 
     } 

     LinearGradientPaint lgp = new LinearGradientPaint(
       new Point2D.Float(0, 0), 
       new Point2D.Float(img.getWidth(), 0), 
       new float[]{startAt, endAt}, 
       new Color[]{new Color(0, 0, 0, 0), Color.RED}); 

     g2d.setPaint(lgp); 

     g2d.setComposite(AlphaComposite.DstOut.derive(1f)); 
     g2d.fill(new Rectangle(0, 0, img.getWidth(), img.getHeight())); 
     g2d.dispose(); 

     return buffer; 

    } 

    public void setImg(BufferedImage img) { 
     this.img = img; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     if(keepRunning==false){ 
      img=null; 
     } 
     else{ 
      try { 
       img = ImageIO.read(new File("strip2.jpg")); 
      } catch (IOException e) { 
      } 
     } 
      super.paintComponent(g); 
      if (img != null) { 
       Graphics2D g2d = (Graphics2D) g.create(); 
       int y = (getHeight() - img.getHeight())/2; 
       int x = (getWidth() - img.getWidth()/3)/2; 
       g2d.drawImage(generateImage(), x, y, this); 

       g2d.dispose(); 
     } 
    } 

} 
+1

См. Также этот [пример] (http://stackoverflow.com/a/5048863/230513), используя [tag: jfreechart]. – trashgod

ответ

5

Конец изображения должны быть сцеплены с началом изображения. Поэтому он всегда повторяет показ

Проверьте Marquee Panel. Вы можете добавить JLabel с ImageIcon в MarqueePanel.

MarqueePanel предлагает различные способы настройки прокрутки.

Edit:

Основной код будет:

MarqueePanel panel = new MarqueePanel(); 
panel.setWrap(true); 
panel.setWrapAmount(0); 
panel.setPreferredWidth(250); 

JLabel label = new JLabel(new ImageIcon("heartbeat.jpg")); 
panel.add(label); 

frame.add(panel); 

Если вы хотите, чтобы изображение полностью появится слева при отображении вы можете изменить метод startScrolling() и использовать scrollOffset = 0;.

+0

Спасибо. Но, как видно, когда текст заканчивается и уходит, он начинается снова.Как круг, мне нужно, чтобы начало ASA текста заканчивалось, поэтому конец приклеен к началу! –

+0

Ummm, опция 'wrap' может помочь. Я надеюсь, что между двумя концами не должно быть места между собой, чтобы объединиться. –

+0

@TinaJasmin, вам также нужно будет установить значение 'wrap amount' равным 0 при использовании' wrap', если вы не хотите разрыва. – camickr

7

Чтобы соединить концы, раскрасит изображение в два раза, как показано на this answer. Первая краска будет концом изображения. Вторая краска будет началом изображения, смещенным на ширину, на которую заканчивается конец.

E.G.

import java.awt.*; 
import java.awt.event.*; 
import java.awt.image.BufferedImage; 
import javax.swing.*; 

import java.net.URL; 
import javax.imageio.ImageIO; 

public class HeartBeat { 

    public static void main(String[] args) throws Exception { 
     URL url = new URL("http://i.stack.imgur.com/i8UJD.jpg"); 
     final BufferedImage bi = ImageIO.read(url); 
     Runnable r = new Runnable() { 

      @Override 
      public void run() { 
       final BufferedImage canvas = new BufferedImage(
         bi.getWidth(), bi.getHeight(), 
         BufferedImage.TYPE_INT_RGB); 
       final JLabel animationLabel = new JLabel(new ImageIcon(canvas)); 
       ActionListener animator = new ActionListener() { 

        int x = 0; 

        @Override 
        public void actionPerformed(ActionEvent e) { 
         Graphics2D g = canvas.createGraphics(); 

         // paint last part of image in left of canvas 
         g.drawImage(bi, x, 0, null); 
         // paint first part of image immediately to the right 
         g.drawImage(bi, x + bi.getWidth(), 0, null); 

         // reset x to prevent hitting integer overflow 
         if (x%bi.getWidth()==0) x = 0; 

         g.dispose(); 
         animationLabel.repaint(); 
         x--; 
        } 
       }; 
       Timer timer = new Timer(40, animator); 
       timer.start(); 
       JOptionPane.showMessageDialog(null, animationLabel); 
       timer.stop(); 
      } 
     }; 
     // Swing GUIs should be created and updated on the EDT 
     // http://docs.oracle.com/javase/tutorial/uiswing/concurrency 
     SwingUtilities.invokeLater(r); 
    } 
} 
+1

Не могли бы вы добавить комментарий или два, где вы получите смещение, объясняющее, что именно происходит там? Я думаю, что это было бы полезно для людей, пытающихся работать через то, как обертывается изображение. – MirroredFate

+1

Как быстрая заметка, в зависимости от того, для чего используется этот дисплей, вы можете сбросить x, когда он изменится до 0 ... в противном случае я думаю, что вы столкнетесь с отрицательным целым числом переполнения, как три года ... вероятно, не имеет значения, но, может быть. – MirroredFate

+0

@MirroredFate Оба хорошие предложения, см. Править. –

Смежные вопросы