2012-04-20 17 views
21

Estoy intentando a la disposición algunos JLabels en mi solicitud como se muestra en este ejemplo:¿Qué diseño puede hacer esto?

enter image description here

siempre tengo este JLabel en el medio y el número de los otros JLabels es variable que puede ir desde 1 a 30. He intentado el diseño de cuadrícula eligiendo un buen número de columnas/filas y estableciendo JLabels vacías en el espacio en blanco pero no puedo obtener un buen resultado, y no puedo encontrar cómo hacerlo con MigLayout, hice uno tiene una buena solución de diseño o cualquier otra solución.

PS: No quiero mostrar el círculo, solo para mostrar que las JLabels están dispuestas en un círculo.

+0

Buena pregunta, y muy descriptiva (y pequeña en bytes) imagen. +1 –

+1

Gracias, creo que después de 30 días consecutivos aquí, comencé a adaptar un poco :) –

Respuesta

14

Sospecho que sus requisitos son tan especializados que no existe un LayoutManager que pueda hacer lo que necesita. Try creating your own!

+0

Creo que has clavado este. +1 –

+1

... ¡y luego viene @Peter para demostrarme que estoy equivocado!:) – vaughandroid

+0

** Antes de comenzar a crear un administrador de diseño personalizado, asegúrese de que ningún administrador de diseño existente cumpla con sus requisitos. ** -> por lo que al combinar su respuesta y la de @Peter puedo obtenerlo, +1 –

13

JH laboratorios tiene un ClockLayout:

Esto es un diseño muy tonta creado para un propósito especial. Simplemente establece sus componentes en un círculo, en el sentido de las agujas del reloj desde la parte superior.

+0

Gran diseño, pero aquí no hay ningún elemento central, por lo que tengo que implementar mi diseño de reloj personalizado. +1 –

3

estoy usando formularios de Windows, ya que no tiene instalada una herramientas Java, pero la idea es la misma, sólo tendrá que imaginar que está agregando el JLabel en lugar de botones y que esta es una JFrame o JWindow en lugar de un formulario .NET.

El código debe ser algo como esto, si suponemos un área de 800 x 800 píxeles a la disposición cosas en

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

Gracias, pero quiero una solución con Layout, ya que no se sugiere utilizar el posicionamiento absoluto. –

+0

Oh, bien, ¿no podrías crear tu propio administrador de diseño que resuelva los puntos según el ancho real del panel? Sería un factor de tipo cosa – sacha

4

me gusta @ de la idea de @ sacha Baqueta y:

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

y me encanta la mayoría de tu código +1, genial solo tu código es modificable en todas las direcciones, muchas gracias – mKorbel

+0

Me gusta el hecho de que cambia el tamaño sin problemas. +1 –

18

Usted don No es necesario un administrador de diseño que lo soporte específicamente. Puede calcular las posiciones x, y con una trigonometría bastante simple, luego use un diseño regular como 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

Guau, eso es interesante :-) –

2
  1. MigLayout puede hacer posicionamiento absoluto con "POS x y [x2] [Y2]" como una restricción componente. MigLayout realmente es el administrador de diseño para gobernarlos a todos. Echa un vistazo a la demostración webstart en su página principal, muestra bien el posicionamiento absoluto. Todavía tendría que calcular las posiciones de los componentes, como con la idea del administrador de diseño personalizado.

  2. También podría simplemente turn off the layout.

  3. Y si quieres ser realmente creativo, puedes mirar JHotDraw.

Cuestiones relacionadas