2012-04-20 54 views
21

我想佈局一些的JLabel在我的應用程序如本例所示:哪些佈局可以做到這一點?

enter image description here

我總是在中間此JLabel和其他人的JLabel的數量是可變它可以從1走30。我已經選擇好的數列/行,並在空格設置一些空的JLabel嘗試網格佈局,但我不能得到一個好的結果,並不能找到如何與MigLayout做到這一點,沒有任何一個具有良好的佈局結構或任何其他解決方案。

PS:我不想顯示圓圈,它只是表明JLabels是在一個圓圈中排列的。

+0

好問題,並且非常描述性(小以字節爲單位)的圖像。 +1 – 2012-04-20 09:37:22

+1

謝謝,我想在這裏後,連續30天,我開始有點適應:) – 2012-04-20 11:31:09

回答

14

我懷疑你的要求是如此專業,有沒有佈局管理,可以做你所需要的。 Try creating your own!

+0

我想你已經釘這一個。 +1 – 2012-04-20 09:37:42

+1

...然後來@Peter證明我錯了!:) – vaughandroid 2012-04-20 09:44:54

+0

**在開始創建自定義佈局管理器之前,請確保沒有現有的佈局管理器符合您的要求。** - >所以通過結合您的答案和@Peter的一個我可以得到它,+1 – 2012-04-20 10:23:37

13

JH實驗室有ClockLayout

這是一個特殊目的創造了一個非常愚蠢的佈局。它只是從頂部順時針將其組件放置在一個圓圈內。

+0

偉大的佈局,但這裏沒有中心元素,所以我必須實現我的自定義clocklayout。 +1 – 2012-04-20 10:21:17

3

我使用的是Windows窗體,因爲我沒有安裝Java工具,但想法是一樣的,您將不得不想象您將添加JLabel而不是按鈕,並且這是一個JFrame或JWindow而不是.NET Form。

代碼應該是這樣的,如果我們假設800×800像素的區域佈局上

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     this.Load += new EventHandler(Form1_Load); 
    } 

    void Form1_Load(object sender, EventArgs e) 
    { 
     int numberItems = 18; 
     int centreX = 400; 
     int centreY = 400; 


     double offset = Math.PI; 
     double step = Math.PI * 2/numberItems; 


     Button b = null; 
     for (int i = 0; i < numberItems; i++) 
     { 
      b = new Button(); 
      b.Width = 30; 
      b.Height = 30; 
      SetPosition(b, 370, offset, i, step); 
      this.Controls.Add(b); 
     } 

     b = new Button(); 
     b.Width = 30; 
     b.Height = 30; 
     b.Location = new Point(centreX, centreY); 
     this.Controls.Add(b); 
    } 


    private void SetPosition(Button button, int legLength, double offset, double posOffSet, double step) 
    { 

     int x = (int)(legLength + Math.Sin(offset + posOffSet * step) * legLength); 
     int y = (int)(legLength + Math.Cos(offset + posOffSet * step) * legLength); 

     button.Location = new Point(x, y); 
    } 
} 
+0

謝謝,但我想要一個佈局解決方案,因爲它不建議使用絕對定位。 – 2012-04-20 10:19:53

+0

噢,好吧,你不可以創建自己的佈局管理器,根據面板的實際寬度計算出點數?只是一個因素類型的東西 – sacha 2012-04-20 10:36:58

4

我喜歡@東東Baqueta的和@薩沙的想法:

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

