Подтвердить что ты не робот

Какой макет может сделать это?

Я пытаюсь разместить некоторые JLabels в своем приложении, как показано в этом примере:

enter image description here

У меня всегда есть эта JLabel в середине, а число других JLabels - переменная, она может идти от 1 до 30. Я попытался создать сетку, выбрав большое количество столбцов/строк и установив несколько пустых JLabels в белом но я не могу получить хороший результат и не могу найти, как это сделать с помощью MigLayout, у кого-то есть хороший макетирование души или любое другое решение.

PS: я не хочу показывать круг, чтобы показать, что JLabels расположены по кругу.

4b9b3361

Ответ 1

Вам не нужен менеджер компоновки, который специально поддерживает это. Вы можете рассчитать позиции 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 mathsscreenshot

Ответ 3

Лаборатории JH имеют ClockLayout:

Это очень глупый макет, созданный для специальной цели. Он просто выставляет свои компоненты по кругу, по часовой стрелке сверху.

Ответ 4

Мне нравится @Baqueta и идея @sacha:

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);
  }
}

Ответ 5

Я использую формы Windows, поскольку у меня нет установленных инструментов Java, но идея такая же, вам просто нужно представить, что вы добавляете JLabel вместо кнопок и что это JFrame или JWindow вместо .NET-формы.

Код должен быть примерно таким, если мы предположим, что область 800 x 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);
    }
}

Ответ 6

  • MigLayout может выполнять абсолютное позиционирование с помощью "pos x y [x2] [y2]" в качестве ограничения компонента. MigLayout действительно является менеджером компоновки, чтобы управлять ими всеми. Просмотрите демоверсию webstart на своей первой странице, она отлично показывает позиционирование. Вам все равно придется вычислять позиции компонентов, например, с помощью идеи менеджера компоновки.

  • Также вы можете просто отключить макет.

  • И если вы хотите стать действительно творческим, вы можете посмотреть JHotDraw.