繁体   English   中英

Java 更改 JPanel 的形状

[英]Java Change shape of JPanel

我正在尝试做一些我认为相当容易但找不到直接答案的事情。 基本上我想将 JPanel 的默认形状更改为圆形(或矩形以外的任何其他形状)。

您将需要提供自己的自定义绘画程序。

您将遇到的另一个问题是让布局管理器使用它,但您可以提供自己的插图以在面板内提供一个可以安全使用的区域

您还需要使组件透明,以允许组件圆形位置之外的区域是透明的。

查看

可能还需要操作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();

        }
    }
}

阅读这篇文章: http : //docs.oracle.com/javase/tutorial/uiswing/misc/trans_shape_windows.html

它详细展示了如何创建椭圆形透明窗口。 从代码中[请参阅如何实现成形窗口部分]:

半透明:

    TranslucentWindowDemo tw = new TranslucentWindowDemo();

    // Set the window to 55% opaque (45% translucent).
    tw.setOpacity(0.55f);

椭圆形:

Oval:addComponentListener(new ComponentAdapter() {
        // Give the window an elliptical shape.
        // If the window is resized, the shape is recalculated here.
        @Override
        public void componentResized(ComponentEvent e) {
            setShape(new Ellipse2D.Double(0,0,getWidth(),getHeight()));
        }
    });

    setUndecorated(true);
    setSize(300,200);

演示:

public ShapedWindowDemo() {
    super("ShapedWindow");
    setLayout(new GridBagLayout());

    // It is best practice to set the window's shape in
    // the componentResized method.  Then, if the window
    // changes size, the shape will be correctly recalculated.
    addComponentListener(new ComponentAdapter() {
        // Give the window an elliptical shape.
        // If the window is resized, the shape is recalculated here.
        @Override
        public void componentResized(ComponentEvent e) {
            setShape(new Ellipse2D.Double(0,0,getWidth(),getHeight()));
        }
    });

    setUndecorated(true);
    setSize(300,200);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    add(new JButton("I am a Button"));
}

这个链接可以帮到你。 它有JAVA中Windows形状和效果的示例: http//today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html

如果您只想布局为圆形,则可以使用圆形布局:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM