在 Java 中创建自定义 JButton
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating a custom JButton in Java
提问by Anton
Is there a way to create a JButton
with your own button graphic and not just with an image inside the button?
有没有办法JButton
用你自己的按钮图形而不只是在按钮内创建一个图像?
If not, is there another way to create a custom JButton
in java?
如果没有,还有另一种方法可以JButton
在java中创建自定义吗?
采纳答案by Kevin
When I was first learning Java we had to make Yahtzee and I thought it would be cool to create custom Swing components and containers instead of just drawing everything on one JPanel
. The benefit of extending Swing
components, of course, is to have the ability to add support for keyboard shortcuts and other accessibility features that you can't do just by having a paint()
method print a pretty picture. It may not be done the best way however, but it may be a good starting point for you.
当我第一次学习 Java 时,我们不得不制作 Yahtzee,我认为创建自定义 Swing 组件和容器而不是仅仅在一个JPanel
. Swing
当然,扩展组件的好处是能够添加对键盘快捷键和其他辅助功能的支持,而这些功能仅靠一种paint()
方法无法打印出漂亮的图片。然而,它可能不是最好的方式,但它可能是你的一个很好的起点。
Edit 8/6 - If it wasn't apparent from the images, each Die is a button you can click. This will move it to the DiceContainer
below. Looking at the source code you can see that each Die button is drawn dynamically, based on its value.
编辑 8/6 - 如果从图像中看不出来,每个 Die 都是一个可以单击的按钮。这将把它移到DiceContainer
下面。查看源代码,您可以看到每个 Die 按钮都是根据其值动态绘制的。
Here are the basic steps:
以下是基本步骤:
- Create a class that extends
JComponent
- Call parent constructor
super()
in your constructors - Make sure you class implements
MouseListener
Put this in the constructor:
enableInputMethods(true); addMouseListener(this);
Override these methods:
public Dimension getPreferredSize() public Dimension getMinimumSize() public Dimension getMaximumSize()
Override this method:
public void paintComponent(Graphics g)
- 创建一个扩展的类
JComponent
super()
在构造函数中调用父构造函数- 确保你的类实现
MouseListener
把它放在构造函数中:
enableInputMethods(true); addMouseListener(this);
覆盖这些方法:
public Dimension getPreferredSize() public Dimension getMinimumSize() public Dimension getMaximumSize()
覆盖此方法:
public void paintComponent(Graphics g)
The amount of space you have to work with when drawing your button is defined by getPreferredSize()
, assuming getMinimumSize()
and getMaximumSize()
return the same value. I haven't experimented too much with this but, depending on the layout you use for your GUI your button could look completely different.
绘制按钮时必须使用的空间量由 定义getPreferredSize()
,假设getMinimumSize()
并getMaximumSize()
返回相同的值。我没有对此进行过多实验,但是,根据您用于 GUI 的布局,您的按钮可能看起来完全不同。
And finally, the source code. In case I missed anything.
最后,源代码。万一我错过了什么。
回答by John Downey
I haven't done SWING development since my early CS classes but if it wasn't built in you could just inherit javax.swing.AbstractButton
and create your own. Should be pretty simple to wire something together with their existing framework.
自从我早期的 CS 课程以来,我就没有做过 SWING 开发,但如果它没有内置,你可以继承javax.swing.AbstractButton
并创建自己的。将某些东西与他们现有的框架连接起来应该非常简单。
回答by rjohnston
You could always try the Synth look & feel. You provide an xml file that acts as a sort of stylesheet, along with any images you want to use. The code might look like this:
您可以随时尝试 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);
}
From there, go on and add your JButton like you normally would. The only change is that you use the setName(string) method to identify what the button should map to in the xml file.
从那里,像往常一样继续添加 JButton。唯一的变化是您使用 setName(string) 方法来标识按钮应该映射到 xml 文件中的内容。
The xml file might look like this:
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>
The bind element there specifies what to map to (in this example, it will apply that styling to any buttons whose name property has been set to "dirt").
那里的 bind 元素指定要映射到的内容(在本例中,它将将该样式应用于 name 属性已设置为“dirt”的任何按钮)。
And a couple of useful links:
还有一些有用的链接:
http://javadesktop.org/articles/synth/
http://javadesktop.org/articles/synth/
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/synth.html
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/synth.html
回答by McDowell
Yes, this is possible. One of the main pros for using Swing is the ease with which the abstract controls can be created and manipulates.
是的,这是可能的。使用 Swing 的主要优点之一是可以轻松创建和操作抽象控件。
Here is a quick and dirty way to extend the existing JButton class to draw a circle to the right of the text.
这是扩展现有 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);
}
}
Note that by overriding paintComponentthat the contents of the button can be changed, but that the border is painted by the paintBordermethod. The getPreferredSizemethod also needs to be managed in order to dynamically support changes to the content. Care needs to be taken when measuring font metrics and image dimensions.
请注意,通过覆盖paintComponent可以更改按钮的内容,但边框是由paintBorder方法绘制的。所述的getPreferredSize方法也需要以动态地支持改动的内容进行管理。在测量字体指标和图像尺寸时需要小心。
For creating a control that you can rely on, the above code is not the correct approach. Dimensions and colours are dynamic in Swing and are dependent on the look and feel being used. Even the default Metallook has changed across JRE versions. It would be better to implement AbstractButtonand conform to the guidelines set out by the Swing API. A good starting point is to look at the javax.swing.LookAndFeeland javax.swing.UIManagerclasses.
为了创建一个您可以依赖的控件,上面的代码不是正确的方法。尺寸和颜色在 Swing 中是动态的,并且取决于所使用的外观和感觉。甚至JRE 版本的默认Metal外观也发生了变化。最好实现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/LookAndFeel.html
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
Understanding the anatomy of LookAndFeel is useful for writing controls: Creating a Custom Look and Feel
了解 LookAndFeel 的结构对于编写控件很有用: 创建自定义外观和感觉
回答by AngelOfCake
I'm probably going a million miles in the wrong direct (but i'm only young :P ). but couldn't you add the graphic to a panel and then a mouselistener to the graphic object so that when the user on the graphic your action is preformed.
我可能会在错误的方向上行驶一百万英里(但我还年轻:P)。但是您不能将图形添加到面板,然后将鼠标侦听器添加到图形对象,以便当用户在图形上执行您的操作时。