问题
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