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

时间:2013-01-07 15:37:34

标签: java image swing scrollpane

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

}

但问题是,当我放大一次并缩小时,一些图像会消失。知道它为什么会这样吗?

以下是重现错误的步骤;   一个。将滑块拖动到最大值,   湾见证图像被扩展到最大值并引入滚动条,   C。现在隐藏了一小部分图像,   d。现在将滑块拖动到最小。   即图像的隐藏部分消失。

1 个答案:

答案 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注释,以确保我重写正确的方法,默认情况下paintComponentprotected保持这种方式,因为您不想公开< / em>此方法应该使用其他类repaint()