【问题标题】:displaying pictures side by side in java在java中并排显示图片
【发布时间】:2019-01-28 13:49:42
【问题描述】:

是否可以使用 BufferedImage 和 Graphics2D 并排显示两张图片?还是应该用其他方法?

在下面的代码中,我可以显示两张图片,但图片 1 与图片 2 重叠。

package zdjecie;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class ObrazPanel extends JPanel {

    private BufferedImage image;
    private BufferedImage image2;

    public ObrazPanel() {
        super();

    File imageFile = new File("C:\\Users\\KostrzewskiT\\eclipse-workspace\\zdjecie\\src\\zdjecie\\java.jpg");
    File imageFile2 = new File("C:\\Users\\KostrzewskiT\\eclipse-workspace\\zdjecie\\src\\zdjecie\\java2.jpg"); 

        try {
            image = ImageIO.read(imageFile);
            image2 = ImageIO.read(imageFile2);
        } catch (IOException e) {
            System.err.println("Blad odczytu obrazka");
            e.printStackTrace();
        }


        Dimension dimension = new Dimension(image.getWidth(), image.getHeight());
        setPreferredSize(dimension);
        Dimension dimension2 = new Dimension(image2.getWidth(), image2.getHeight());
        setPreferredSize(dimension2);
    }


    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(image, 0, 0, this);
        g2d.drawImage(image2, 200, 200, this);
    }
}

【问题讨论】:

  • 如果它们重叠,是因为您没有正确定位它们吗?
  • 那么史蒂夫如何正确定位它们?
  • 我认为您的setPreferredSize(dimension); 代码是错误的,因为您是在 JPanel 上调用它的。您是否希望这会改变图像的大小?
  • 更改g2d.drawImage(image2, 200, 200, this); 中的值,使它们不会重叠。
  • with BufferedImage and Graphics2D - 为什么?只需从 BufferedImage 创建一个 ImagIcon 并使用 ImageIcon 创建一个 JLabel。然后,您只需将标签添加到面板,您就可以使用您想要显示图像的任何布局管理器。 JPanel 的默认 FlowLabel 并排显示图像。

标签: java swing javax.imageio


【解决方案1】:

您调用setPreferredSize 两次,这导致第一次调用基本上什么都不做。这意味着你总是有一个preferredSize 等于第二张图像的尺寸。您应该做的是将大小设置为new Dimension(image.getWidth() + image2.getWidth(), image2.getHeight()),假设两者具有相同的高度。如果不是这种情况,请将height 设置为两个图像的最大值。

其次,您需要将第二张图片与第一张图片精确偏移第一张图片的宽度:

g2d.drawImage(image, 0, 0, this);
g2d.drawImage(image2, image.getWidth(), 0, this);

