1

公爵.png ->公爵.png

arrowToLeft.gif ->arrowToKeft

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

}

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

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

4

1 回答 1

1

您不会通过调用重写方法的实现来尊重绘制链,如下所示:super.XXXpaintComponent

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

    //do the rest of the painting here
}

正如文档明确指出的那样:

如果你不调用 super 的实现,你必须尊重 opaque 属性,也就是说,如果这个组件是不透明的,你必须用不透明的颜色完全填充背景。如果您不尊重 opaque 属性,您可能会看到视觉伪影。

还要注意@Override注释以确保我覆盖了正确的方法,并且默认情况下paintComponent保持protected这种方式,因为您不想将此方法公开给他们应该使用的其他类repaint()

于 2013-01-07T20:25:33.933 回答