我正在尝试做一些我认为相当容易但却无法找到直接答案的事情。基本上我想将JPanel的默认形状更改为圆形(或除矩形以外的任何其他形状)。
答案 0 :(得分:2)
您需要提供自己的自定义绘画程序。
您将面临的另一个问题是让布局管理器使用它,但是您可以提供自己的插图以在面板中提供可以安全使用的区域
您还需要使组件透明,以允许组件圆圈位置之外的区域透明。
结帐
你可能还需要操纵Graphics
上下文的剪切矩形。这是棘手而危险的,如果你能避免它,我会的。
更新了示例
public class CirclePaneTest {
public static void main(String[] args) {
new CirclePaneTest();
}
public CirclePaneTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.RED);
setLayout(new GridBagLayout());
CirclePane circlePane = new CirclePane();
JLabel label = new JLabel("This is a test");
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
// This is a test to show the usable bounds
label.setBorder(new LineBorder(Color.RED));
circlePane.setLayout(new BorderLayout());
circlePane.add(label);
add(circlePane);
}
}
public class CirclePane extends JPanel {
public CirclePane() {
setOpaque(false);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected int getRadius() {
// Determines the radius based on the smaller of the width
// or height, so we stay symmetrical
return Math.min(getWidth(), getHeight());
}
@Override
public Insets getInsets() {
int radius = getRadius();
int xOffset = (getWidth() - radius) / 2;
int yOffset = (getHeight() - radius) / 2;
// These are magic numbers, you might like to calculate
// your own values based on your needs
Insets insets = new Insets(
radius / 6,
radius / 6,
radius / 6,
radius / 6);
return insets;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int radius = getRadius();
int xOffset = (getWidth() - radius) / 2;
int yOffset = (getHeight() - radius) / 2;
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getBackground());
g2d.fillOval(xOffset, yOffset, radius, radius);
g2d.setColor(Color.GRAY);
g2d.drawOval(xOffset, yOffset, radius, radius);
// This is test code to test the insets/usable area bounds...
// Insets insets = getInsets();
// g2d.drawRect(xOffset + insets.left,
// yOffset + insets.top,
// (xOffset + radius) - (insets.right + insets.left),
// (yOffset + radius) - (insets.bottom + insets.top));
g2d.dispose();
}
}
}
答案 1 :(得分:0)
阅读这篇文章:http://docs.oracle.com/javase/tutorial/uiswing/misc/trans_shaped_windows.html
详细说明了如何创建椭圆形透明窗口。
答案 2 :(得分:0)
此链接可以帮助您。它有JAVA中Windows形状和效果的示例: http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html
答案 3 :(得分:0)
如果您只希望布局为圆形,则可以使用圆形布局:
class CircleLayout implements LayoutManager
{
public void addLayoutComponent(String name,
Component comp)
{}
public void removeLayoutComponent(Component comp)
{}
public void setSizes(Container parent)
{
if (sizesSet) return;
int n = parent.getComponentCount();
preferredWidth = 0;
preferredHeight = 0;
minWidth = 0;
minHeight = 0;
maxComponentWidth = 0;
maxComponentHeight = 0;
// compute the maximum component widths and heights
// and set the preferred size to the sum of
// the component sizes.
for (int i = 0; i < n; i++)
{
Component c = parent.getComponent(i);
if (c.isVisible())
{
Dimension d = c.getPreferredSize();
maxComponentWidth = Math.max(maxComponentWidth,
d.width);
maxComponentHeight = Math.max(maxComponentHeight,
d.height);
preferredWidth += d.width;
preferredHeight += d.height;
}
}
minWidth = preferredWidth / 2;
minHeight = preferredHeight / 2;
sizesSet = true;
}
public Dimension preferredLayoutSize(Container parent)
{
setSizes(parent);
Insets insets = parent.getInsets();
int width = preferredWidth + insets.left
+ insets.right;
int height = preferredHeight + insets.top
+ insets.bottom;
return new Dimension(width, height);
}
public Dimension minimumLayoutSize(Container parent)
{
setSizes(parent);
Insets insets = parent.getInsets();
int width = minWidth + insets.left + insets.right;
int height = minHeight + insets.top + insets.bottom;
return new Dimension(width, height);
}
public void layoutContainer(Container parent)
{
setSizes(parent);
// compute center of the circle
Insets insets = parent.getInsets();
int containerWidth = parent.getSize().width
- insets.left - insets.right;
int containerHeight = parent.getSize().height
- insets.top - insets.bottom;
int xcenter = insets.left + containerWidth / 2;
int ycenter = insets.top + containerHeight / 2;
// compute radius of the circle
int xradius = (containerWidth - maxComponentWidth) / 2;
int yradius = (containerHeight - maxComponentHeight) / 2;
int radius = Math.min(xradius, yradius);
// lay out components along the circle
int n = parent.getComponentCount();
for (int i = 0; i < n; i++)
{
Component c = parent.getComponent(i);
if (c.isVisible())
{
double angle = 2 * Math.PI * i / n;
// center point of component
int x = xcenter + (int)(Math.cos(angle) * radius);
int y = ycenter + (int)(Math.sin(angle) * radius);
// move component so that its center is (x, y)
// and its size is its preferred size
Dimension d = c.getPreferredSize();
c.setBounds(x - d.width / 2, y - d.height / 2,
d.width, d.height);
}
}
}
private int minWidth = 0;
private int minHeight = 0;
private int preferredWidth = 0;
private int preferredHeight = 0;
private boolean sizesSet = false;
private int maxComponentWidth = 0;
private int maxComponentHeight = 0;
}
你可以像这样使用它:
class CircleLayoutFrame extends JFrame
{
public CircleLayoutFrame()
{
setTitle("CircleLayoutTest");
Container contentPane = getContentPane();
contentPane.setLayout(new CircleLayout());
contentPane.add(new JButton("Yellow"));
contentPane.add(new JButton("Blue"));
contentPane.add(new JButton("Red"));
contentPane.add(new JButton("Green"));
contentPane.add(new JButton("Orange"));
contentPane.add(new JButton("Fuchsia"));
contentPane.add(new JButton("Indigo"));
}
}