【问题标题】:Button with round edges圆边纽扣
【发布时间】:2012-12-01 17:18:13
【问题描述】:

我正在尝试获得一个带有圆边的按钮。我的按钮的背景颜色为黄色。我的按钮无法获得圆边。这是我正在尝试的代码

 class RoundedBorder implements Border {
        int radius;
        RoundedBorder(int radius) {
            this.radius = radius;
        }
        public Insets getBorderInsets(Component c) {
            return new Insets(this.radius+1, this.radius+1, this.radius+2, this.radius);
        }
        public boolean isBorderOpaque() {
            return true;
        }
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            g.drawRoundRect(x,y,width-1,height-1,radius,radius);
        }
    }

jButton1.setText(aContinue);
        jButton1.setBackground(new java.awt.Color(255, 255, 0));
        jButton1.setBorder(new RoundedBorder(20));

我无法使用这段代码获得圆边。这是我的按钮的外观。

我想要没有溢出背景颜色的圆形边缘。

【问题讨论】:

  • 不要让史蒂夫乔布斯看到这个问题......他发明了圆边!

标签: java swing user-interface button jbutton


【解决方案1】:

选项1- 使用图片

Option2- 使用以下代码(摘自Make a button round

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public class RoundButton extends JButton {
  public RoundButton(String label) {
    super(label);

// These statements enlarge the button so that it 
// becomes a circle rather than an oval.
    Dimension size = getPreferredSize();
    size.width = size.height = Math.max(size.width, 
      size.height);
    setPreferredSize(size);

// This call causes the JButton not to paint 
   // the background.
// This allows us to paint a round background.
    setContentAreaFilled(false);
  }

// Paint the round background and label.
  protected void paintComponent(Graphics g) {
    if (getModel().isArmed()) {
// You might want to make the highlight color 
   // a property of the RoundButton class.
      g.setColor(Color.lightGray);
    } else {
      g.setColor(getBackground());
    }
    g.fillOval(0, 0, getSize().width-1, 
      getSize().height-1);

// This call will paint the label and the 
   // focus rectangle.
    super.paintComponent(g);
  }

// Paint the border of the button using a simple stroke.
  protected void paintBorder(Graphics g) {
    g.setColor(getForeground());
    g.drawOval(0, 0, getSize().width-1, 
      getSize().height-1);
  }

// Hit detection.
  Shape shape;
  public boolean contains(int x, int y) {
// If the button has changed size, 
   // make a new shape object.
    if (shape == null || 
      !shape.getBounds().equals(getBounds())) {
      shape = new Ellipse2D.Float(0, 0, 
        getWidth(), getHeight());
    }
    return shape.contains(x, y);
  }

// Test routine.
  public static void main(String[] args) {
// Create a button with the label "Jackpot".
    JButton button = new RoundButton("Jackpot");
    button.setBackground(Color.green);

// Create a frame in which to show the button.
    JFrame frame = new JFrame();
    frame.getContentPane().setBackground(Color.yellow);
    frame.getContentPane().add(button);
    frame.getContentPane().setLayout(new FlowLayout());
    frame.setSize(150, 150);
    frame.setVisible(true);
  }
}

Option3- 使用支持圆形按钮的外观http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/NimbusLookandFeel_OBE2012/CustomizingLandF.html

Option4- 使用 JavaFX 并使用 CSS。有免费的 CSS 脚本支持这个

【讨论】:

    【解决方案2】:

    oracle 发现了这个很好的例子,它提供了一个创建 RoundButton 的类。

    这是一个使用编辑的RoundButton 类创建RoundedButton 类的示例:

    import java.awt.AWTEvent;
    import java.awt.AWTEventMulticaster;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseEvent;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    
    
    public class Test {
    
        public Test() {
            initComponents();
        }
    
        private void initComponents() {
            final JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            final JTextField tf = new JTextField("");
    
            RoundedButton rb = new RoundedButton("Go");
            rb.setBackground(Color.yellow);
            rb.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    JOptionPane.showMessageDialog(frame, "You said: " + tf.getText());
                }
            });
    
            frame.add(tf, BorderLayout.NORTH);
            frame.add(rb);
    
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new Test();
                }
            });
        }
    }
    
    class RoundedButton extends Component {
    
        ActionListener actionListener;     // Post action events to listeners
        String label;                      // The Button's text
        protected boolean pressed = false; // true if the button is detented.
    
        /**
         * Constructs a RoundedButton with no label.
         */
        public RoundedButton() {
            this("");
        }
    
        /**
         * Constructs a RoundedButton with the specified label.
         *
         * @param label the label of the button
         */
        public RoundedButton(String label) {
            this.label = label;
            enableEvents(AWTEvent.MOUSE_EVENT_MASK);
        }
    
        /**
         * gets the label
         *
         * @see setLabel
         */
        public String getLabel() {
            return label;
        }
    
        /**
         * sets the label
         *
         * @see getLabel
         */
        public void setLabel(String label) {
            this.label = label;
            invalidate();
            repaint();
        }
    
        /**
         * paints the RoundedButton
         */
        @Override
        public void paint(Graphics g) {
    
            // paint the interior of the button
            if (pressed) {
                g.setColor(getBackground().darker().darker());
            } else {
                g.setColor(getBackground());
            }
            g.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
    
            // draw the perimeter of the button
            g.setColor(getBackground().darker().darker().darker());
            g.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
    
            // draw the label centered in the button
            Font f = getFont();
            if (f != null) {
                FontMetrics fm = getFontMetrics(getFont());
                g.setColor(getForeground());
                g.drawString(label, getWidth() / 2 - fm.stringWidth(label) / 2, getHeight() / 2 + fm.getMaxDescent());
            }
        }
    
        /**
         * The preferred size of the button.
         */
        @Override
        public Dimension getPreferredSize() {
            Font f = getFont();
            if (f != null) {
                FontMetrics fm = getFontMetrics(getFont());
                int max = Math.max(fm.stringWidth(label) + 40, fm.getHeight() + 40);
                return new Dimension(max, max);
            } else {
                return new Dimension(100, 100);
            }
        }
    
        /**
         * The minimum size of the button.
         */
        @Override
        public Dimension getMinimumSize() {
            return new Dimension(100, 100);
        }
    
        /**
         * Adds the specified action listener to receive action events from this
         * button.
         *
         * @param listener the action listener
         */
        public void addActionListener(ActionListener listener) {
            actionListener = AWTEventMulticaster.add(actionListener, listener);
            enableEvents(AWTEvent.MOUSE_EVENT_MASK);
        }
    
        /**
         * Removes the specified action listener so it no longer receives action
         * events from this button.
         *
         * @param listener the action listener
         */
        public void removeActionListener(ActionListener listener) {
            actionListener = AWTEventMulticaster.remove(actionListener, listener);
        }
    
        /**
         * Determine if click was inside round button.
         */
        @Override
        public boolean contains(int x, int y) {
            int mx = getSize().width / 2;
            int my = getSize().height / 2;
            return (((mx - x) * (mx - x) + (my - y) * (my - y)) <= mx * mx);
        }
    
        /**
         * Paints the button and distribute an action event to all listeners.
         */
        @Override
        public void processMouseEvent(MouseEvent e) {
            Graphics g;
            switch (e.getID()) {
                case MouseEvent.MOUSE_PRESSED:
                    // render myself inverted....
                    pressed = true;
    
                    // Repaint might flicker a bit. To avoid this, you can use
                    // double buffering (see the Gauge example).
                    repaint();
                    break;
                case MouseEvent.MOUSE_RELEASED:
                    if (actionListener != null) {
                        actionListener.actionPerformed(new ActionEvent(
                                this, ActionEvent.ACTION_PERFORMED, label));
                    }
                    // render myself normal again
                    if (pressed == true) {
                        pressed = false;
    
                        // Repaint might flicker a bit. To avoid this, you can use
                        // double buffering (see the Gauge example).
                        repaint();
                    }
                    break;
                case MouseEvent.MOUSE_ENTERED:
    
                    break;
                case MouseEvent.MOUSE_EXITED:
                    if (pressed == true) {
                        // Cancel! Don't send action event.
                        pressed = false;
    
                        // Repaint might flicker a bit. To avoid this, you can use
                        // double buffering (see the Gauge example).
                        repaint();
    
                        // Note: for a more complete button implementation,
                        // you wouldn't want to cancel at this point, but
                        // rather detect when the mouse re-entered, and
                        // re-highlight the button. There are a few state
                        // issues that that you need to handle, which we leave
                        // this an an excercise for the reader (I always
                        // wanted to say that!)
                    }
                    break;
            }
            super.processMouseEvent(e);
        }
    }
    

    【讨论】:

    • 真棒帮助..谢谢..可以为 jtextfield 调整此代码吗??
    • @Ragssure 可以,但它实际上将是一个全新的类,它扩展了 Component 类而不是调整原始类,因为 JTextField 与 JButton 非常不同
    • @Rags 我的错误如果你扩展 JTextComponent 可能会更容易
    • 截至 2018 年 7 月,圆形按钮周围出现黑角。仅在 Windows 上(Linux 上的相同按钮可以正常工作)
    • 到 oracle 的链接已损坏
    【解决方案3】:

    实现此目的的另一种简洁方法是定义一个自定义ButtonUI,该ButtonUI 将绘制一个圆角按钮。

    【讨论】:

      猜你喜欢
      • 2023-03-14
      • 2019-10-08
      • 2020-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多