有没有一种方法可以用您自己的按钮图形而不只是按钮内的图像来创建JButton?
如果不是,是否还有另一种方法可以在Java中创建自定义JButton?
当我第一次学习Java时,我们不得不制造Yahtzee,我认为创建自定义的Swing组件和容器会很酷,而不仅仅是在JPanel上绘制所有内容。当然,扩展Swing组件的好处是能够添加对键盘快捷键和其他辅助功能的支持,而仅仅通过paint()方法打印出漂亮的图片就无法做到。但是,它可能不是最佳方法,但是对您来说可能是一个很好的起点。
编辑8/6-如果从图像中看不到,则每个"模具"都是可以单击的按钮。这会将其移至下面的DiceContainer。查看源代码,您可以看到每个Die按钮都是基于其值动态绘制的。


基本步骤如下:
创建一个扩展JComponent的类
在构造函数中调用父构造函数super()
确保您实现了MouseListener类
把它放在构造函数中:
1 2
| enableInputMethods(true);
addMouseListener(this); |
覆盖以下方法:
1 2 3
| public Dimension getPreferredSize()
public Dimension getMinimumSize()
public Dimension getMaximumSize() |
覆盖此方法:
1
| public void paintComponent(Graphics g) |
假设getMinimumSize()和getMaximumSize()返回相同的值,则绘制按钮时必须使用的空间量由getPreferredSize()定义。我没有对此进行过多的尝试,但是,根据您用于GUI的布局,按钮的外观可能会完全不同。
最后是源代码。万一我错过了什么。
是的,这是可能的。使用Swing的主要优点之一是可以轻松创建和操作抽象控件。
这是扩展现有JButton类以在文本右侧绘制一个圆的一种快速而肮脏的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| 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方法,以便动态支持对内容的更改。在测量字体指标和图像尺寸时需要格外小心。
对于创建您可以依赖的控件,上面的代码不是正确的方法。尺寸和颜色在Swing中是动态的,并且取决于所使用的外观。甚至默认的Metal外观在JRE版本中也发生了变化。最好实现AbstractButton并遵守Swing API提出的准则。一个好的起点是查看javax.swing.LookAndFeel和javax.swing.UIManager类。
http://docs.oracle.com/javase/8/docs/api/javax/swing/LookAndFeel.html
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
了解LookAndFeel的结构对于编写控件非常有用:
创建自定义外观
您可以随时尝试使用Synth的外观。您提供一个充当某种样式表的xml文件,以及您要使用的任何图像。代码可能看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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);
} |
从那里开始,像往常一样添加JButton。唯一的变化是您使用setName(string)方法来标识按钮应映射到xml文件中的内容。
xml文件可能如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <synth>
<style id="button">
<font name="DIALOG" size="12" style="BOLD"/>
<state value="MOUSE_OVER">
<imagePainter method="buttonBackground" path="dirt.webp" sourceInsets="2 2 2 2"/>
<insets top="2" botton="2" right="2" left="2"/>
</state>
<state value="ENABLED">
<imagePainter method="buttonBackground" path="dirt.webp" 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"的按钮)。
还有几个有用的链接:
http://javadesktop.org/articles/synth/
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/synth.html
我可能在错误的方向行驶了100万英里(但我还很年轻:P)。 但是您不能将图形添加到面板中,然后将鼠标侦听器添加到图形对象中,以便在用户访问图形时执行您的操作。
自从我早期的CS类以来,我还没有进行过SWING开发,但是如果它不是内置的,则可以继承javax.swing.AbstractButton并创建自己的。将某些东西与其现有框架连接起来应该非常简单。