第一次尝试自己写布局管理器,实用价值不大,核心代码和测试代码如下:
ConcentricCirclesPanel.java
- import java.awt.Component;
- import java.awt.Container;
- import java.awt.Dimension;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.Insets;
- import java.awt.LayoutManager;
- import java.awt.LayoutManager2;
- import java.awt.RenderingHints;
- import javax.swing.JPanel;
- public class ConcentricCirclesPanel extends JPanel {
- private static final long serialVersionUID = 6265955429442551839L;
- protected void paintComponent(Graphics g) {
- super.paintComponent(g);
- LayoutManager layout = getLayout();
- if (!(layout instanceof ConcentricCirclesLayout)) return;
- ConcentricCirclesLayout ccl = (ConcentricCirclesLayout)layout;
- int fcr = ccl.getFirstCircleRadius();
- int ri = ccl.getRadiusIncrement();
- int cn = ccl.getCircleNum();
- Insets insets = getInsets();
- int cx = insets.left + (getWidth() - insets.left - insets.right) / 2;
- int cy = insets.top + (getHeight() - insets.top - insets.bottom) / 2;
- ((Graphics2D) g).setRenderingHint(
- RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON
- );
- for (int r = fcr, ENDR = fcr + ri * (cn - 1); r <= ENDR; r += ri) {
- g.drawOval(cx - r, cy - r, r * 2, r * 2);
- }
- }
- public static class ConcentricCirclesLayout implements LayoutManager2 {
- private int firstCircleRadius;
- private int radiusIncrement;
- private int circleNum;
- private double angleDegrees;
- private Component[] comps;
- public ConcentricCirclesLayout() {
- this(20, 20, 3, 0.0);
- }
- public ConcentricCirclesLayout(int firstCircleRadius, int radiusIncrement, int circleNum, double angleDegrees) {
- super();
- if (firstCircleRadius < 0) throw new IllegalArgumentException("firstCircleRadius < 0");
- if (radiusIncrement < 1) throw new IllegalArgumentException("radiusIncrement < 0");
- if (circleNum < 1) throw new IllegalArgumentException("circleNum < 0");
- this.firstCircleRadius = firstCircleRadius;
- this.radiusIncrement = radiusIncrement;
- this.circleNum = circleNum;
- this.angleDegrees = angleDegrees;
- this.comps = new Component[this.circleNum];
- }
- public int getFirstCircleRadius() {
- return this.firstCircleRadius;
- }
- public void setFirstCircleRadius(int firstCircleRadius) {
- if (firstCircleRadius < 0) throw new IllegalArgumentException("firstCircleRadius < 0");
- this.firstCircleRadius = firstCircleRadius;
- }
- public int getRadiusIncrement() {
- return this.radiusIncrement;
- }
- public void setRadiusIncrement(int radiusIncrement) {
- if (radiusIncrement < 1) throw new IllegalArgumentException("radiusIncrement < 0");
- this.radiusIncrement = radiusIncrement;
- }
- public int getCircleNum() {
- return this.circleNum;
- }
- public double getAngleDegrees() {
- return this.angleDegrees;
- }
- public void setAngleDegrees(double angleDegrees) {
- this.angleDegrees = angleDegrees;
- }
- public void addLayoutComponent(Component comp, Object constraints) {
- synchronized (comp.getTreeLock()) {
- if (constraints == null) constraints = Integer.valueOf(0);
- if (!(constraints instanceof Integer)) {
- throw new IllegalArgumentException("cannot add to layout: constraint must be a Integer (or null)");
- }
- int num = ((Integer)constraints).intValue();
- if (num < 0 || num >= this.circleNum) {
- throw new IndexOutOfBoundsException("component index out of bounds");
- }
- this.comps[num] = comp;
- }
- }
- @Deprecated
- public void addLayoutComponent(String name, Component comp) {
- synchronized (comp.getTreeLock()) {
- if (name == null) name = "0";
- int num = 0;
- try {
- num = Integer.parseInt(name);
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + name);
- }
- addLayoutComponent(comp, Integer.valueOf(num));
- }
- }
- public void removeLayoutComponent(Component comp) {
- synchronized (comp.getTreeLock()) {
- for (int i = this.comps.length - 1; i >= 0; i--) {
- if (comp == this.comps[i]) {
- this.comps[i] = null;
- break;
- }
- }
- }
- }
- public float getLayoutAlignmentX(Container target) {
- return 0.5F;
- }
- public float getLayoutAlignmentY(Container target) {
- return 0.5F;
- }
- public void invalidateLayout(Container target) {
- }
- public Dimension preferredLayoutSize(Container parent) {
- Insets insets = parent.getInsets();
- int diameter = (this.firstCircleRadius + this.radiusIncrement * (this.circleNum - 1)) * 2;
- int width = insets.left + insets.right + diameter;
- int height = insets.top + insets.bottom + diameter;
- return new Dimension(width, height);
- }
- public Dimension minimumLayoutSize(Container parent) {
- return new Dimension(0, 0);
- }
- public Dimension maximumLayoutSize(Container target) {
- return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
- }
- public void layoutContainer(Container parent) {
- synchronized (parent.getTreeLock()) {
- final double a = Math.toRadians(this.angleDegrees);
- Insets insets = parent.getInsets();
- int cx = insets.left + (parent.getWidth() - insets.left - insets.right) / 2;
- int cy = insets.top + (parent.getHeight() - insets.top - insets.bottom) / 2;
- Component[] cs = this.comps;
- for (int i = 0, LEN = cs.length; i < LEN; i++) {
- Component c = null;
- if ((c = cs[i]) == null) continue;
- Dimension d = c.getPreferredSize();
- int radius = this.firstCircleRadius + this.radiusIncrement * i;
- int dx = (int) (cx + radius * Math.cos(a) + 0.5);
- int dy = (int) (cy - radius * Math.sin(a) + 0.5);
- c.setBounds(dx - d.width / 2, dy - d.height / 2, d.width, d.height);
- }
- }
- }
- }
- }
CCTestFrame.java
- import java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.Dimension;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- public class CCTestFrame extends JFrame implements Runnable {
- private static final long serialVersionUID = -1488776778002491586L;
- private final ConcentricCirclesPanel.ConcentricCirclesLayout layout;
- private final ConcentricCirclesPanel ccPanel;
- private final JButton[] buttons;
- public CCTestFrame() {
- super("CCTestFrame");
- setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- setBounds(60, 60, 800, 600);
- final int N = 5;
- this.ccPanel = new ConcentricCirclesPanel();
- this.layout = new ConcentricCirclesPanel.ConcentricCirclesLayout(39, 50, N, 156.0);
- this.buttons = new JButton[N];
- this.ccPanel.setBackground(Color.BLACK);
- this.ccPanel.setForeground(Color.GREEN);
- this.ccPanel.setLayout(this.layout);
- for (int i = 0; i < N; i++) {
- JButton btn = new JButton(Integer.toString(i));
- btn.setPreferredSize(new Dimension(45, 23));
- this.buttons[i] = btn;
- this.ccPanel.add(btn, Integer.valueOf(i));
- }
- getContentPane().add(this.ccPanel, BorderLayout.CENTER);
- Thread thread = new Thread(this);
- thread.setDaemon(true);
- thread.start();
- }
- public void run() {
- Color[] cs = new Color[120];
- for (int i = cs.length - 1; i >= 0; i--) {
- cs[i] = new Color(Color.HSBtoRGB(i / 120.0F, 0.86F, 1.0F));
- }
- int c = 0;
- double a = 360.0;
- try {
- while (true) {
- for (int i = this.buttons.length - 1; i >= 0; i--) {
- this.buttons[i].setBackground(cs[c]);
- }
- c++;
- c %= 120;
- this.layout.setAngleDegrees(a);
- this.ccPanel.doLayout();
- a -= 1.6;
- a %= 360.0;
- Thread.sleep(30L);
- }
- } catch (InterruptedException e) {
-
- }
- }
- public static void main(String[] args) {
- new CCTestFrame().setVisible(true);
- }
- }
|
|