JLabel disappears after scrolling

浪尽此生 提交于 2019-12-25 02:59:13

问题


I've got scroll panel which contains ImageIcon. I want to add JLabel with absolute position in px. What I've got:

The code:

public class HelloWorld {


    HelloWorld() {

        JFrame jfrm = new JFrame("Hello, World!");
        jfrm.setSize(640, 480);
        JPanel mapPanel = new JPanel();
        mapPanel.setLayout(null);
        mapPanel.setSize(600,400);
        jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ImageIcon imageIcon = new ImageIcon("src\\SwingExp\\img\\map.gif");
        JScrollPane scrollPane = new JScrollPane(new JLabel(imageIcon));
        scrollPane.setBounds(5,5,600,400);
        JLabel usaLabel = new JLabel("U.S.A.");
        usaLabel.setBounds(210,200,50,25);
        mapPanel.add(usaLabel);
        mapPanel.add(scrollPane);

        jfrm.add(mapPanel);
        jfrm.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new HelloWorld();
            }
        });
    }
}

But if I'll scroll a little, USA label will disappear from map:

JLabel positions must be absolute, as you see. How to avoid this?


回答1:


Add the usaLabel to the label containing the icon, not the scrollpane:

ImageIcon imageIcon = new ImageIcon("src\\SwingExp\\img\\map.gif");
JLabel map = new JLabel( imageIcon );
JScrollPane scrollPane = new JScrollPane( map );
//JScrollPane scrollPane = new JScrollPane(new JLabel(imageIcon));
scrollPane.setBounds(5,5,600,400);
JLabel usaLabel = new JLabel("U.S.A.");
usaLabel.setBounds(210,200,50,25);
map.add( usaLabel );
//mapPanel.add(usaLabel);

Also stop using a null layout everywhere. There is no need for your mapPanel variable. Just add the scrollpane directly to the content pane of the frame. By default the scrollpane will be added to the CENTER and will take up all the space available in the frame.




回答2:


I offer this as an alternate answer:

  • It uses an EmptyBorder for white (OK blue) space
  • The scroll pane returns a preferred size scaled by the width factor.
  • Scrolls to the end then seamlessly starts over.
  • America (Australia, New Zealand & ..everywhere else depicted) is always in view since the GUI displays one 'image width'. ;)

The source image was created for this answer.

Code

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.*;
import javax.imageio.ImageIO;

class HelloScrollingWorld {

    public JPanel gui = new JPanel(new BorderLayout());
    JScrollPane scrollPane;
    Timer timer = null;
    /**
     * The number of images we tile horizontally, must be >1 for scroll bar
     */
    int width = 2;
    /**
     * The equator (drawn in pale gray) is 44 px south of the vertical
     * center of the image.
     */
    int offset = 44;
    /**
     * Use this as padding on top and bottom.
     */
    int pad = 15;

    HelloScrollingWorld() {
        try {
            URL worldImage = new URL("http://i.stack.imgur.com/OEGTq.png");
            BufferedImage img = ImageIO.read(worldImage);
            initComponents(img);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private final void initComponents(final BufferedImage image) {
        JPanel multiimage = new JPanel(new GridLayout(1, 0, 0, 0));
        for (int ii = 0; ii < width; ii++) {
            multiimage.add(new JLabel(new ImageIcon(image)));
        }
        multiimage.setBackground(Color.BLUE.brighter());
        // add the white (or bright blue) space.
        multiimage.setBorder(new EmptyBorder(pad, 0, pad + offset, 0));
        scrollPane = new JScrollPane(
                multiimage,
                JScrollPane.VERTICAL_SCROLLBAR_NEVER,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS) {

            /**
             * return the preferred size scaled by the width.
             */
            @Override
            public Dimension getPreferredSize() {
                Dimension d = super.getPreferredSize();

                return new Dimension(d.width / width, d.height);
            }
        };
        gui.add(scrollPane, BorderLayout.CENTER);
        ActionListener scrollListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                scrollGui();
            }
        };
        timer = new Timer(15, scrollListener);
        timer.start();
    }

    public void stopTimer() {
        timer.stop();
    }

    public void scrollGui() {
        JScrollBar scrollBar = scrollPane.getHorizontalScrollBar();
        BoundedRangeModel model = scrollBar.getModel();
        int max = model.getMaximum() - scrollBar.getVisibleAmount();
        int now = model.getValue();
        if (now < max) {
            model.setValue(now + 1);
        } else {
            model.setValue(1);
        }
    }

    public JComponent getGui() {
        return gui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                HelloScrollingWorld hsw = new HelloScrollingWorld();

                JOptionPane.showMessageDialog(
                        null,
                        hsw.getGui(),
                        "Hello Scrolling Padded World",
                        JOptionPane.INFORMATION_MESSAGE);

                hsw.stopTimer();
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}


来源:https://stackoverflow.com/questions/21833460/jlabel-disappears-after-scrolling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!