Вопрос по layout, java, swing, miglayout, grid-layout – Какой макет может сделать это?

21

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

enter image description here

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

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

Хороший вопрос и очень описательное (& маленькое в байтах) изображение. +1 Andrew Thompson
Спасибо, я думаю, что после 30 дней подряд я начал немного адаптироваться :) imanis_tn

Ваш Ответ

6   ответов
14

что ваши требования настолько специализированы, что нет LayoutManager, который может делать то, что вам нужно.Попробуйте создать свой собственный!

Before you start creating a custom layout manager, make sure that no existing layout manager meets your requirements. - & GT; поэтому, комбинируя ваш ответ и @Peter's, я могу получить его, +1 imanis_tn
Я думаю, что ты прибил этот. +1
Создание собственного менеджера макетов может показаться сложным, но на самом деле все довольно просто!
... и приходит @Peter, чтобы доказать, что я не прав! :)
3

так как у меня нет установленных инструментов 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);
    }
}
Спасибо, но мне нужно решение с Layout, поскольку не предлагается использовать абсолютное позиционирование. imanis_tn
Да ладно, не могли бы вы создать свой собственный менеджер компоновки, который обрабатывает точки на основе фактической ширины панели? Будет просто вещь типа фактор
4

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);
  }
}
и я люблю большинство вашего кода +1, отлично, только ваш код можно изменять по всем направлениям, большое спасибо
Мне нравится тот факт, что он плавно меняет размеры. +1
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

Вау, это интересно :-)
2

pos x y [x2] [y2]" as a component constraint. MigLayout really is the layout manager to rule them all. Check out the webstart demo on their front page, it shows off absolute positioning well. You'd still have to calculate the positions of the components like with the custom layout manager idea.

Also you could just turn off the layout.

And if you want to get really creative, you could look at JHotDraw.

13

ClockLayout:

This is a very silly layout created for a special purpose. It simply lays out its components in a circle, clockwise from the top.

Отличная компоновка, но здесь нет центрального элемента, поэтому мне нужно реализовать настройку часов. +1 imanis_tn

Похожие вопросы