public class CircleLayoutTest { 
    public JComponent makeUI() { 
    JPanel panel = new JPanel() { 
     @Override protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Insets i = getInsets(); 
     g.translate(i.left, i.top); 
     g.setColor(Color.RED); 
     int w = getWidth() - i.left - i.right; 
     int h = getHeight() - i.top - i.bottom; 
     g.drawOval(0, 0, w, h); 
     g.translate(-i.left, -i.top); 
     } 
    }; 
    panel.setLayout(new FlowLayout() { 
     @Override public void layoutContainer(Container target) { 
     synchronized(target.getTreeLock()) { 
      int nmembers = target.getComponentCount(); 
      if(nmembers<=0) return; 
      Insets i = target.getInsets(); 
      double cx = .5 * target.getWidth(); 
      double cy = .5 * target.getHeight(); 
      Component m = target.getComponent(0); 
      Dimension d = m.getPreferredSize(); 
      m.setSize(d.width, d.height); 
      m.setLocation((int)(cx+.5-.5*d.width),(int)(cy+.5-.5*d.height)); 
      if(nmembers-1<=0) return; 
      double rw = .5 * (target.getWidth() - i.left - i.right); 
      double rh = .5 * (target.getHeight() - i.top - i.bottom); 
      double x = 0, y = 0, r = 0; 
      double radian = 2.0 * Math.PI/(nmembers-1); 
      for(int j=1; j<nmembers; j++) { 
      m = target.getComponent(j); 
      if(m.isVisible()) { 
       d = m.getPreferredSize(); 
       m.setSize(d.width, d.height); 
       x = cx + rw * Math.cos(r) - .5 * d.width; 
       y = cy + rh * Math.sin(r) - .5 * d.height; 
       m.setLocation((int)(x+.5), (int)(y+.5)); 
       r += radian; 
      } 
      } 
     } 
     } 
    }); 
    JPanel p = new JPanel(new BorderLayout()); 
    p.add(initPanel(panel)); 
    return p; 
    } 
    private static JComponent initPanel(JComponent p) { 
    p.setBorder(BorderFactory.createEmptyBorder(50,50,50,50)); 
    for(int i=0; i<6; i++) { 
     p.add(new JLabel("No."+i)); 
    } 
    return p; 
    } 
    public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     @Override public void run() { 
     createAndShowGUI(); 
     } 
    }); 
    } 
    public static void createAndShowGUI() { 
    JFrame f = new JFrame(); 
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    f.getContentPane().add(new CircleLayoutTest().makeUI()); 
    f.setSize(320 ,320); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
    } 
} 
+0

,我喜歡你的大多數代碼+1,只有你的代碼在所有方向上都可以被重新分配,非常感謝你 – mKorbel 2012-04-20 17:18:17

+0

我喜歡它順利調整大小的事實。 +1 – 2012-04-20 17:33:46

18

你不不需要一個專門支持這個的佈局管理器。可以計算出X,Y定位自己與一些相當簡單的三角函數,然後使用常規的佈局,如SpringLayout

import java.awt.Point; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SpringLayout; 

public class CircleLayout { 

    /** 
    * Calculate x,y positions of n labels positioned in 
    * a circle around a central point. Assumes AWT coordinate 
    * system where origin (0,0) is top left. 
    * @param args 
    */ 
    public static void main(String[] args) { 
    int n = 6; //Number of labels 
    int radius = 100; 
    Point centre = new Point(200,200); 

    double angle = Math.toRadians(360/n); 
    List<Point> points = new ArrayList<Point>(); 
    points.add(centre); 

    //Add points 
    for (int i=0; i<n; i++) { 
     double theta = i*angle; 
     int dx = (int)(radius * Math.sin(theta)); 
     int dy = (int)(-radius * Math.cos(theta)); 
     Point p = new Point(centre.x + dx, centre.y + dy); 
     points.add(p); 
    } 

    draw(points); 
    } 

    private static void draw(List<Point> points) { 
    JFrame frame = new JFrame("Labels in a circle"); 
    frame.setSize(500, 500); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    JPanel panel = new JPanel();; 
    SpringLayout layout = new SpringLayout(); 

    int count = 0; 
    for (Point point : points) { 
     JLabel label = new JLabel("Point " + count); 
     panel.add(label); 
     count++; 
     layout.putConstraint(SpringLayout.WEST, label, point.x, SpringLayout.WEST, panel); 
     layout.putConstraint(SpringLayout.NORTH, label, point.y, SpringLayout.NORTH, panel); 
    } 

    panel.setLayout(layout); 

    frame.add(panel); 
    frame.setVisible(true); 

    } 
} 

the maths screenshot

+0

哇,這很有趣:-) – 2012-04-20 11:55:52

2
  1. MigLayout可以做到絕對定位與 「POS X Y [X2] [Y2]」 作爲組分約束。 MigLayout真的是佈局經理來統治他們。看看他們的頭版Webstart的演示,它展示了良好的絕對定位。你仍然要計算像與自定義佈局管理理念組件的位置。

  2. 你也可以只turn off the layout

  3. 如果你想獲得真正的創意,你可以看看JHotDraw