2016-09-13 6 views
0

JPanel에서 확장하여 이미지를 확대 및 축소하고 최상위 레벨에서 JScrollPane을 사용하여 누군가가 확대/축소 된 영역을 가로 질러 앞뒤로 스크롤 할 수있게하는 간단한 클래스를 작성하려고합니다. 영상. JScrollPane 부분에 문제가 있습니다.JScrollPane 및 확대/축소 이미지

확대/축소 버튼 중 하나를 클릭하면 JScrollBars가 나타나거나 재설정 버튼이 사라질 때까지 버튼을 두 번 클릭해야합니다. 계속해서 확대하거나 축소하는 경우에도 막대가 나타나기 시작한 후에도 막대가 새로운 확대/축소 수준에 따라 업데이트되지 않습니다. 창 크기를 조정하면이 문제가 해결되지만 좀 더 구체적인 해결책을 찾고 있습니다.

ImagePanel 번호 :

package com.zephyr.graphics; 

import java.awt.Color; 
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.image.BufferedImage; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 
import javax.swing.JPanel; 

public class ImagePanel extends JPanel implements PropertyChangeListener{ 

    private File imageFile; 

    private BufferedImage image; 

    private double zoomMultiplier; 

    public ImagePanel() 
    { 
     imageFile = null; 

     image = null; 

     zoomMultiplier = 1; 
    } 

    public ImagePanel(File imageFile) 
    { 
     this.imageFile = imageFile; 

     try { 
      image = ImageIO.read(imageFile); 
     } catch (IOException e) { 
      image = null; 
     } 

     zoomMultiplier = 1; 
    } 

    public void setImageFile(File imageFile) 
    { 
     this.imageFile = imageFile; 

     if(imageFile == null) 
     { 
      image = null; 
     } 
     else 
     { 
      try { 
       image = ImageIO.read(imageFile); 
      } catch (IOException e) { 
       image = null; 
      } 
     } 

     zoomMultiplier = 1; 

     this.revalidate(); 
     this.repaint(); 
    } 

    public File getImageFile() 
    { 
     return imageFile; 
    } 

    public void paintComponent(Graphics g) 
    { 
     g.clearRect(0, 0, this.getWidth(), this.getHeight()); 

     if(image == null) 
     { 
      this.setPreferredSize(new Dimension(this.getParent().getWidth(), this.getParent().getHeight())); 
      g.setColor(Color.black); 
      g.fillRect(0, 0, this.getWidth(), this.getHeight()); 
     } 
     else 
     { 
      double preferredWidth = this.getParent().getWidth() * zoomMultiplier; 
      double preferredHeight = this.getParent().getHeight() * zoomMultiplier; 

      this.setPreferredSize(new Dimension((int)preferredWidth, (int)preferredHeight)); 

      Image scaled = image.getScaledInstance((int)preferredWidth, (int)preferredHeight, Image.SCALE_DEFAULT); 

      g.drawImage(scaled, 0, 0, null); 
     } 
    } 

    @Override 
    public void propertyChange(PropertyChangeEvent evt) { 
     if(evt.getPropertyName().equals("Image File")) 
     { 
      setImageFile((File)evt.getNewValue()); 
     } 
     else if(evt.getPropertyName().equals("Zoom In")) 
     { 
      double additive = ((Number)evt.getNewValue()).doubleValue(); 

      zoomMultiplier += additive; 

      this.revalidate(); 
      this.repaint(); 
     } 
     else if(evt.getPropertyName().equals("Zoom Out")) 
     { 
      double subtractive = ((Number)evt.getNewValue()).doubleValue(); 

      zoomMultiplier -= subtractive; 

      this.revalidate(); 
      this.repaint(); 
     } 
     else if(evt.getPropertyName().equals("Zoom Reset")) 
     { 
      zoomMultiplier = 1; 

      this.revalidate(); 
      this.repaint(); 
     } 
    } 
} 

메인 클래스

package com.zephyr.graphics; 

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeSupport; 
import java.io.File; 

import javax.swing.JButton; 
import javax.swing.JFileChooser; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 

public class Main { 

