2012-04-20 12 views
21

Sto cercando di layout di alcune JLabels nella mia applicazione, come mostrato in questo esempio:Quale layout può fare questo?

enter image description here

ho sempre questo JLabel al centro e il numero degli altri JLabels è variabile può andare da 1 a 30. Ho provato il layout di Grid scegliendo un buon numero di colonne/righe e impostando alcuni JLabel vuoti nello spazio bianco ma non riesco a ottenere un buon risultato, e non riesco a trovare come farlo con MigLayout, fatto qualsiasi uno ha un buon souling layout o qualsiasi altra soluzione.

PS: Non voglio mostrare il cerchio è solo per mostrare che i JLabels sono disposti in un cerchio.

+0

Buona domanda e immagine molto descrittiva (e di dimensioni ridotte in byte). +1 –

+1

Grazie, penso che dopo 30 giorni consecutivi qui, ho iniziato un po 'ad adattarmi :) –

risposta

14

Ho il sospetto che le vostre esigenze siano così specializzate che non esiste un LayoutManager in grado di fare ciò che vi serve. Try creating your own!

+0

Penso che tu abbia inchiodato questo. +1 –

+1

... e insieme arriva @Peter per dimostrarmi che ho torto!:) – vaughandroid

+0

** Prima di iniziare a creare un gestore di layout personalizzato, assicurati che nessun gestore di layout esistente soddisfi i tuoi requisiti. ** -> quindi combinando la tua risposta e quella di @Peter posso ottenerla, +1 –

13

JH Labs ha un ClockLayout:

Questo è un layout molto stupido creato per uno scopo particolare. Disegna semplicemente i suoi componenti in un cerchio, in senso orario dall'alto.

+0

Grande layout, ma qui non c'è un elemento centrale, quindi devo implementare il mio orologio personalizzato. +1 –

3

Sto usando Windows Form, come non ho uno strumenti Java installato, ma l'idea è la stessa, dovrete solo immaginare che si sta aggiungendo il JLabel al posto dei bottoni e che questo è un JFrame o JWindow invece di un modulo .NET.

Il codice dovrebbe essere qualcosa di simile, se si assume una superficie di 800 x 800 pixel per il layout roba

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

Grazie, ma voglio una soluzione con Layout poiché non è consigliabile utilizzare Absolute Positioning. –

+0

Oh ok, quindi non è possibile creare il proprio gestore di layout che elabora i punti in base alla larghezza effettiva del pannello? Sarebbe solo una cosa tipo di fattore – sacha

4

Mi piace @ idea di @ sacha di Baqueta e:

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

e amo la maggior parte del tuo codice +1, ottimo solo il tuo codice è resettabile in tutte le direzioni, grazie mille – mKorbel

+0

Mi piace il fatto che ridimensiona senza problemi. +1 –

18

È don 'ho bisogno di un gestore di layout che supporta specificamente questo. È possibile calcolare le posizioni x, y con una semplice trigonometria, quindi utilizzare un layout regolare come 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

Wow, è interessante :-) –

2
  1. MigLayout può fare posizionamento assoluto con "POS x y [x2] [y2]" come un vincolo componente. MigLayout è davvero il gestore del layout per dominarli tutti. Guarda la demo webstart sulla loro prima pagina, mostra bene il posizionamento assoluto. Dovresti comunque calcolare le posizioni dei componenti come con l'idea del gestore di layout personalizzato.

  2. Inoltre è possibile solo turn off the layout.

  3. E se vuoi essere davvero creativo, puoi guardare JHotDraw.

Problemi correlati