2016-08-19 5 views
0

행 헤더와 열 헤더가있는 테이블이 포함 된 JFrame이 있습니다. 내 테이블은 3 개의 패널 (행 머리글, 열 머리글 및 눈금)로 구성된 사용자 지정 구성 요소입니다. 패널은 JBL 또는 JLabel을 포함하는 일반 JPanel이며 MigLayout에 있습니다. JScrollPane 안에이 구성 요소를 표시하여 모눈과 머리글을 동시에 스크롤합니다. 이 부분은 정상적으로 작동합니다.헤더가있는 JScrollPane 확대

이제 사용자는 내 구성 요소를 확대 할 수 있어야합니다.

pbjar JXLayer를 사용하려고했지만 레이어 전체에 JScrollPane을 배치하면 모든 것이 확대되고 이벤트는 스크롤 막대가됩니다.

JScrollPane의 각 viewPort에 하나씩 3 개의 JXLayers를 사용하려고했습니다. 하지만이 솔루션은 viewPorts 내부의 패널이 왼쪽 상단에 배치되는 대신 중앙에 배치되므로 레이아웃이 엉망입니다.

import org.jdesktop.jxlayer.JXLayer; 
import org.pbjar.jxlayer.demo.TransformUtils; 
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel; 

public class Matrix extends JScrollPane { 

    private Grid grid; 
    private Header rowHeader; 
    private Header columnHeader; 

    private DefaultTransformModel zoomTransformModel; 
    private double zoom = 1; 

    public Matrix() { 
     super(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); 

     this.zoomTransformModel1 = new DefaultTransformModel(); 
     this.zoomTransformModel1.setScaleToPreferredSize(true); 
     this.zoomTransformModel1.setScale(1); 
     this.zoomTransformModel2 = new DefaultTransformModel(); 
     this.zoomTransformModel2.setScaleToPreferredSize(true); 
     this.zoomTransformModel2.setScale(1); 
     this.zoomTransformModel3 = new DefaultTransformModel(); 
     this.zoomTransformModel3.setScaleToPreferredSize(true); 
     this.zoomTransformModel3.setScale(1); 

     this.grid = new Grid(); 

     this.setViewportView(TransformUtils.createTransformJXLayer(this.grid, 
       zoomTransformModel1);); 
     this.matrixRowHeader = new Header(Orientation.VERTICAL); 
     this.setRowHeader(new JViewport(
       TransformUtils.createTransformJXLayer(
        this.rowHeader, zoomTransformModel2))); 

     this.matrixColumnHeader = new Header(Orientation.HORIZONTAL); 
     this.setColumnHeader(new JViewport(
       TransformUtils.createTransformJXLayer(
        this.columnHeader, zoomTransformModel2))); 
    } 

    public void setScale(double scale) { 
     this.zoomTransformModel1.setScale(scale); 
     this.zoomTransformModel2.setScale(scale); 
     this.zoomTransformModel3.setScale(scale); 
    } 
} 

스크롤 막대를 확대하지 않고 레이아웃을 망칠 필요없이 JScrollPane의 확대/축소를 처리하는 방법은 무엇입니까?

답변

0

먼저 MigLayout이 JXLayer와 호환되지 않는 것으로 보입니다. 둘 다 사용하면 MigLayout을 사용하는 패널의 구성 요소에 예기치 않은 동작이 발생합니다.

그런 다음 원본 pbjar JXLayer를 사용하면 구성 요소를 레이어 창 가운데에만 놓을 수 있습니다. Pbjar 소스는 on github을 다운로드 할 수 있습니다. 이것은 공식 Piet Blok 저장소가 아닙니다.

I 발견 해결책은 TransformLayout, TransformUI를 수정하고, 상기 클래스 TranformModel :

Alignment ENUM은 층의 구성 요소에 대한 가능한 배열을 제공한다. TransformLayout에서

public enum Alignment { 
    TOP, 
    BOTTOM, 
    LEFT, 
    RIGHT, 
    CENTER 
} 

:

@Override 
public void layoutContainer(Container parent) { 
    JXLayer<?> layer = (JXLayer<?>) parent; 
    LayerUI<?> layerUI = layer.getUI(); 
    if (layerUI instanceof CustomTransformUI) { 
     JComponent view = (JComponent) layer.getView(); 
     JComponent glassPane = layer.getGlassPane(); 
     if (view != null) { 
     Rectangle innerArea = new Rectangle(); 
     SwingUtilities.calculateInnerArea(layer, innerArea); 
     view.setSize(view.getPreferredSize()); 
     Rectangle viewRect = new Rectangle(0, 0, view.getWidth(), view 
      .getHeight()); 
     int x; 
     int y; 
     Alignment alignX = ((CustomTransformUI) layerUI).getAlignX(); 
     Alignment alignY = ((CustomTransformUI) layerUI).getAlignY(); 
     if(alignX == Alignment.LEFT) { 
      x = (int) (innerArea.getX() - viewRect.getX()); 
     } else if(alignX == Alignment.RIGHT) { 
      x = (int) (innerArea.getX()+innerArea.getWidth()-viewRect.getWidth()-viewRect.getX()); 
     } else { 
      x = (int) Math.round(innerArea.getCenterX() 
        - viewRect.getCenterX()); 
     } 
     if(alignY == Alignment.TOP) { 
      y = (int) (innerArea.getY() - viewRect.getY()); 
     } else if(alignY == Alignment.BOTTOM) { 
      y = (int) (innerArea.getY()+innerArea.getHeight()-viewRect.getHeight()-viewRect.getY()); 
     } else { 
      y = (int) Math.round(innerArea.getCenterY() 
        - viewRect.getCenterY()); 
     } 
     viewRect.translate(x, y); 
     view.setBounds(viewRect); 

     } 
     if (glassPane != null) { 
     glassPane.setLocation(0, 0); 
     glassPane.setSize(layer.getWidth(), layer.getHeight()); 
     } 
     return; 
    } 
    super.layoutContainer(parent); 
} 

