请教:判断JToggleButton的select状态设置不同背景色问题 本帖最后由 maomidemati 于 2011-09-13 22:58:35 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我改了一下第一次按下是灰色的,第二次点击是黄色背景,我也不是很清楚为什么出现这个效果发现如果设置前景色的话一切会是按照逻辑走import java.awt.Color;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.*;public class Hour { JPanel timePanel = new JPanel(); JBusyTimeButton btn1 = new JBusyTimeButton("1"); JBusyTimeButton btn2 = new JBusyTimeButton("2"); JBusyTimeButton btn3 = new JBusyTimeButton("3"); JBusyTimeButton btn4 = new JBusyTimeButton("4"); JBusyTimeButton btn5 = new JBusyTimeButton("5"); JBusyTimeButton btn6 = new JBusyTimeButton("6"); public Hour() { timePanel.add(btn1); timePanel.add(btn2); timePanel.add(btn3); timePanel.add(btn4); timePanel.add(btn5); timePanel.add(btn6); } public JPanel getBusyTimePanel() { return timePanel; } public class JBusyTimeButton extends JToggleButton { private static final long serialVersionUID = 1L; public JBusyTimeButton(String text) { super(text); setBackground(Color.green); this.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {// if (!((JToggleButton)e.getSource()).isSelected()) {// ((JToggleButton)e.getSource()).setBackground(Color.green);// } else {// ((JToggleButton)e.getSource()).setBackground(Color.YELLOW);// } JToggleButton j=(JToggleButton)e.getSource(); ButtonModel bm=j.getModel(); if(bm.isSelected()) { j.setBackground(Color.YELLOW); System.out.println("奇数次按下,更改颜色"); } } }); } } public static void main(String[] args) { JFrame frame = new JFrame(); Hour bt = new Hour(); frame.add(bt.getBusyTimePanel()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); }} 谢谢楼上的兄弟帮忙!现在也很怀疑是setBackground的问题,在csdn里找到了很早一个高手mq612的回复:“点击后的颜色你并没有更改,setBackground(Color)方法只改变了正常状态下的背景颜色,当你第一次点击的时候显示的深灰色是组件默认的,可是这时候你用setBackground(Color)方法改变了正常状态下的颜色,所以当你再次点击回到正常状态的时候,你想要的颜色出现了。”猜想可能JToggleButton的按下状态就接受setBackground()方法设置的颜色了,需求其他高手证实下;如果真这样,要达到我的需求,是否可以在不同的select状态设置不同的icon? 我做实验的时候也是猜到了是执行了setBackgroud的方法,但是因为多线程的机制没有及时重绘按钮不过也没整清楚怎么改,另一方面,我用前景色设置逻辑上都是很正常的。我觉得能满足需求的情况下,用按钮的Icon来解决是不错的选择,给你贴出来代码,代码里面获取image的方法不推荐,虽然可以跑public JBusyTimeButton(String text) { super(text); setBackground(Color.green); this.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JToggleButton j=(JToggleButton)e.getSource(); ButtonModel bm=j.getModel(); if(bm.isSelected()) {// j.setBackground(Color.YELLOW); //这里找一张跟按钮恰好大小的图片就可以了 j.setIcon(new ImageIcon("resources/images/thu2.jpeg")); System.out.println("奇数次按下,更改颜色"); } else{ j.setIcon(null); } } }); public class JBusyTimeButton extends JToggleButton { private static final long serialVersionUID = 3243445422431L; public JBusyTimeButton(String text) { super(text); setBackground(Color.GREEN); this.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JToggleButton toggle = (JToggleButton)e.getSource(); if(toggle.isSelected()) { toggle.setBackground(Color.YELLOW); }else { toggle.setBackground(Color.GREEN); } } }); } } 很囧,代码证明你这个根本不会变成黄色背景色一次……楼主还是用Icon的方法解决吧,可以参照我写的那个例子 java -versionjava version "1.7.0"Java(TM) SE Runtime Environment (build 1.7.0-b147)Java HotSpot(TM) Client VM (build 21.0-b17, mixed mode, sharing) public class JBusyTimeButton extends JToggleButton { private static final long serialVersionUID = 3243445422431L; public JBusyTimeButton(String text) { super(text); setBackground(Color.GREEN); this.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JToggleButton toggle = (JToggleButton)e.getSource(); if(toggle.isSelected()) { toggle.setBackground(Color.YELLOW); }else { toggle.setBackground(Color.GREEN); } } }); } } 我的运行环境和你一样,用默认的 Metal L&F 表示任然没有变黄不知道你用的是什么L&F看下 MetalToggleButtonUI 就明白了, protected void paintButtonPressed(Graphics g, AbstractButton b) { if ( b.isContentAreaFilled() ) { g.setColor(getSelectColor()); g.fillRect(0, 0, b.getWidth(), b.getHeight()); } } protected Color getSelectColor() { return selectColor; } public void installDefaults(AbstractButton b) { super.installDefaults(b); if(!defaults_initialized) { focusColor = UIManager.getColor(getPropertyPrefix() + "focus"); selectColor = UIManager.getColor(getPropertyPrefix() + "select"); disabledTextColor = UIManager.getColor(getPropertyPrefix() + "disabledText"); defaults_initialized = true; } }可以看出来,selectColor这个颜色取的是 "ToggleButton.select" 中的键值而不是什么 background 颜色用我下面这个类,应该可以解决问题import java.awt.Color;import javax.swing.AbstractButton;import javax.swing.JFrame;import javax.swing.JToggleButton;import javax.swing.plaf.metal.MetalToggleButtonUI;@SuppressWarnings("serial")public class JPressButton extends JToggleButton { private Color selectBackground; /** * 其它构造方法请自己添加 */ public JPressButton() { super(); } @Override public void updateUI() { setUI(new PressButtonUI()); } public Color getSelectBackground() { return selectBackground; } public void setSelectBackground(Color selectBackground) { this.selectBackground = selectBackground; updateUI(); } class PressButtonUI extends MetalToggleButtonUI { @Override public void installDefaults(AbstractButton b) { super.installDefaults(b); JPressButton pressButton = (JPressButton) b; selectColor = pressButton.getSelectBackground(); } } /** * 示例 * @param args */ public static void main(String... args) { JFrame frame = new JFrame(); JPressButton button = new JPressButton(); button.setText("123"); button.setBackground(Color.green); button.setSelectBackground(Color.yellow); frame.setContentPane(button); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); }} 使用Metal laf的话JToggleButton toggle = new JToggleButton("Switch");toggle.setBackground(Color.GREEN);toggle.setUI(new MetalToggleButtonUI(){ @Override protected Color getSelectColor(){ return Color.YELLOW; }}); 楼上这样做的话,不是很标准哦一个JAVA界面做好之后,如果一 updateUI 就让很多已经设置好的效果消失的话,那是很不可取的例如:如果希望某个控件有一个空边框很多人喜欢这样设:component.setBorder(null);但是这样设,一旦 updateUI 就会把边框设回成默认的了至于为什么,看一下 LookAndFeel.installBorder 的源码就知道了控件安装 ui 的时候,都是用这个方法设置边框的所以如果希望有个空边框,应该这样设:component.setBorder(BorderFactory.createEmptyBorder()); 确实如此。以前没手动调用过 updateUI,没注意到这个问题。 非常感谢sunyiz兄弟的帮忙!这个解答圆满的达到了需求,而且还学到了牛人的解决方法,从对应的UI类源码中去探索。非常感谢!! 这是小弟csdn上第一次发帖,没想到得到各位朋友的鼎力相助,这么快就解决了难题,非常感激。小弟虽穷,再加点分,才能表达感激之情:) 找不到符号 Java调用过程时的错误:PLS-00306求解 倒!我的eclipse没有了颜色提示! 我做了个局域网广播的小程序,就是有问题找不到: 简单的问题,谢谢大家!!! 帮忙,HELP! ImageIO.read()都可以接受什么样的图片格式? 如何导出HTML文件里面的数据? 编译通过,运行时Exception in thread "main" java.lang.NoClassDefFoundError:到底是什么错误??? 高分挑错!高手快来出招啊。。。。。。 这个常量是什么情况? 位移操作
发现如果设置前景色的话一切会是按照逻辑走import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.*;public class Hour {
JPanel timePanel = new JPanel();
JBusyTimeButton btn1 = new JBusyTimeButton("1");
JBusyTimeButton btn2 = new JBusyTimeButton("2");
JBusyTimeButton btn3 = new JBusyTimeButton("3");
JBusyTimeButton btn4 = new JBusyTimeButton("4");
JBusyTimeButton btn5 = new JBusyTimeButton("5");
JBusyTimeButton btn6 = new JBusyTimeButton("6"); public Hour() {
timePanel.add(btn1);
timePanel.add(btn2);
timePanel.add(btn3);
timePanel.add(btn4);
timePanel.add(btn5);
timePanel.add(btn6);
} public JPanel getBusyTimePanel() {
return timePanel;
} public class JBusyTimeButton extends JToggleButton {
private static final long serialVersionUID = 1L; public JBusyTimeButton(String text) {
super(text);
setBackground(Color.green);
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// if (!((JToggleButton)e.getSource()).isSelected()) {
// ((JToggleButton)e.getSource()).setBackground(Color.green);
// } else {
// ((JToggleButton)e.getSource()).setBackground(Color.YELLOW);
// }
JToggleButton j=(JToggleButton)e.getSource();
ButtonModel bm=j.getModel();
if(bm.isSelected()) {
j.setBackground(Color.YELLOW); System.out.println("奇数次按下,更改颜色");
}
}
});
}
} public static void main(String[] args) {
JFrame frame = new JFrame();
Hour bt = new Hour();
frame.add(bt.getBusyTimePanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
现在也很怀疑是setBackground的问题,在csdn里找到了很早一个高手mq612的回复:
“点击后的颜色你并没有更改,setBackground(Color)方法只改变了正常状态下的背景颜色,当你第一次点击的时候显示的深灰色是组件默认的,可是这时候你用setBackground(Color)方法改变了正常状态下的颜色,所以当你再次点击回到正常状态的时候,你想要的颜色出现了。”猜想可能JToggleButton的按下状态就接受setBackground()方法设置的颜色了,需求其他高手证实下;
如果真这样,要达到我的需求,是否可以在不同的select状态设置不同的icon?
不过也没整清楚怎么改,另一方面,我用前景色设置逻辑上都是很正常的。我觉得能满足需求的情况下,用按钮的Icon来解决是不错的选择,给你贴出来代码,代码里面获取image的方法不推荐,虽然可以跑
public JBusyTimeButton(String text) {
super(text);
setBackground(Color.green);
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JToggleButton j=(JToggleButton)e.getSource();
ButtonModel bm=j.getModel();
if(bm.isSelected()) {
// j.setBackground(Color.YELLOW);
//这里找一张跟按钮恰好大小的图片就可以了
j.setIcon(new ImageIcon("resources/images/thu2.jpeg"));
System.out.println("奇数次按下,更改颜色");
} else{
j.setIcon(null);
}
}
});
private static final long serialVersionUID = 3243445422431L; public JBusyTimeButton(String text) {
super(text);
setBackground(Color.GREEN);
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JToggleButton toggle = (JToggleButton)e.getSource(); if(toggle.isSelected()) {
toggle.setBackground(Color.YELLOW);
}else {
toggle.setBackground(Color.GREEN);
}
}
});
}
}
很囧,代码证明你这个根本不会变成黄色背景色一次……楼主还是用Icon的方法解决吧,可以参照我写的那个例子
java -version
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) Client VM (build 21.0-b17, mixed mode, sharing)
private static final long serialVersionUID = 3243445422431L; public JBusyTimeButton(String text) {
super(text);
setBackground(Color.GREEN);
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JToggleButton toggle = (JToggleButton)e.getSource(); if(toggle.isSelected()) {
toggle.setBackground(Color.YELLOW);
}else {
toggle.setBackground(Color.GREEN);
}
}
});
}
}
我的运行环境和你一样,
用默认的 Metal L&F 表示任然没有变黄
不知道你用的是什么L&F
看下 MetalToggleButtonUI 就明白了, protected void paintButtonPressed(Graphics g, AbstractButton b) {
if ( b.isContentAreaFilled() ) {
g.setColor(getSelectColor());
g.fillRect(0, 0, b.getWidth(), b.getHeight());
}
} protected Color getSelectColor() {
return selectColor;
} public void installDefaults(AbstractButton b) {
super.installDefaults(b);
if(!defaults_initialized) {
focusColor = UIManager.getColor(getPropertyPrefix() + "focus");
selectColor = UIManager.getColor(getPropertyPrefix() + "select");
disabledTextColor = UIManager.getColor(getPropertyPrefix() + "disabledText");
defaults_initialized = true;
}
}可以看出来,selectColor这个颜色取的是 "ToggleButton.select" 中的键值
而不是什么 background 颜色用我下面这个类,应该可以解决问题
import java.awt.Color;import javax.swing.AbstractButton;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.plaf.metal.MetalToggleButtonUI;@SuppressWarnings("serial")
public class JPressButton extends JToggleButton {
private Color selectBackground;
/**
* 其它构造方法请自己添加
*/
public JPressButton() {
super();
}
@Override
public void updateUI() {
setUI(new PressButtonUI());
} public Color getSelectBackground() {
return selectBackground;
} public void setSelectBackground(Color selectBackground) {
this.selectBackground = selectBackground;
updateUI();
}
class PressButtonUI extends MetalToggleButtonUI {
@Override
public void installDefaults(AbstractButton b) {
super.installDefaults(b);
JPressButton pressButton = (JPressButton) b;
selectColor = pressButton.getSelectBackground();
}
}
/**
* 示例
* @param args
*/
public static void main(String... args) {
JFrame frame = new JFrame();
JPressButton button = new JPressButton();
button.setText("123");
button.setBackground(Color.green);
button.setSelectBackground(Color.yellow);
frame.setContentPane(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}}
JToggleButton toggle = new JToggleButton("Switch");
toggle.setBackground(Color.GREEN);
toggle.setUI(new MetalToggleButtonUI(){
@Override protected Color getSelectColor(){
return Color.YELLOW;
}
});
一个JAVA界面做好之后,
如果一 updateUI 就让很多已经设置好的效果消失的话,那是很不可取的例如:如果希望某个控件有一个空边框
很多人喜欢这样设:
component.setBorder(null);
但是这样设,一旦 updateUI 就会把边框设回成默认的了
至于为什么,看一下 LookAndFeel.installBorder 的源码就知道了
控件安装 ui 的时候,都是用这个方法设置边框的
所以如果希望有个空边框,应该这样设:
component.setBorder(BorderFactory.createEmptyBorder());
这个解答圆满的达到了需求,而且还学到了牛人的解决方法,从对应的UI类源码中去探索。非常感谢!!
小弟虽穷,再加点分,才能表达感激之情:)