简体   繁体   English

Java-使用Swing创建连续的图像幻灯片

[英]Java - Create a continuous image slide with Swing

I wasn't sure how to properly name my problem up in the caption but I hope my image can express what I am looking for: 我不确定如何在标题中正确地命名我的问题,但我希望我的形象能表达我的期望:

https://i.stack.imgur.com/fIhP8.png

So what I am trying to accomplish is that you for example have two pictures, as seen above, and an object with an slide next to it [ named (1) in the picture ] 所以我要完成的工作是,例如,您有两张图片(如上图所示),以及旁边有一张幻灯片的对象[图片中名为(1)]

Dependent on the progress/value of the slide (1), does IMAGE A slide away and IMAGE B will pop-up . 根据幻灯片的进度/值(1), IMAGE A是否会滑出,然后IMAGE B会弹出

Once the slide reaches the bottom, IMAGE B will completely take over the display area and IMAGE A is hidden. 一旦幻灯片到达底部, IMAGE B将完全占据显示区域,而IMAGE A被隐藏。 Same applies vice-versa with the slide going up to the top. 反之亦然,幻灯片上升到顶部。

Is there any idea how to create such a thing with Java in Swing? 有什么想法如何在Swing中用Java创建这样的东西吗? I hope my explanation was accurate enough to understand. 我希望我的解释足够准确,可以理解。

Thank you for the help :) 感谢您的帮助 :)

Edit 1: Here is the code I implemented @camickr I thought it should work only by setting the viewpanel. 编辑1:这是我实现@camickr的代码,我认为它只能通过设置视图面板才能工作。 Did I do any mistake following your instructions? 按照您的指示我有没有做错任何事情?

JPanel bigPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 20));
JPanel displayPanel = new JPanel();
JScrollPane scrollPane = new JScrollPane();
[...] 
displayPanel.setLayout(new BoxLayout(displayPanel, BoxLayout.X_AXIS));
JLabel label1 = new JLabel(new ImageIcon("R:\\imgA.jpg"));
JLabel label2 = new JLabel(new ImageIcon("R:\\imgB.jpg"));
displayPanel.add(label1);
displayPanel.add(label2);
scrollPane.setViewportView(displayPanel);
bigPanel.add(scrollPane);
  1. Create two JLabels each with an ImageIcon for the image. 创建两个JLabels每个JLabels都带有一个ImageIcon作为图像。
  2. Add each label to a JPanel using a horizontal BoxLayout 使用水平BoxLayout将每个标签添加到JPanel
  3. add the panel to a JScrollPane 将面板添加到JScrollPane
  4. add the scroll pane to the frame. 将滚动窗格添加到框架。

The scroll pane will automatically display a scrollbar if the panel does not completely fill the space available to the scroll pane. 如果面板没有完全填满滚动窗格的可用空间,则滚动窗格将自动显示滚动条。

Edit: 编辑:

The code you posted is NOT an "MRE": 您发布的代码不是“ MRE”:

  1. We can't compile that code, so we don't know the exact context of how the code is used. 我们无法编译该代码,因此我们不知道代码使用的确切上下文。

  2. What is the point of the text field? 文本字段的意义是什么? Your question was about scrolling two images. 您的问题是关于滚动两个图像。 So the text field is irrelevant to the stated question. 因此,文本字段与所述问题无关。

  3. We don't have access to your image, so that should also not be included in the "MRE". 我们无权访问您的图片,因此也不应包含在“ MRE”中。

The basics of your question is the ability to scroll two labels. 您问题的基础是滚动两个标签的能力。 So to test this all you need is something like: 因此,要对此进行测试,您需要的是:

JLabel red = new JLabel("Image 1");
red.setOpaque(true);
red.setBackground( Color.RED );
red.setPreferredSize( new Dimension(200, 200) ); // for testing only

JLabel blue = new JLabel("Image 2");
...

JPanel displayPanel = new JPanel();
displayPanel.setLayout(new BoxLayout(displayPanel, BoxLayout.X_AXIS));
JScrollPane scrollPane = new JScrollPane(displayPanel);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);

