java - 在垂直滚动窗格视图端口中,图像消失

  显示原文与译文双语对照的内容

duke.png -> duke.png

arrowToLeft.gif -> arrowToKeft

arrowToRight.gif -> enter image description here

我需要一个 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);
 }
 }

}

但问题在于,当我放大一次并缩小时,一些图像消失了。 为什么它的行为像这样?

下面是复制 Bug的步骤;。 将 slider 条拖动到最大值,b 。 将图像扩展到最大值,并引入滚动条,c 。 现在图像中的部分是隐藏的,。 现在将 slider 栏拖到最小。 图像的隐藏部分消失了。

时间: 原作者:

通过调用重写的方法,你不遵守的绘制链,如:


@Override
protected void paintComponent(Graphics grphcs) {
 super.paintComponent(grphcs);

//do the rest of the painting here
}

作为 ,文档的状态很清楚:

如果不调用超级用户的实现,则必须遵守不透明属性,如果该组件不透明,则必须完全填充背景。 如果你不遵守opaque属性,你可能会看到可视工件。

还要注意,为了确保我重写了正确的方法,在默认情况下使用 @Override 注释,默认情况下 paintComponentprotected,因为你不希望向其他类公开这个方法

原作者:
...