Java更改JPanel的形状

问题描述 投票:0回答:3

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

java swing jpanel shape java-2d
3个回答
2
投票

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

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

您还希望使组件透明,以使组件的圆形位置之外的区域透明。

退房

可能还需要操纵JCompnent#getInsets上下文的剪切矩形。这是棘手和危险的,如果可以避免的话,我会的。

已更新示例

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9EQ0hucy5wbmcifQ==” alt =“在此处输入图像描述”>

Graphics

0
投票

如果只希望布局为圆形,则可以使用圆形布局:

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();

        }
    }
}

您可以这样使用它:

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

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

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

http://docs.oracle.com/javase/tutorial/uiswing/misc/trans_shaped_windows.html
© www.soinside.com 2019 - 2024. All rights reserved.