2016-08-19 3 views
0

Ich habe einen JFrame, der eine Tabelle mit Zeilen- und Spaltenüberschriften enthält. Meine Tabelle ist eine benutzerdefinierte Komponente aus 3 Bereichen (Zeilenkopf, Spaltenkopf und Raster). Die Panels sind normale JPanels, die entweder JButton oder JLabel enthalten, in einem MigLayout. Ich zeige diese Komponente in einem JScrollPane an, um gleichzeitig mein Raster und meine Header zu scrollen. Dieser Teil funktioniert gut.Zoom auf ein JScrollPane mit Kopfzeilen

Jetzt sollte der Benutzer in der Lage sein, auf meine Komponente zu zoomen.

Ich habe versucht, die Pbjar JXLayer zu verwenden, aber wenn ich meine ganze JScrollPane in die Ebene einfügen, wird alles gezoomt, Ereignis die Bildlaufleisten.

Ich habe versucht, 3 JXLayers zu verwenden, einen für jeden viewPort meiner JScrollPane. Aber diese Lösung ist nur ein Fehler in meinem Layout, da die Panels innerhalb der ViewPorts zentriert werden, anstatt dass sie von oben nach links ausgerichtet sind.

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

Wie kann ich den Zoom auf meinem JScrollPane behandeln, ohne auf den Bildlaufleisten ein- und ohne mein Layout vermasselt?

Antwort

0

Erstens scheint MigLayout mit dem JXLayer nicht kompatibel zu sein. Wenn beide Komponenten verwendet werden, haben die Komponenten im Panel, die MigLayout verwenden, ein unvorhersagbares Verhalten.

Dann können Sie mit dem ursprünglichen pbjar JXLayer nur Ihre Komponente in der Mitte des Ebenenfensters platzieren. Pbjar Quellen können on github herunterladen. Beachten Sie, dass dies nicht das offizielle Repository von Piet Blok ist.

Die Lösung gefunden ist, die TransformLayout, TransformUI und die TranformModel Klassen zu modifizieren:

Alignment ENUM die mögliche Ausrichtung für die Komponente in der Schicht ergeben.

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

In 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); 
} 

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

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

Sie können nun eine zoombare Panel mit Config erstellen erbarbare Ausrichtung mit:

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

Beachten Sie, das ist eine schnelle Lösung. Es kann wahrscheinlich verbessert werden.