“同心圆”布局管理器
2008-11-20 21:46
246 查看
第一次尝试自己写布局管理器,实用价值不大,核心代码和测试代码如下:
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
;
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) {
//e.printStackTrace();
}
}
public static void main(String[] args) {
new CCTestFrame().setVisible(true);
}
}
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
;
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) {
//e.printStackTrace();
}
}
public static void main(String[] args) {
new CCTestFrame().setVisible(true);
}
}
相关文章推荐
- 一步一步学android之布局管理器——LinearLayout
- Android布局管理器
- 布局管理器之CardLayout(卡片布局管理器)
- UI之五种布局管理器
- 三十、Java图形化界面设计——布局管理器之BorderLayout(边界布局)
- 布局管理器之CardLayout(卡片布局管理器)
- Android的6种布局管理器总结
- JavaSE学习55:GUI编程之布局管理器
- AWT中的几种布局管理器
- Swing无序网格布局管理器(GridBagLayout)应用详解
- QT学习笔记1---布局管理器
- Java图形化界面设计——布局管理器之FlowLayout(流式布局)
- Swing的布局管理器
- Android 布局管理器
- 04 Java图形化界面设计——布局管理器之BorderLayout(边界布局)
- java图形用户界面边界布局管理器
- QT学习笔记----布局管理器的使用
- 12.13 布局管理器
- Android - 布局管理器LayoutInflater及LayoutParams动态设置宽高属性
- Android 布局管理器 之 LinearLayout