Proper way to use JLabels to update an image

后端 未结 2 897
我在风中等你
我在风中等你 2020-11-29 14:11

I am creating a GUI, and am fairly new to swing and awt. I am trying to create a gui that, upon launch, sets the background to an image, then uses a method to create a slide

相关标签:
2条回答
  • 2020-11-29 14:40

    You're calling Thread.sleep(...) and likely on the EDT or Swing event thread (full name is the Event Dispatch Thread). This thread is responsible for all Swing painting/drawing and user interactions, and so sleeping it will only serve to freeze your entire GUI. Instead you should use a Swing Timer to allow you to swap a JLabel's ImageIcon.

    So, briefly:

    • Don't call Thread.sleep(...) on the Swing event thread (Event Dispatch Thread or EDT).
    • Do use a Swing Timer to do your repeating delayed actions.
    • Don't make and add many JLabels. Just make and add one.
    • Do Swap the ImageIcon that the JLabel displays by calling setIcon(...) on the label.
    • Better (cleaner) to write if (busy == false) { as if (!busy) {

    e.g.,

    ImageIcon[] icons = {...}; // filled up with your ImageIcons
    
    if (!busy) {
      int timerDelay = 2000;
      new Timer(timerDelay, new ActionListener() {
        private int i = 0;
        public void actionPerfomed(ActionEvent e) {
          myLabel.setIcon(icons(i));
          i++;
          if (i == icons.length) {
            ((Timer)e.getSource).stop();
          } 
        };
      }).start();
    }
    
    0 讨论(0)
  • 2020-11-29 14:53

    See ImageViewer for a working example of displaying images using a Swing based Timer.

    See also How to use Swing Timers.


    And while I'm here, another (prettier) example of animating an image. It uses this Mercator map of land masses. The image can be tiled horizontally, and therefore be scrolled left/right as needed.

    Mercator Map of Land Masses

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.Point2D;
    import java.awt.image.BufferedImage;
    import javax.swing.*;
    
    import java.net.URL;
    import javax.imageio.ImageIO;
    
    public class WorldView {
    
        public static void main(String[] args) throws Exception {
            URL url = new URL("http://i.stack.imgur.com/P59NF.png");
            final BufferedImage bi = ImageIO.read(url);
            Runnable r = new Runnable() {
    
                @Override
                public void run() {
                    int width = 640;
                    int height = 316;
                    Graphics2D g = bi.createGraphics();
    
                    float[] floats = new float[]{0f, .4f, .55f, 1f};
                    Color[] colors = new Color[]{
                        new Color(20, 20, 20, 0),
                        new Color(0, 10, 20, 41),
                        new Color(0, 10, 20, 207),
                        new Color(0, 10, 20, 230),};
                    final LinearGradientPaint gp2 = new LinearGradientPaint(
                            new Point2D.Double(320f, 0f),
                            new Point2D.Double(0f, 0f),
                            floats,
                            colors,
                            MultipleGradientPaint.CycleMethod.REFLECT);
    
                    final BufferedImage canvas = new BufferedImage(
                            bi.getWidth(), bi.getHeight() + 60,
                            BufferedImage.TYPE_INT_RGB);
    
                    final JLabel animationLabel = new JLabel(new ImageIcon(canvas));
                    ActionListener animator = new ActionListener() {
    
                        int x = 0;
                        int y = 30;
    
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            Graphics2D g = canvas.createGraphics();
                            g.setColor(new Color(55, 75, 125));
    
                            g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
    
                            int offset = (x % bi.getWidth());
                            g.drawImage(bi, offset, y, null);
                            g.drawImage(bi, offset - bi.getWidth(), y, null);
    
                            g.setPaint(gp2);
                            g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
    
                            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);
        }
    }
    

    Here is a version of that image with the equator added (it is 44 pixels 'south' of the center of the image).

    enter image description here

    0 讨论(0)
提交回复
热议问题