duke.png - >
arrowToLeft.gif - >
arrowToRight.gif - >
我需要一个UI,我想在Swing中描绘网络设备的图形表示。为此,我只是加载多个图像并逐个重叠以显示设备的当前状态。我必须支持缩放此视图。缩放代码如下所示。
public class LayeredPaneTest{
private JLayeredPane layeredPane;
private JScrollPane scrollPane;
private static double MIN_ZOOM_VALUE = 0.60; // 1.0;
private static double MAX_ZOOM_VALUE = 2.0;
private static final int LAYER1 = 0;
private static final int LAYER2 = 1;
private static final int LAYER3 = 3;
private double scaleFactor = 1.0;
private JInternalFrame internalFrame =
new JInternalFrame("LayeredPaneTest",false, false, false, false);
public LayeredPaneTest(){
loadView();
}
public JInternalFrame getView(){
return internalFrame;
}
private void loadView(){
((javax.swing.plaf.basic.BasicInternalFrameUI)internalFrame.getUI())
.setNorthPane(null);
internalFrame.setBorder(null);
internalFrame.getContentPane().add(buildCenterPane());
internalFrame.setSize(new Dimension(200, 200));
internalFrame.setLocation(0, 0);
internalFrame.setResizable(false);
internalFrame.setVisible(true);
}
private JPanel buildCenterPane(){
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
layeredPane = new JLayeredPane();
Position shelfPosition = new Position(0,0,200,200);
setLayeredPaneSize(shelfPosition);
JLabel label = getImageLabel(getImage("duke.png"),
new Position(0,0,100,100));
layeredPane.add(label, Integer.valueOf(LAYER1));
label = getImageLabel(getImage("arrowToLeft.gif"),
new Position(100,100,50,50));
layeredPane.add(label, Integer.valueOf(LAYER2));
label = getImageLabel(getImage("arrowToRight.gif"),
new Position(50,50,50,50));
layeredPane.add(label, Integer.valueOf(LAYER3));
scrollPane = new JScrollPane(layeredPane);
panel.add(scrollPane, BorderLayout.CENTER);
panel.add(getSliderPane(), BorderLayout.SOUTH);
return panel;
}
private Image getImage(String key){
InputStream is = this.getClass().getResourceAsStream(key);
try {
return ImageIO.read(is);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private void setLayeredPaneSize(Position shelfPosition){
int width = (int)(shelfPosition.getWidth() * scaleFactor + 10);
int height = (int)(shelfPosition.getHeight() * scaleFactor + 10);
layeredPane.setPreferredSize(new Dimension(width,height));
}
public void zoom(double factor){
if (factor < MIN_ZOOM_VALUE)
factor = MIN_ZOOM_VALUE;
else if (factor > MAX_ZOOM_VALUE)
factor = MAX_ZOOM_VALUE;
scaleFactor = factor;
Position shelfPosition = new Position(0,0,200,200);
setLayeredPaneSize(shelfPosition);
scrollPane.getViewport().repaint();
scrollPane.repaint();
scrollPane.getViewport().revalidate();
scrollPane.revalidate();
}
private JLabel getImageLabel(Image image, Position position) {
position = position.moveInRatio(scaleFactor);
ImageLabel label = new ImageLabel(new ImageIcon(image), position);
label.setOpaque(false);
label.setBounds(position.getLeft(),
position.getTop(),position.getWidth(),position.getHeight());
return label;
}
private JPanel getSliderPane(){
JPanel outer = new JPanel();
outer.setLayout(new FlowLayout());
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
final JSlider slider = new JSlider((int) (MIN_ZOOM_VALUE * 100),
(int) (MAX_ZOOM_VALUE * 100), 100);
slider.setMajorTickSpacing(1);
slider.setMinorTickSpacing(1);
double sliderValue = scaleFactor * 100.0;
slider.setValue((int) sliderValue);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
scaleFactor = slider.getValue() / 100.0;
zoom(scaleFactor);
}
});
panel.add(slider, BorderLayout.CENTER);
outer.add(panel);
return outer;
}
public static void main(String...strings){
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new LayeredPaneTest().getView(),
BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
static class Position{
private final int left,top,width,height;
Position(int x1, int y1, int x2, int y2){
this.left = x1;
this.top = y1;
this.width = x2;
this.height = y2;
}
public int getLeft() {
return left;
}
public int getTop() {
return top;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
private class ImageLabel extends JLabel{
private static final long serialVersionUID = 6152144095443433296L;
private ImageIcon image;
private Position position;
public ImageLabel(ImageIcon image, Position position){
super(image);
this.image = image;
this.position = position;
}
public void paintComponent(Graphics g) {
int newX = (int)(position.getLeft() * scaleFactor);
int newY = (int)(position.getTop() * scaleFactor);
Graphics2D g2 = (Graphics2D)g;
int newW = (int)(position.getWidth() * scaleFactor);
int newH = (int)(position.getHeight() * scaleFactor);
setBounds(newX, newY, newW, newH);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawImage(image.getImage(), 0, 0, newW, newH, null);
}
}
}
但问题是,当我放大一次并缩小时,一些图像会消失。知道它为什么会这样吗?
以下是重现错误的步骤; 一个。将滑块拖动到最大值, 湾见证图像被扩展到最大值并引入滚动条, C。现在隐藏了一小部分图像, d。现在将滑块拖动到最小。 即图像的隐藏部分消失。
答案 0 :(得分:1)
您不会通过调用super.XXX
实现重写的paintComponent
方法来尊重 paint chain ,如下所示:
@Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
//do the rest of the painting here
}
正如the docs明确指出:
如果你没有调用super的实现,你必须尊重opaque 属性,即如果此组件是不透明的,则必须完全 以非不透明的颜色填充背景。如果你不尊重 opaque属性你可能会看到视觉文物。
另请注意@Override
注释,以确保我重写正确的方法,默认情况下paintComponent
是protected
保持这种方式,因为您不想公开< / em>此方法应该使用其他类repaint()