2012-04-20 64 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