【讨论】:

    【解决方案2】:

    数学逻辑不正确。请参阅getPreferredSize() 方法以了解计算所需宽度的正确方法,以及对paintComponent(Graphics) 方法的更改以将它们并排放置。

    另一种选择(未在此答案中检查)是将每个图像放入JLabel,然后将标签添加到具有适当布局的面板中。

    这是更改的效果:

    import java.awt.*;
    import java.awt.image.BufferedImage;
    import javax.swing.*;
    import java.net.*;
    import javax.imageio.ImageIO;
    
    public class ObrazPanel extends JPanel {
    
        private BufferedImage image;
        private BufferedImage image2;
    
        public ObrazPanel() throws MalformedURLException {
            super();
    
            URL imageFile = new URL("https://i.stack.imgur.com/7bI1Y.jpg");
            URL imageFile2 = new URL("https://i.stack.imgur.com/aH5zB.jpg");
    
            try {
                image = ImageIO.read(imageFile);
                image2 = ImageIO.read(imageFile2);
            } catch (Exception e) {
                System.err.println("Blad odczytu obrazka");
                e.printStackTrace();
            }
        }
    
        @Override
        public Dimension getPreferredSize() {
            int w = image.getWidth() + image2.getWidth();
            int h1 = image.getHeight();
            int h2 = image2.getHeight();
            int h = h1>h2 ? h1 : h2;
            return new Dimension(w,h);
        }
    
        @Override
        public void paintComponent(Graphics g) {
            // always best to start with this.. 
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.drawImage(image, 0, 0, this);
            g2d.drawImage(image2, image.getWidth(), 0, this);
        }
    
        public static void main(String[] args) {
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception useDefault) {
                    }
                    ObrazPanel o;
                    try {
                        o = new ObrazPanel();
                        JFrame f = new JFrame(o.getClass().getSimpleName());
                        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                        f.setLocationByPlatform(true);
    
                        f.setContentPane(o);
                        f.pack();
                        f.setMinimumSize(f.getSize());
    
                        f.setVisible(true);
                    } catch (MalformedURLException ex) {
                        ex.printStackTrace();
                    }
                }
            };
            SwingUtilities.invokeLater(r);
        }
    }
    

    【讨论】:

    【解决方案3】:

    只要有变化,我就会加入图像并将它们绘制到另一个缓冲图像。然后我可以在需要重绘面板时重新绘制组合图像。

    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class SideBySideImagePanel extends JPanel {
        private static final long serialVersionUID = 5868633578732134172L;
        private BufferedImage left;
        private BufferedImage right;
        private BufferedImage join;
    
        public SideBySideImagePanel() {
            ClassLoader loader = this.getClass().getClassLoader();
            BufferedImage left = null, right = null;
    
            try {
                left = ImageIO.read(loader.getResourceAsStream("resources/Android.png"));
                right = ImageIO.read(loader.getResourceAsStream("resources/Java.png"));
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            this.setLeft(left);
            this.setRight(right);
        }
    
        public BufferedImage getLeft() {
            return left;
        }
    
        public void setLeft(BufferedImage left) {
            this.left = left;
        }
    
        public BufferedImage getRight() {
            return right;
        }
    
        public void setRight(BufferedImage right) {
            this.right = right;
        }
    
        @Override
        public void invalidate() {
            super.invalidate();
            join = combineImages(left, right);
            setPreferredSize(new Dimension(join.getWidth(), join.getHeight()));
        }
    
        @Override
        public void paintComponent(Graphics g) {
            g.drawImage(join, 0, 0, null);
        }
    
        private BufferedImage combineImages(BufferedImage left, BufferedImage right) {
            int width = left.getWidth() + right.getWidth();
            int height = Math.max(left.getHeight(), right.getHeight());
            BufferedImage combined = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 
            Graphics g = combined.getGraphics();
    
            g.drawImage(left, 0, 0, null);
            g.drawImage(right, left.getWidth(), 0, null);
    
            return combined;
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new JFrame("Image Joiner");
                    SideBySideImagePanel panel = new SideBySideImagePanel();
    
                    frame.getContentPane().add(panel);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLocationRelativeTo(null);
                    frame.pack();
                    frame.setVisible(true);
                }
            });
        }
    }
    

    【讨论】:

      【解决方案4】:

      我在您的代码中发现了一些错误,但我不知道您要做什么...

      1] 你实际上并没有使用第一个设置

          Dimension dimension = new Dimension(image.getWidth(), image.getHeight());
          setPreferredSize(dimension); //not used
          Dimension dimension2 = new Dimension(image2.getWidth(), image2.getHeight());
          setPreferredSize(dimension2); //because overridden by this
      

      这意味着,面板的尺寸与image2相同,您应该如下设置:

      • 高度为两个图像高度的最大值
      • 宽度至少是两张图片宽度的总和(如果你想在同一个面板中绘制它们,就像你正在尝试的那样)

      2] imageimage2 数据类型是什么?在上面的块中,您有 File 但具有不同的命名变量,File 类当然没有宽度或高度参数

      我假设它的ImageGraphics.drawImage 中应有使用,那么:

      正如我提到的,您需要设置首选尺寸

      • 图像高度到最大值
      • 宽度至少为每个宽度的汇总值

      维度的东西:

      Dimension panelDim = new Dimension(image.getWidth() + image2.getWidth(),Math.max(image.getHeight(),image2.getHeight()));
      setPreferredSize(panelDim)
      

      然后您可以以原始尺寸绘制图像 - 由于坐标的左上角为 0;0,右下角为 this.getWidth(); this.getHeight() - 检查例如。 this explanation - 你需要从左下角开始绘画,然后移动到正确的位置增加“X”作为第一张图像的宽度

      @Override
      public void paintComponent(Graphics g) {
          Graphics2D g2d = (Graphics2D) g;
              /* public abstract boolean drawImage(Image img,
              int x,
              int y,
              Color bgcolor,
              ImageObserver observer)
              */
          //start to paint at [0;0]
          g2d.drawImage(image, 0, 0, this); 
          //start to paint just on the right side of first image (offset equals to width of first picture)- next pixel on the same line, on the bottom of the screen 
          g2d.drawImage(image2,image2.getWidth()+1, 0, this);
      }
      

      我没有机会测试它,但它应该是这样的。 重要的是

      • 您需要有合适的尺寸来拟合两个图像
      • 屏幕坐标从屏幕左上角开始 [0;0]

      【讨论】:

      • imageimage2BufferedImages。
      • 它应该也可以,BufferedImageImage 的孩子,如果我是正确的
      猜你喜欢
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      • 2018-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多