我想在现有的JComponent基础上创建一个新的Swing,但是使用不同的API。换句话说,我不想扩展现有的组件,因为我不希望它是可访问的API。
这里有一个例子来说明我的需要:
JCheckBox
的替换,它显示两个按钮的开/关。这可以基于预先配置的JCommandButtonStrip
(一些信息这里),但公开完全相同的JCheckBox
API。不得更改JCommandButtonStrip
的配置。
解决这一问题的最佳办法是什么?
Clarifications:
正如有人指出的那样,我写的关于API的内容还不清楚。
当然,JComponent
有许多公共字段和方法,每个子类都可以使用它们。然后,JComponent
的每个子类都可以添加自己的公共字段和方法。例如,AbstractButton
添加isSelected()
方法,而JCommandButtonStrip
添加getButtonCount()
方法。
所以,我的意思是:我想创建一个新的JComponent
子类MyJComponent
,它基于一个现有的ExistingJComponent
。我不希望ExistingJComponent
的公共方法(除了JComponent
的方法)被我的类MyJComponent
公开。然后,我想向MyJComponent
添加一些公共方法。
请注意,我并不是在寻找JCommandButtonStrip
/JCheckBox
示例的替代方案。我对解决这个问题的一般方法很感兴趣。
发布于 2014-03-25 17:05:58
您可以创建一个扩展JComponent的新类,然后在构造函数中插入一个复选框。
public class MyCoolCheckbox extends JComponent{
private JCheckBox checkbox;
public MyCoolCheckbox(String label) {
checkbox= new JCheckBox(label);
this.setLayout(new BorderLayout());
this.add(checkbox, BorderLayout.CENTER);
}
}
这显然是不完整的,您可能需要将某些方法委托给孩子。可能会很乱。IDEs (如IntelliJ IDEA )将为您生成所有这些,如果您点击alt- if (默认情况下),然后委托,然后选择复选框成员并选择您想要委派的条目。例如:
public void setForeground(Color fg) {
checkbox.setForeground(fg);
}
public void setBackground(Color bg) {
checkbox.setBackground(bg);
}
public Color getForeground() {
return checkbox.getForeground();
}
public Color getBackground() {
return checkbox.getBackground();
}
请记住,因为子代码位于Swing组件树中,其他代码可以访问这些子代码,即使它们被标记为私有。
((JCheckBox)myCoolCheckbox.getComponents()[0]).setSelected(true);
发布于 2014-03-25 23:23:24
基于这张JCommandButtonStrip
图片
我认为您正在寻找JToggleButton,就像@垃圾上帝建议的那样,但是考虑到当前对您的“问题”的描述,我不确定按钮组。如果您需要按钮组,那么使用它。
不管怎样,我的回答指向了这句话:
这可以基于预先配置的
JCommandButtonStrip
(这里有一些信息),但公开完全相同的JCheckBox
API。
再一次,我们还不清楚你是在尝试做一个按钮条,比如JCommandButtonStrip
,还是想做其他的事情。但是,您可以从JComponent扩展您自己的组件,并且只从外部委托那些需要的方法。例如,假设您想要做一个按钮条,比如JCommandButtonStrip
。然后你就可以拥有:
JComponent
扩展的类:按钮条。Note:已经有一个JToolBar组件可以完美地使用,而无需重新发明轮子。下面的示例只是为了向您展示您可以控制提供给开发人员的API。
MyCommandBar.java
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.event.ChangeListener;
public class MyCommandBar extends JComponent {
private final JPanel content;
private final Map<String, CommandItem> map = new HashMap<>();
public MyCommandBar() {
super();
content = new JPanel(new GridLayout(1, 0));
content.setOpaque(false);
setLayout(new FlowLayout());
add(content);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics graphics = g.create();
graphics.setColor(getBackground());
graphics.fillRect(0, 0, getWidth(), getHeight());
graphics.dispose();
}
public void addCommandItem(String actionCommand, CommandItem commandItem) {
if(map.get(actionCommand) != null) {
removeCommandItem(actionCommand);
}
content.add(commandItem.getComponent());
map.put(actionCommand, commandItem);
}
public void removeCommandItem(String actionCommand) {
CommandItem commandItem = map.get(actionCommand);
if(commandItem != null) {
content.remove(commandItem.getComponent());
content.revalidate();
content.repaint();
map.remove(actionCommand);
}
}
public CommandItem getCommandItem(String actionCommand) {
return map.get(actionCommand);
}
public static class CommandItem {
public static final int TOGGLE_BUTTON_STYLE = 0;
public static final int CHECK_BOX_STYLE = 1;
public static final int DEFAULT_BUTTON_STYLE = 2;
private final AbstractButton component;
public CommandItem(String text, boolean state, Icon icon, int style) {
switch(style) {
case TOGGLE_BUTTON_STYLE : component = new JToggleButton(text, icon, state); break;
case CHECK_BOX_STYLE : component = new JCheckBox(text, icon, state); break;
default: component = new JButton(text, icon);
}
}
protected AbstractButton getComponent() {
return component;
}
public void addActionListener(ActionListener listener) {
component.addActionListener(listener);
}
public void addChangeListener(ChangeListener listener) {
component.addChangeListener(listener);
}
public void setAction(Action action) {
component.setAction(action);
}
}
}
使用实例
这个代码片段展示了如何使用MyCommandBar
类:
MyCommandBar commandBar = new MyCommandBar();
commandBar.setBorder(BorderFactory.createLineBorder(Color.black, 1));
commandBar.addCommandItem("BOLD", new MyCommandBar.CommandItem("<html><b>Bold</b></html>", true, null, MyCommandBar.CommandItem.TOGGLE_BUTTON_STYLE));
commandBar.addCommandItem("ITALICS", new MyCommandBar.CommandItem("<html><i>Italics</i></html>", false, null, MyCommandBar.CommandItem.CHECK_BOX_STYLE));
commandBar.addCommandItem("UNDERLINE", new MyCommandBar.CommandItem("<html><u>Underline</u></html>", false, null, MyCommandBar.CommandItem.DEFAULT_BUTTON_STYLE));
你会看到这样的东西:
发布于 2014-03-26 19:52:50
可以使用引用JComponent
转发类的私有字段创建JComponent
的JComponent
子类。
与ExistingComponent
的交互是通过MyJComponent
的方法与转发类完成的,您可以自由地向MyJComponent
添加更多的方法。
关于转发类使用的委托模式,请参见有效的Java项目16。
https://stackoverflow.com/questions/22641561
复制相似问题