0

私はかなり簡単だと思うことをしようとしていますが、簡単な答えを見つけることができません。基本的に、JPanel のデフォルトの形状を円形 (または長方形以外の形状) に変更したいと考えています。

4

3 に答える 3

2

独自のカスタム ペインティング ルーチンを用意する必要があります。

もう 1 つの問題は、レイアウト マネージャーを使用することですが、安全に使用できるパネル内の領域を提供するために独自のインセットを提供できます。

コンポーネントを透明にして、コンポーネントの円の位置の外側の領域を透明にすることもできます。

チェックアウト

コンテキストのクリッピング四角形も操作する必要ある場合があります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();

        }
    }
}
于 2013-02-03T19:44:54.333 に答える
0

この記事を読む: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"));
}
于 2013-02-03T18:32:59.910 に答える
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"));
   }
}
于 2013-02-03T21:35:02.747 に答える