TransformUI에서 :

private Alignment alignX; // horizontal alignment 
private Alignment alignY; // verticalalignment 

public TransformUI(TransformModel model, Alignment alignX, Alignment alignY) { 
    super(); 
    this.setModel(model); 
    this.alignX = alignX; 
    this.alignY = alignY; 
} 

public Alignment getAlignX() { 
    return alignX; 
} 

public Alignment getAlignY() { 
    return alignY; 
} 

TransformModel에서 :

private Alignment alignX = Alignment.CENTER; 
private Alignment alignY = Alignment.CENTER; 

public CustomTransformModel(Alignment alignX, Alignment alignY) { 
    super(); 
    this.alignX = alignX; 
    this.alignY = alignY; 
} 

@Override 
public AffineTransform getTransform(JXLayer<? extends JComponent> layer) { 
    JComponent view = (JComponent)layer.getView(); 
    /* 
    * Set the current actual program values in addition to the user 
    * options. 
    */ 
    this.setValue(Type.LayerWidth, layer == null ? 0 : layer.getWidth()); 
    this.setValue(Type.LayerHeight, layer == null ? 0 : layer.getHeight()); 
    this.setValue(Type.ViewWidth, view == null ? 0 : view.getWidth()); 
    this.setValue(Type.ViewHeight, view == null ? 0 : view.getHeight()); 
    /* 
    * If any change to previous values, recompute the transform. 
    */ 
    if (!Arrays.equals(this.prevValues, this.values)) { 
     System.arraycopy(this.values, 0, this.prevValues, 0, this.values.length); 
     this.transform.setToIdentity(); 
     if (view != null) { 
      double scaleX; 
      double scaleY; 
      double centerX; 
      if(this.alignX == Alignment.LEFT) { 
       centerX = 0.0; 
      } else if (this.alignX == Alignment.RIGHT){ 
       centerX = layer == null ? 0.0 : (double)layer.getWidth(); 
      } else { 
       centerX = layer == null ? 0.0 : (double)layer.getWidth()/2.0; 
      } 
      double centerY; 
      if(this.alignY == Alignment.TOP) { 
       centerY = 0.0; 
      } else if(this.alignY == Alignment.BOTTOM){ 
       centerY = layer == null ? 0.0 : (double)layer.getHeight(); 
      } else { 
       centerY = layer == null ? 0.0 : (double)layer.getHeight()/2.0; 
      } 
      AffineTransform nonScaledTransform = this.transformNoScale(centerX, centerY); 
      if (((Boolean)this.getValue(Type.ScaleToPreferredSize)).booleanValue()) { 
       scaleY = scaleX = ((Double)this.getValue(Type.PreferredScale)).doubleValue(); 
      } else { 
       Area area = new Area(new Rectangle2D.Double(0.0, 0.0, view.getWidth(), view.getHeight())); 
       area.transform(nonScaledTransform); 
       Rectangle2D bounds = area.getBounds2D(); 
       scaleX = layer == null ? 0.0 : (double)layer.getWidth()/bounds.getWidth(); 
       scaleY = layer == null ? 0.0 : (double)layer.getHeight()/bounds.getHeight(); 
       if (((Boolean)this.getValue(Type.PreserveAspectRatio)).booleanValue()) { 
        scaleY = scaleX = Math.min(scaleX, scaleY); 
       } 
      } 
      this.transform.translate(centerX, centerY); 
      this.transform.scale((Boolean)this.getValue(Type.Mirror) != false ? - scaleX : scaleX, scaleY); 
      this.transform.translate(- centerX, - centerY); 
      this.transform.concatenate(nonScaledTransform); 
     } 
    } 
    return this.transform; 
} 

는 이제 config로 줌 가능한 패널을 만들 수 있습니다 유휴 정렬 :

TransformModel model = new TransformModel(Alignment.LEFT, Alignment.TOP); 
TransformUI ui = new TransformUI(model, Alignment.LEFT, Alignment.TOP); 
new JXLayer((Component)component, (LayerUI)ui) 

빠른 픽스입니다. 그것은 아마도 개선 될 수 있습니다.