2016-08-19 45 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) 

注意這是一個快速修復。它可能可以改進。