2012-06-28 3 views
1

이미지를 편집 할 수있는 간단한 앱을 만들고 싶습니다. 앱의 기본보기에는 JSplitPane과 두 개의 JScrollPane이 포함되어 있습니다. JScrollPane에는 각각 JPanel이 포함됩니다. 오른쪽 JPanel에는 여러 버튼이 있으며 왼쪽은 JPanel입니다. 내 그림 영역입니다. 내가 처음 내가 원하는 크기를 설정할 수 JPanelDrawingArea을 만들어JScrollPane이 JSplitPane의 JScrollBar를 업데이트하지 않습니다.

다음

내 문제는 ...

. 크기가 JScrollPane 크기보다 큰 경우 JScrollBars이 표시됩니다 (기본값은 같음). 그러나 이미지를 JPanelDrawingArea에로드 할 때 스크롤 막대가 업데이트되지 않습니다. 사실 JPanelDrawingArea (크기가 JScrollPane보다 큽니다)의 새로운 기본 크기를 설정 했음에도 불구하고 수동으로 JSplitPanes 분할 자 위치를 변경하지 않으면 스크롤 막대가 업데이트되지 않습니다. 여기

JSplitPane 사용자 정의 클래스입니다 :

public class DrawingPaneView extends JSplitPane{ 

private DrawingWorkMode drawingWorkMode; 
private ImageWorkerView imageWorker; 
JScrollPane workScrollPane; 
JScrollPane pictureScrollPane; 
private DrawingPaneController controller; 

private Dimension minimumSize = new Dimension(100, 200); 
private JPanel imagePanel; 


public DrawingPaneView() { 

    setPreferredSize(new Dimension(ConfigClass.APP_WIDTH,ConfigClass.DRAWING_PANE_HEIGHT)); 
    controller = new DrawingPaneController(this); 

    //Panel 
    drawingWorkMode = new DrawingWorkMode(); 
    workScrollPane = new JScrollPane(drawingWorkMode); 

    //Image 
    imageWorker = new ImageWorkerView(); 
    pictureScrollPane = new JScrollPane(imageWorker); 


    workScrollPane.setMinimumSize(minimumSize); 
    pictureScrollPane.setMinimumSize(minimumSize); 


    //addJPanels 
    this.setOrientation(JSplitPane.HORIZONTAL_SPLIT); 
    this.setRightComponent(workScrollPane); 
    this.setLeftComponent(pictureScrollPane); 

    //addLeftPanelWithJButtonOnly 
    imagePanel = new ImagePanelView(); 
    pictureScrollPane.setRowHeaderView(imagePanel); 

    this.setDividerLocation(ConfigClass.DRAWING_PANE_WIDTH); 
    this.setOneTouchExpandable(true); 

} 

//Change mode 
public void changeMode(String mode){ 
    drawingWorkMode.changeMode(mode); 
}  
} 

그리고 그리기 수행 내 사용자 지정 JPanel가 :

public class ImageWorkerView extends JPanel { 

private BufferedImage img; 
private ImageWorkerController controller; 
private int defaultBounds = 50; 
private double scale=1.0; 
int imgW; 
int imgH; 

public ImageWorkerView() { 
    //setLayout(new BorderLayout(0, 0)); 
    controller = new ImageWorkerController(this); 
} 


public void setScale(double scale) { 
    this.scale = scale; 
} 

public void setImage(File image) { 
    try { 
     img = ImageIO.read(image); 
     if (img.getType() != BufferedImage.TYPE_INT_RGB) { 
      BufferedImage img2 = 
       new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB); 
      Graphics big = img2.getGraphics(); 
      big.drawImage(img, 0, 0, null); 
      img = img2; 
     } 
    } catch (IOException e) { 
     System.out.println("Image could not be read"); 
    } 
} 

