在Java Swing中显示运动图像

我正在尝试在Java Swing中显示高宽度图像(比如2000×100,就像心率条一样)。 我需要只显示一个宽度为500的窗口,同时它向左略微移动。 我当前的代码(有点复杂,它也有不必要的动画)这样做,但我需要添加的function是:图像的结尾应该与图像的开头连接。 所以它总是重复显示一遍又一遍。

总之,我需要加入图像的两端! 我怎样才能做到这一点?

在此处输入图像描述

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 = 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(); } } } 

图像的结尾应与图像的开头连接。 所以它总是重复显示

看看Marquee面板 。 您可以将带有ImageIconJLabel添加到MarqueePanel

MarqueePanel提供了各种自定义滚动的方法。

编辑:

基本代码是:

 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;

要加入两端,请将图像绘制两次, 如此答案中所示 。 第一幅画将是图像的结尾。 第二个颜料将是图像的开始,偏移结束的宽度。

例如

 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://sofzh.miximages.com/java/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); } }