简体   繁体   中英

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 ]

Dependent on the progress/value of the slide (1), does IMAGE A slide away and IMAGE B will pop-up .

Once the slide reaches the bottom, IMAGE B will completely take over the display area and IMAGE A is hidden. 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? 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. 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.
  2. Add each label to a JPanel using a horizontal BoxLayout
  3. add the panel to a 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":

  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".

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. 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.

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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