private void adjustPreferredSize(Boolean defaultSize){ 

    if(defaultSize){ 
     //Calculate the proper size of drawing area 
     imgW = ConfigClass.DRAWING_PANE_WIDTH - ImagePanelView.PREFERRED_WIDTH-10; 
     imgH = ConfigClass.DRAWING_PANE_HEIGHT-50; 
     setPreferredSize(new Dimension(imgW,imgH)); 
     controller.setWindowHeight(imgH); 
    } 
    else{ 
     imgW = (int)(img.getWidth() * scale + (defaultBounds*2)); 
     imgH = (int)(img.getHeight() * scale + (defaultBounds*2)); 
     setPreferredSize(new Dimension(imgW,imgH)); 
     controller.setWindowHeight(imgH); 
    } 
} 

@Override 
public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2 = (Graphics2D) g; 

    if(img!=null){ 
     if(scale!=1.0){ 
      AffineTransform at = AffineTransform.getScaleInstance(scale, scale); 
      AffineTransformOp aop = 
       new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC); 
      g2.drawImage(img, aop, defaultBounds, defaultBounds); 
     } 
     else 
      g2.drawImage(img, defaultBounds, defaultBounds, null); 
     adjustPreferredSize(false); 
    } 
    else{ 
     adjustPreferredSize(true); 
    } 



} 
} 

을 그리고 난이 이미지로드 방법 :

public class ImageWorkerController { 
ImageWorkerView view; 
ImageModel model; 


public ImageWorkerController(ImageWorkerView workerView) { 
    this.view = workerView; 
    this.model = ApplicationContext.getObject(ImageModel.class); 

    //Load image 
    ApplicationContext.getObject(Context.class).addPropertyChangeListener(new PropertyChangeListener() { 
     public void propertyChange(PropertyChangeEvent evt) { 
      if(Context.IMAGE_LOADED.equals(evt.getPropertyName())){ 
       view.setImage((File) evt.getNewValue()); 
       view.repaint(); 
      } 
     } 
    }); 

public void setWindowHeight(int h){ 
    model.setDrawingWindowHeight(h); 
} 

}

처음 보았을 때 adjustPreferredSize() 메서드가 있으며 JScrollPane보다 큰 preferredSize을 설정하면 JScrollBars이 표시됩니다. 그러나 그것이 다시 불릴 때 그것은 아무것도하지 않습니다.

http://s17.postimage.org/e1nkja3zx/liliebead.jpg

그래서 업데이트 할 JScrollPane를 만드는 이벤트의 어떤 종류가있다 : 당신이 예를 아래에

흥미있는 무엇, 때 수동으로 화면에 JScrollBars가 표시 디바이더의 위치를 ​​변경? 몇 가지 방법을 시도했습니다 : updateUI(), repaint(), revalidate(). 그들 중 누구도 일하지 않았습니다.

내가 잘못하고있는 아이디어가 있습니까?

답변

2

요약하면 ImageWorkerView (repaint()이라고하는 곳)의 revalidate()이 필요합니다. 이렇게하면 구성 요소와 부모에게 "다시 레이아웃"을 요청하고 차례로 스크롤 막대에 필요한 조정을 트리거합니다.

0

답장을 보내 주셔서 감사합니다. 당신의 제안은 저를 생각하게했습니다. 실제로 내가 잘못한 것은 repaint() 다음에 revalidate() immediatelly이므로 메서드 이전에 revalidate() 메서드가 실행되고 ImageWorkerView 메서드에서 실행됩니다 (디버깅 중에이 오류가 발견되었습니다).

ApplicationContext.getObject(Context.class).addPropertyChangeListener(new PropertyChangeListener() { 
     public void propertyChange(PropertyChangeEvent evt) { 
      if(Context.IMAGE_LOADED.equals(evt.getPropertyName())){ 
       view.setImage((File) evt.getNewValue()); 
       //view.repaint(); 
       view.paintImmediately(new Rectangle(1, 1)); 
       view.revalidate(); 
      } 
     } 
    }); 

그래서 지금 paintComponent 세트를 선호하는 크기와 다음 revalidate()는 스크롤 막대를 조정 :이 작업을 수행 할 수있는 적절한 방법이다.