1

duke.png ->duke.png

arrowToLeft.gif ->arrowToKeft

arrowToRight.gif ->ここに画像の説明を入力

Swing でネットワーク デバイスのグラフィカル表現を表現したい UI が必要です。このために、複数の画像を読み込んで 1 つずつ重ねて、デバイスの現在の状態を表示しています。このビューのズームをサポートする必要があります。ズームコードはこんな感じ。

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

}

しかし、ここでの問題は、一度ズームインしてズームアウトすると、一部の画像が消えることです。なぜこのように振る舞うのか分かりますか?

バグを再現する手順は次のとおりです。を。a. スライダー バーを最大までドラッグします。画像が最大まで拡大され、スクロール バーが表示されます。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の実装を呼び出さない場合は、不透明なプロパティを尊重する必要があります。つまり、このコンポーネントが不透明な場合は、背景を不透明でない色で完全に塗りつぶす必要があります。不透明なプロパティを尊重しないと、視覚的なアーティファクトが表示される可能性があります。

また、@Overrideアノテーションに注意して、正しいメソッドをオーバーライドしていることを確認してください。デフォルトpaintComponentでは、このメソッドを他のクラスに公開protectedしたくないので、そのままにしておいてください。repaint()

于 2013-01-07T20:25:33.933 に答える