Create a proper program using the above as the basics. 使用上面的基础知识创建一个合适的程序。

When the frame is displayed the images will be displayed at full size. 当显示框时,图像将以原尺寸显示。 Shrink the frame and the scrollbars will appear. 缩小边框,将出现滚动条。

The solution is not exactly what you asked for, but it shows you how to use default components to achieve the scrolling effect. 解决方案不完全是您所需要的,但是它向您展示了如何使用默认组件来实现滚动效果。 I personally find it more intuitive to scroll the images right to left by using a horizontal scrollbar instead of using a vertical slider. 我个人发现使用水平滚动条而不是垂直滑块将图像从右向左滚动更为直观。

In order to have some control over how the images are painted, I'd recommend creating an own panel for that, and use drawImage calls in the overridden paintComponent method. 为了控制图像的绘制方式,我建议为此创建一个自己的面板,并在覆盖的paintComponent方法中使用drawImage调用。 The "location" of the image should preferably be a relative value - that is, a double value between 0.0 (showing the first image) and 1.0 (showing the second image) to be independent of the resolution and image size. 图像的“位置”应当优选地是相对值,即,在0.0(示出第一幅图像)和1.0(示出第二幅图像)之间的double值,以独立于分辨率和图像尺寸。

There is a caveat regarding the image size, though: One has to assume that the size of both images is the same. 关于图像大小一个警告,虽然:一个人必须假定这两个图像的大小是一样的。 Otherwise, you're opening a can of worms regarding the question of how different image sizes should be handled. 否则,您将打开一罐蠕虫,其中涉及应如何处理不同图像大小的问题。 Additionally, there are some degrees of freedom what should happen when the containing component is larger or smaller than the images. 此外,当包含的成分大于或小于图像时,应该发生一些自由度。 But for simplicity, one can assume that it has always the right size. 但为简单起见,可以假定它始终具有正确的大小。

A simple implementation could then look like this: 然后,一个简单的实现可能如下所示:

ImageSlide

And here's the corresponding code: 这是相应的代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

public class ImageSlideTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        BufferedImage image0 = createImage("Image 0", Color.RED);
        BufferedImage image1 = createImage("Image 1", Color.GREEN);

        ImageSlidePanel imageSlidePanel = new ImageSlidePanel(image0, image1);
        JPanel panel = new JPanel(new BorderLayout());

        panel.add(imageSlidePanel, BorderLayout.CENTER);

        JSlider slider = new JSlider(SwingConstants.VERTICAL, 0, 100, 0);
        slider.addChangeListener(e -> 
        {
            double location = slider.getValue() / 100.0;
            imageSlidePanel.setLocation(location);
        });
        panel.add(slider, BorderLayout.EAST);

        f.getContentPane().add(panel);

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static BufferedImage createImage(String text, Color color)
    {
        int w = 300;
        int h = 200;
        BufferedImage image =
            new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();
        g.setColor(color);
        g.fillRect(0, 0, w, h);
        g.setColor(Color.BLACK);
        g.setFont(new Font("Dialog", Font.PLAIN, 30));
        g.drawString(text, 50, 50);
        g.dispose();
        return image;
    }
}

class ImageSlidePanel extends JPanel
{
    private final BufferedImage image0;
    private final BufferedImage image1;
    private double location;

    // Note: The images should have the same size...
    public ImageSlidePanel(BufferedImage image0, BufferedImage image1)
    {
        this.image0 = image0;
        this.image1 = image1;
        this.location = 0.0;
    }

    public void setLocation(double location)
    {
        this.location = Math.min(1.0, Math.max(0.0, location));
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        int dx = (int) (image0.getWidth() * location);
        g.drawImage(image0, -dx, 0, null);
        g.drawImage(image1, -dx + image0.getWidth(), 0, null);
    }

    @Override
    public Dimension getPreferredSize()
    {
        if (isPreferredSizeSet())
        {
            return super.getPreferredSize();
        }
        int w = image0.getWidth();
        int h = image0.getHeight();
        return new Dimension(w, h);
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM