2013-04-24 6 views
1

나는 어디에서나 이미지를 그리는 방법에 사교육이 있다는 것을 알고있다. 일반적으로 사람들은 이미지를로드하는 객체를 추가하여 이미지를 표시 할 것을 제안합니다. 그러나 제 경우에는 이미지에서 어떤 것을 바꿀 때마다 새로운 객체를 인스턴스화하고 싶지 않습니다.자바 그리기 이미지 JPanel : 작동하지만 이상한

그래서 그래픽 클래스를 사용하고 있습니다. 또한 MVC 방식을 사용하고 있습니다.

문제점 : 우리가 보는 바와 같이, I는 다른 이미지를로드하면 그려지는 이미지의 작은 영역에 존재 이 작은 영역 화상에 따라 변경한다. 그런 다음 버퍼링 된 이미지가 올바르게로드되었다고 가정합니다.

그래서, 문제가 될 것입니다 곳을 찾고 : 이 나의 코드 :

import java.awt.FlowLayout; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.util.Observable; 
import java.util.Observer; 

import javax.swing.JFileChooser; 
import javax.swing.JFrame; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JPanel; 

public class DisplayView extends JFrame implements Observer { 

    private static final long serialVersionUID = 1L; 
    /** 
    * @param args 
    */ 
    private static DisplayView instance; 
    private DisplayControl control; 
    private JFileChooser fileChooser; 

    Panel imageLeft, imageRight; 

    private DisplayView() { 

     JMenuItem exit = new JMenuItem("Exit"); 
     exit.setMnemonic('E'); 
     exit.setToolTipText("Exit Application"); 
     exit.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       System.exit(0); 
      } 
     }); 

     fileChooser = new JFileChooser(); 
     fileChooser.setFileFilter(new ImageFileFilter()); 

     JMenuItem loadImage = new JMenuItem("Load Image"); 
     loadImage.setMnemonic('O'); 
     loadImage.setToolTipText("Loads an Image to Process"); 
     loadImage.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent event) { 
       int ret = fileChooser.showDialog(DisplayView.getInstance(), 
         "Open file"); 

       if (ret == JFileChooser.APPROVE_OPTION) { 
        System.out.println(fileChooser.getSelectedFile()); 
        control.onFileChoose(fileChooser.getSelectedFile() 
          .getAbsolutePath()); 
       } 
      } 
     }); 

     JMenu file = new JMenu("File"); 
     file.setMnemonic('F'); 
     file.add(loadImage); 
     file.add(exit); 

     JMenuBar menuBar = new JMenuBar(); 
     menuBar.add(file); 

     imageLeft = new Panel(); 
     imageLeft.setSize(500, 500); 
     imageLeft.setVisible(true); 

     imageRight = new Panel(); 

     this.setLayout(new FlowLayout()); 
     this.add(imageLeft); 
     // this.add(imageRight); 

     this.setTitle("Test"); 
     this.setSize(300, 200); 
     this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     this.setJMenuBar(menuBar); 
    } 

    static public DisplayView getInstance() { 
     if (instance == null) 
      instance = new DisplayView(); 
     return DisplayView.instance; 
    } 

    public void setControl(DisplayControl control) { 
     this.control = control; 
    } 

    @Override 
    public void update(Observable o, Object arg) { 
     // TODO Auto-generated method stub 
     if (o instanceof DisplayModel) { 
      this.imageLeft.setImage(((DisplayModel) o).getOriginalImage()); 
      // this.imageRight.setImage(((DisplayModel) o).getProcessedImage()); 

     } 
    } 

} 

class Panel extends JPanel { 

    BufferedImage image; 

    public void setImage(BufferedImage image) { 
     if (image != null) 
      this.image = image; 
     this.repaint(); 
    } 

    @Override 
    public void paint(Graphics g) { 
     // TODO Auto-generated method stub 
     super.paint(g); 
     if (image != null) 
      g.drawImage(image, 0, 0, this); 
    } 
} 
+0

사용자 정의 회화

  • paintComponent보다는를 오버라이드 (override)은 "적절한 LayoutManager 사용"대답은 항상 동일합니다? 그냥 다시 그걸 수정하지 못했습니다? –

  • +0

    이것은 단순한 응용 프로그램의보기입니다. 따라서 모델의 이미지가 변경 될 때마다 뷰는 알림을 받고 이미지를 다시 설정하고 다시 그리기 작업을 수행합니다. 권리? –

    +0

    그런 식으로 할 수도 있고, 주변에두고 재사용 할 수도 있습니다. 어느 쪽이든 작동합니다. –

    답변

    1

    문제는 Panel 클래스 getPreferredSize()을 무시하고 그렇게 선호하지 않는다는 것입니다 크기는 실제로 (0,0)이므로 FlowLayoutPanel에 (0,0) 크기를 할당합니다.

    어쨌든, JLabel은 정확히 동일한 작업을 수행하고 원하는 크기를 처리하기 위해 Panel 클래스를 교체하는 것이 좋습니다.

    • setSize()을 호출하면 LayoutManager를 사용해야 할 때 쓸모가 없습니다. 일반적으로 setSize/setLocation/setBounds/setPreferredSize을 잊어 버리는 것이 일반적입니다. 당신이 당신의 이미지에 무엇을 변경하고 있는지 paint
    +0

    +1, 나는 JLabel을 사용하는 당신의 제안을 간과했다. OP는 커스텀 페인팅 경로를 따라 계속 진행될 때'repaint()'를 호출하기 전에 컴포넌트를 revalidate()해야 할 것이다. – camickr

    +0

    @camickr 나는 당신의 대답도 +1하려했으나 삭제 되었기 때문에 거부했다. ;-). 예, 사용자 정의 페인팅 경로는 작업하기 위해 많은 개선이 필요합니다. –

    +0

    답변 해 주셔서 감사합니다. JPanel 크기로 뭔가있을 수 있다고 상상했기 때문에 setSize 행의 코드에 삽입했습니다. 몇 가지 테스트를 수행했습니다. 1 - 방금 JLabel 용 JPanel을 대체했습니다.하지만 그 무엇도 그려지지 않았습니다. 이미지의 작은 사각형도 아닙니다. 2 -이 줄을 setImage에 Panel 클래스에 삽입했습니다. this.setPreferredSize (새 Dimension (image.getWidth(), image.getHeight())); - 나는 첫 번째 결과를 바꾸지 않았다. 3 - 레이아웃 관리를 정의하는 라인에 주석을 달아서, 기본 레이아웃을 사용하여 멋지게 작업했습니다. 하지만이 레이아웃 관리를 사용하여 어떻게 관리하는지 궁금합니다. Thks –