2016-08-19 40 views
0

我有一个包含带有行和列标题的表的JFrame。 我的表格是由3个面板(行标题,列标题和网格)组成的自定义组件。 面板是常规的JPanel,包含JButton或JLabel,在MigLayout中。 我在JScrollPane中显示这个组件,以便同时滚动我的网格和我的标题。 这部分工作正常。使用标题放大JScrollPane

现在,用户应该能够放大我的组件。

我尝试过使用pbjar JXLayer,但是如果将整个JScrollPane放入图层中,则一切都会放大,并且事件滚动条。

我试着用3个JXLayers,一个用于我的JScrollPane的每个viewPort。但是这个解决方案只是混淆了我的布局,因为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); 
    } 
} 

如何在不缩放scrollBars的情况下处理JScrollPane上的缩放并且不会弄乱我的布局?

回答

0

首先,MigLayout似乎与JXLayer不兼容。同时使用时,使用MigLayout的面板中的组件具有不可预知的行为。

然后,原始pbjar JXLayer只允许您将组件放在图层窗格的中心。 Pbjar来源可以下载on github。请注意,这不是官方的Piet Blok仓库。

我发现的解决方案是修改TransformLayoutTransformUITranformModel类:

Alignment枚举得到可能的对准对于该层中的组分。

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

TransformLayout

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

现在,您可以创建一个配置可缩放的面板可用排列使用:

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

注意这是一个快速修复。它可能可以改进。