    public static void main(String[] args) 
    { 
     PropertyChangeSupport pcs = new PropertyChangeSupport(Main.class); 

     JFileChooser chooser = new JFileChooser(System.getProperty("user.home")); 
     chooser.setDialogTitle("Select an image"); 
     chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 

     File file = null; 

     if(chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) 
     { 
      file = chooser.getSelectedFile(); 
     } 
     else 
     { 
      System.err.println("NO FILE WAS SELECTED OR THE WINDOW WAS CLOSED"); 
      return; 
     } 

     JFrame frame = new JFrame("ImagePanel Tester"); 
     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     ImagePanel iPanel = new ImagePanel(file); 
     pcs.addPropertyChangeListener(iPanel); 

     JScrollPane iScroll = new JScrollPane(iPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
     iScroll.setPreferredSize(new Dimension(1024, 768)); 

     JPanel controlPanel = new JPanel(); 
     controlPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); 

     JButton zoomIn = new JButton("Zoom In"); 
     zoomIn.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       pcs.firePropertyChange("Zoom In", null, new Double(.25)); 
       frame.revalidate(); 
       frame.repaint(); 
      } 

     }); 
     controlPanel.add(zoomIn); 

     JButton zoomOut = new JButton("Zoom Out"); 
     zoomOut.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       pcs.firePropertyChange("Zoom Out", null, new Double(.25)); 
       frame.revalidate(); 
       frame.repaint(); 
      } 

     }); 
     controlPanel.add(zoomOut); 

     JButton zoomReset = new JButton("Zoom Reset"); 
     zoomReset.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       pcs.firePropertyChange("Zoom Reset", null, null); 
       frame.revalidate(); 
       frame.repaint(); 
      } 

     }); 
     controlPanel.add(zoomReset); 

     JButton changeImage = new JButton("Change Image"); 
     changeImage.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       if(chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) 
       { 
        File tempFile = chooser.getSelectedFile(); 
        pcs.firePropertyChange("Image File", null, tempFile); 
        frame.revalidate(); 
        frame.repaint(); 
       } 
      } 

     }); 
     controlPanel.add(changeImage); 

     frame.add(iScroll, BorderLayout.CENTER); 
     frame.add(controlPanel, BorderLayout.SOUTH); 
     frame.pack(); 
     frame.setVisible(true); 
     frame.revalidate(); //Shouldn't really be necessary, but seems to be helping 

    } 
} 
+1

'this.setPreferredSize (this.setPreferredSize (this.getParent(). getWidth(), this.getParent(). getHeight())) '이것은 페인트 메서드 내에서 호출되어야하는 것이 아닙니다! getPreferredSize() 메소드를 오버라이드 (override) 해, 올바른 값을 돌려 준다. 또한 바람직한 크기는 부모의 크기가 아니라 구성 요소의 내용 크기에 따라 결정됩니다. –

+0

누락 된'PropertyChangeSupport'는 코드가 다른 사람들을 위해 컴파일되지 않는 다양한 이유 중 하나입니다. 1) 더 빨리 도움을 받으려면 [MCVE] 또는 [Short, Self Contained, Correct Example] (http://www.sscce.org/)를 게시하십시오. MCVE/SSCCE라고 생각되는 것을 IDE에서 새 프로젝트에 붙여 넣은 다음 수정없이 컴파일 및 실행되는지 확인하십시오. 2) 예를 들어 이미지를 얻는 한 가지 방법은 [이 Q & A] (http://stackoverflow.com/q/19209650/418556)에서 볼 수있는 이미지에 핫 링크하는 것입니다. –

+0

@AndrewThompson Thompson 첫 번째 주석이 의미있는 반면, 두 번째 주석은 의미가 없지만 'PropertyChangeSupport'는 main 메소드의 맨 처음 줄에 만들어지며 java.beans 패키지의 일부입니다. 이 코드는 여러 컴퓨터에서 잘 컴파일됩니다. 첫 번째 주석에서 언급 한 코드 줄은 ImagePanel의 기본 크기가 부모 구성 요소의 실제 크기와 일치하는지 확인하기위한 것입니다. 보통은 특정 영역의 JScrollPane이 적용됩니다. – brad95411

답변

0

일부 무거운 파고 후, 스크롤 인터페이스는 저를 저장했다. 이를 구현하고이 example 다음의 각각의 메서드와 paintComponent에서 preferredSize 참조를 제거하면 내가 가지고있는 문제가 해결됩니다.