在Java中创建自定义JButton

在Java中创建自定义JButton,java,swing,jbutton,Java,Swing,Jbutton,有没有办法用自己的按钮图形而不仅仅是按钮内的图像创建JButton 如果没有,是否有其他方法可以在java中创建自定义的JButton?我从早期的CS类开始就没有做过SWING开发,但是如果它不是内置的,您可以继承javax.SWING.AbstractButton并创建自己的。与现有框架连接起来应该非常简单。您可以尝试Synth外观。您提供了一个xml文件,该文件充当一种样式表,以及您想要使用的任何图像。代码可能如下所示: try { SynthLookAndFeel synth =

有没有办法用自己的按钮图形而不仅仅是按钮内的图像创建
JButton


如果没有,是否有其他方法可以在java中创建自定义的
JButton

我从早期的CS类开始就没有做过SWING开发,但是如果它不是内置的,您可以继承
javax.SWING.AbstractButton
并创建自己的。与现有框架连接起来应该非常简单。

您可以尝试Synth外观。您提供了一个xml文件,该文件充当一种样式表,以及您想要使用的任何图像。代码可能如下所示:

try {
    SynthLookAndFeel synth = new SynthLookAndFeel();
    Class aClass = MainFrame.class;
    InputStream stream = aClass.getResourceAsStream("\\default.xml");

    if (stream == null) {
        System.err.println("Missing configuration file");
        System.exit(-1);                
    }

    synth.load(stream, aClass);

    UIManager.setLookAndFeel(synth);
} catch (ParseException pe) {
    System.err.println("Bad configuration file");
    pe.printStackTrace();
    System.exit(-2);
} catch (UnsupportedLookAndFeelException ulfe) {
    System.err.println("Old JRE in use. Get a new one");
    System.exit(-3);
}
<synth>
    <style id="button">
        <font name="DIALOG" size="12" style="BOLD"/>
        <state value="MOUSE_OVER">
            <imagePainter method="buttonBackground" path="dirt.png" sourceInsets="2 2 2 2"/>
            <insets top="2" botton="2" right="2" left="2"/>
        </state>
        <state value="ENABLED">
            <imagePainter method="buttonBackground" path="dirt.png" sourceInsets="2 2 2 2"/>
            <insets top="2" botton="2" right="2" left="2"/>
        </state>
    </style>
    <bind style="button" type="name" key="dirt"/>
</synth>
从这里开始,像平常一样添加JButton。唯一的变化是使用setName(string)方法来标识按钮应该映射到xml文件中的什么

xml文件可能如下所示:

try {
    SynthLookAndFeel synth = new SynthLookAndFeel();
    Class aClass = MainFrame.class;
    InputStream stream = aClass.getResourceAsStream("\\default.xml");

    if (stream == null) {
        System.err.println("Missing configuration file");
        System.exit(-1);                
    }

    synth.load(stream, aClass);

    UIManager.setLookAndFeel(synth);
} catch (ParseException pe) {
    System.err.println("Bad configuration file");
    pe.printStackTrace();
    System.exit(-2);
} catch (UnsupportedLookAndFeelException ulfe) {
    System.err.println("Old JRE in use. Get a new one");
    System.exit(-3);
}
<synth>
    <style id="button">
        <font name="DIALOG" size="12" style="BOLD"/>
        <state value="MOUSE_OVER">
            <imagePainter method="buttonBackground" path="dirt.png" sourceInsets="2 2 2 2"/>
            <insets top="2" botton="2" right="2" left="2"/>
        </state>
        <state value="ENABLED">
            <imagePainter method="buttonBackground" path="dirt.png" sourceInsets="2 2 2 2"/>
            <insets top="2" botton="2" right="2" left="2"/>
        </state>
    </style>
    <bind style="button" type="name" key="dirt"/>
</synth>

其中的bind元素指定要映射到的对象(在本例中,它将该样式应用于name属性设置为“dirt”的任何按钮)

还有几个有用的链接:


是的,这是可能的。使用Swing的主要优点之一是易于创建和操作抽象控件

下面是一种扩展现有JButton类以在文本右侧绘制圆的快速而肮脏的方法

package test;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;

import javax.swing.JButton;
import javax.swing.JFrame;

public class MyButton extends JButton {

    private static final long serialVersionUID = 1L;

    private Color circleColor = Color.BLACK;

    public MyButton(String label) {
        super(label);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Dimension originalSize = super.getPreferredSize();
        int gap = (int) (originalSize.height * 0.2);
        int x = originalSize.width + gap;
        int y = gap;
        int diameter = originalSize.height - (gap * 2);

        g.setColor(circleColor);
        g.fillOval(x, y, diameter, diameter);
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension size = super.getPreferredSize();
        size.width += size.height;
        return size;
    }

    /*Test the button*/
    public static void main(String[] args) {
        MyButton button = new MyButton("Hello, World!");

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 400);

        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new FlowLayout());
        contentPane.add(button);

        frame.setVisible(true);
    }

}
请注意,通过覆盖paintComponent可以更改按钮的内容,但边框是通过paintBorder方法绘制的。还需要管理getPreferredSize方法,以便动态支持对内容的更改。在测量字体度量和图像尺寸时需要小心

