有没有办法用您自己的按钮图形创建JButton
,而不仅仅是按钮内的图像?
如果没有,是否有另一种在java中创建自定义JButton
的方法?
答案 0 :(得分:87)
当我第一次学习Java时,我们不得不制作Yahtzee,我认为创建自定义Swing组件和容器会很酷,而不是只在一个JPanel
上绘制所有内容。当然,扩展Swing
组件的好处是能够添加对键盘快捷键和其他辅助功能的支持,而这些功能只有通过paint()
方法打印漂亮的图片才能实现。然而,这可能不是最好的方式,但它可能是一个很好的起点。
编辑8/6 - 如果图像中不明显,则每个Die都是一个可以单击的按钮。这会将其移至下面的DiceContainer
。查看源代码,您可以看到每个Die按钮都是根据其值动态绘制的。
以下是基本步骤:
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的布局,您的按钮可能看起来完全不同。
最后,source code。如果我错过了什么。
答案 1 :(得分:32)
是的,这是可能的。使用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 方法,以便动态支持对内容的更改。在测量字体指标和图像尺寸时需要小心。
为了创建一个可以依赖的控件,上面的代码不是正确的方法。 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的解剖结构对于编写控件非常有用: Creating a Custom Look and Feel
答案 2 :(得分:12)
你可以随时尝试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);
}
从那里开始,像往常一样添加你的JButton。唯一的变化是您使用setName(string)方法来标识按钮应该在xml文件中映射到的内容。
xml文件可能如下所示:
<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”的任何按钮)。
以及一些有用的链接:
http://javadesktop.org/articles/synth/
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/synth.html
答案 3 :(得分:8)
我可能在错误的直接上行驶了一百万英里(但我只是年轻人:P)。但是你不能将图形添加到面板,然后将鼠标滑块添加到图形对象,以便当图形上的用户执行操作时。
答案 4 :(得分:6)
我从早期的CS课程开始就没有完成SWING开发,但如果它没有内置,你可以继承javax.swing.AbstractButton
并创建自己的。将某些内容与现有框架连在一起应该非常简单。