本帖最后由 maomidemati 于 2011-09-13 22:58:35 编辑

解决方案 »

  1.   

    我改了一下第一次按下是灰色的,第二次点击是黄色背景,我也不是很清楚为什么出现这个效果
    发现如果设置前景色的话一切会是按照逻辑走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);
        }
    }
      

  2.   

    谢谢楼上的兄弟帮忙!
    现在也很怀疑是setBackground的问题,在csdn里找到了很早一个高手mq612的回复:
    “点击后的颜色你并没有更改,setBackground(Color)方法只改变了正常状态下的背景颜色,当你第一次点击的时候显示的深灰色是组件默认的,可是这时候你用setBackground(Color)方法改变了正常状态下的颜色,所以当你再次点击回到正常状态的时候,你想要的颜色出现了。”猜想可能JToggleButton的按下状态就接受setBackground()方法设置的颜色了,需求其他高手证实下;
    如果真这样,要达到我的需求,是否可以在不同的select状态设置不同的icon?
      

  3.   

    我做实验的时候也是猜到了是执行了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);
                        }
                    }
                });
      

  4.   

        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);
                            }
                        }
                    });
            }
        }
      

  5.   


    很囧,代码证明你这个根本不会变成黄色背景色一次……楼主还是用Icon的方法解决吧,可以参照我写的那个例子
      

  6.   


    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)
      

  7.   

      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);
                            }
                        }
                    });
            }
        }
      

  8.   


    我的运行环境和你一样,
    用默认的 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);
    }}
      

  9.   

    使用Metal laf的话
    JToggleButton toggle = new JToggleButton("Switch");
    toggle.setBackground(Color.GREEN);
    toggle.setUI(new MetalToggleButtonUI(){
        @Override protected Color getSelectColor(){
            return Color.YELLOW;
        }
    });
      

  10.   

    楼上这样做的话,不是很标准哦
    一个JAVA界面做好之后,
    如果一 updateUI 就让很多已经设置好的效果消失的话,那是很不可取的例如:如果希望某个控件有一个空边框
    很多人喜欢这样设:
    component.setBorder(null);
    但是这样设,一旦 updateUI 就会把边框设回成默认的了
    至于为什么,看一下 LookAndFeel.installBorder 的源码就知道了
    控件安装 ui 的时候,都是用这个方法设置边框的
    所以如果希望有个空边框,应该这样设:
    component.setBorder(BorderFactory.createEmptyBorder());
      

  11.   

    确实如此。以前没手动调用过 updateUI,没注意到这个问题。
      

  12.   

    非常感谢sunyiz兄弟的帮忙!
    这个解答圆满的达到了需求,而且还学到了牛人的解决方法,从对应的UI类源码中去探索。非常感谢!!
      

  13.   

    这是小弟csdn上第一次发帖,没想到得到各位朋友的鼎力相助,这么快就解决了难题,非常感激。
    小弟虽穷,再加点分,才能表达感激之情:)