对于创建可以依赖的控件,上述代码不是正确的方法。尺寸和颜色在摇摆中是动态的,取决于所使用的外观和感觉。甚至默认的金属外观在JRE版本中也发生了变化。最好实现AbstractButton,并遵守Swing API规定的准则。一个好的起点是查看javax.swing.LookAndFeeljavax.swing.UIManager

了解LookAndFeel的结构对于编写控件非常有用:

当我第一次学习Java时,我们必须制作Yahtzee,我认为创建自定义Swing组件和容器而不是在一个
JPanel
上绘制所有内容会很酷。当然,扩展
Swing
组件的好处是能够添加对键盘快捷键和其他辅助功能的支持,而这些功能仅仅通过
paint()
方法无法打印漂亮的图片。然而,这可能不是最好的方法,但对你来说,这可能是一个很好的起点

编辑8/6-如果从图像中看不清楚,每个模具都是一个按钮,您可以单击。这将把它移动到下面的
容器中。查看源代码,您可以看到每个模具按钮都是基于其值动态绘制的



以下是基本步骤:

  • 创建一个扩展
    JComponent
  • 在构造函数中调用父构造函数
    super()
  • 确保类实现了
    MouseListener
  • 将其放入构造函数中:

    enableInputMethods(true);   
    addMouseListener(this);
    
  • 覆盖这些方法:

    public Dimension getPreferredSize()  
    public Dimension getMinimumSize()  
    public Dimension getMaximumSize()
    
  • 覆盖此方法:

    public void paintComponent(Graphics g)
    
  • 绘制按钮时必须使用的空间量由
    getPreferredSize()
    定义,假设
    getMinimumSize()
    getMaximumSize()
    返回相同的值。我并没有对此做过太多的尝试,但是,根据GUI使用的布局,您的按钮看起来可能会完全不同


    最后一个问题是。以防我遗漏了什么

    我可能走错方向了一百万英里(但我还年轻:p)。但是你不能先将图形添加到面板,然后再将鼠标侦听器添加到图形对象,这样当用户在图形上执行操作时,你的操作就可以了。

    这会起作用,但如果可能的话,我更喜欢使用标准的按钮,而不是创建我的按钮类型。您好,首先感谢您的代码!我建议在代码中添加一个“setActionComme(String命令)”。这是筛选Swing中事件的方法之一。(但你可以争辩说,有1001件东西可以添加,以使事情稍微好一点:P)要创建一个可以冲压的模具,你实际上可以使用一个普通的旧JButton(而不是子类化或创建自定义JComponent),方法是利用JButton中的setIcon/setPressedIcon以及其他图标功能