2012-09-16 127 views
0

我尋找的是安排了幾個數據的Java自定義佈局管理器(例如的JLabel)類似蝸牛的背線的方式。的Java蝸行佈局管理器

到目前爲止,我已經嘗試對圓周佈置,我發現在互聯網上進行自定義,但沒有運氣工作..任何想法?

+0

是標籤的文本沿水平方向排列的?或者它是否沿曲線對齊?後者用JLabel很難做,但用定製繪畫更容易。 –

+0

它基本上是一個圖表,我嘗試使用該佈局來排列節點,但是首先嚐試在JFrame中添加一些標籤以查看數據如何排列。這很簡單。 – kafou

+0

通過「蝸牛背線」DYM螺旋? *「任何想法???」*修復卡住'?'鍵和顯示[你曾嘗試](http://www.whathaveyoutried.com/)。 –

回答

2

您可以編寫自己的佈局。螺旋公式我從Spirals得到。它阿基米德而蝸牛更像Fermat's spiral,你可以改變calculatePoint()方法返回一個不同的螺旋。

注:這個佈局是有點低效率的,因爲它會重新計算,而不是每一個時代緩存它的所有部件的位置。

import java.awt.*; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.event.*; 

public class SpiralLayout implements LayoutManager2 { 

    private enum Size { MIN, MAX, PREF } 

    private double radiusStep; 
    private double angleStep; 

    public SpiralLayout() { 
     this(10, Math.toRadians(15.0)); 
    } 

    public SpiralLayout(double radius, double stepSize) { 
     this.radiusStep = radius; 
     this.angleStep = stepSize; 
    } 

    public void setRadiusStep(double radiusStep) { 
     this.radiusStep = radiusStep; 
    } 


    public void setAngleStep(double angleStep) { 
     this.angleStep = angleStep; 
    } 

    @Override 
    public void addLayoutComponent(String name, Component comp) { 
     // calculated on the fly 
    } 

    @Override 
    public void removeLayoutComponent(Component comp) { 
     // calculated on the fly 
    } 

    @Override 
    public Dimension preferredLayoutSize(Container parent) { 
     return getSize(parent, Size.PREF); 
    } 

    private Dimension getSize(Container parent, Size size) { 
     doLayoutContainer(parent, Short.MAX_VALUE, Short.MAX_VALUE, size); 

     Point min = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); 
     Point max = new Point(0, 0); 
     for(Component component : parent.getComponents()) { 
      Dimension preferredSize = getSize(component, size); 
      min.x = Math.min(min.x, component.getX()); 
      min.y = Math.min(min.y, component.getY()); 
      max.x = Math.max(max.x, component.getX() + preferredSize.width); 
      max.y = Math.max(max.y, component.getY() + preferredSize.height); 
     } 
     int center = Short.MAX_VALUE/2; 
     return new Dimension(
       Math.max(Math.abs(center - min.x), Math.abs(center - max.x) * 2), 
       Math.max(Math.abs(center - min.y), Math.abs(center - max.y) * 2)); 
    } 

    private Dimension getSize(Component component, Size size) { 
     switch(size) { 
     case MAX: 
      return component.getMaximumSize(); 
     case MIN: 
      return component.getMinimumSize(); 
     case PREF: 
      return component.getPreferredSize(); 
     default: 
      assert false : "Unknown size: " + size; 
      return new Dimension(); 
     } 
    } 

    @Override 
    public Dimension minimumLayoutSize(Container parent) { 
     return getSize(parent, Size.MIN); 
    } 

    @Override 
    public void layoutContainer(Container parent) { 
     doLayoutContainer(parent, 
       parent.getWidth(), parent.getHeight(), Size.PREF); 
    } 

    private List<Rectangle> doLayoutContainer(Container parent, 
      int width, int height, Size size) { 

     Point offset = new Point(width/2, height/2); 
     List<Rectangle> componentBounds = new ArrayList<Rectangle>(); 
     double angle = 0; 
     double radius = 1; 
     for(Component component : parent.getComponents()) { 
      Dimension preferredSize = getSize(component, size); 
      Rectangle bounds; 
      do { 
       bounds = new Rectangle(
         add(calculatePoint(angle, radius), offset), 
         preferredSize); 
       angle += angleStep; 
       radius += radiusStep; 
      } 
      while(overlaps(bounds, componentBounds)); 

      component.setBounds(bounds); 
      componentBounds.add(bounds); 
     } 
     return componentBounds; 
    } 

    private Point calculatePoint(double angle, double radius) { 
     double x = radius * Math.cos(angle); 
     double y = radius * Math.sin(angle); 
     return new Point((int) x, (int) y); 
    } 

    private boolean overlaps(Rectangle bounds, List<Rectangle> componentBounds) { 
     for(Rectangle other : componentBounds) { 
      if(other.intersects(bounds)) { 
       return true; 
      } 
     } 
     return false; 
    } 

    private Point add(Point a, Point b) { 
     return new Point(a.x + b.x, a.y + b.y); 
    } 

    @Override 
    public void addLayoutComponent(Component comp, Object constraints) { 
     // calculated on the fly 
    } 

    @Override 
    public Dimension maximumLayoutSize(Container parent) { 
     return getSize(parent, Size.MAX); 
    } 

    @Override 
    public float getLayoutAlignmentX(Container target) { 
     return 0.5f; 
    } 

    @Override 
    public float getLayoutAlignmentY(Container target) { 
     return 0.5f; 
    } 

    @Override 
    public void invalidateLayout(Container target) { 
     // calculated on the fly 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       final SpiralLayout layout = new SpiralLayout(); 
       final JPanel panel = new JPanel(layout); 

       final JSpinner angleSpinner = new JSpinner(new SpinnerNumberModel(Math.toDegrees(layout.angleStep), 1.0, 360.0, 5.0)); 
       angleSpinner.addChangeListener(new ChangeListener() { 
        @Override 
        public void stateChanged(ChangeEvent e) { 
         double angle = (Double) angleSpinner.getValue(); 
         layout.setAngleStep(Math.toRadians(angle)); 
         panel.revalidate(); 
        } 
       }); 
       final JSpinner radiusSpinner = new JSpinner(new SpinnerNumberModel((int) layout.radiusStep, 1, 1000, 1)); 
       radiusSpinner.addChangeListener(new ChangeListener() { 
        @Override 
        public void stateChanged(ChangeEvent e) { 
         int radius = (Integer) radiusSpinner.getValue(); 
         layout.setRadiusStep(radius); 
         panel.revalidate(); 
        } 
       }); 
       JPanel buttons = new JPanel(); 
       buttons.add(new JLabel("Radius step:")); 
       buttons.add(radiusSpinner); 
       buttons.add(new JLabel("Angle step")); 
       buttons.add(angleSpinner); 

       for(int i = 1; i <= 25; i++) { 
        panel.add(new JLabel("Label " + i)); 
       } 
       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       frame.getContentPane().add(buttons, BorderLayout.PAGE_START); 
       frame.getContentPane().add(panel); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 
}