【问题标题】:BasicButtonUI button won’t repaintBasicButtonUI 按钮不会重绘
【发布时间】:2015-08-01 17:59:26
【问题描述】:

我正在尝试在this SO post 上找到的关于使用 BasicButtonUI 制作的自定义按钮的代码。我试图让我的自定义按钮在按下时消失,但由于某种原因我看不到任何结果。我做了一个SSCCE来说明问题:

我在计时器中放了一个打印语句来验证它是否正常工作,这让我相信我重绘的方式有问题。

import javax.swing.*;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.*;
import java.awt.event.*;

class StyledButtonUI extends BasicButtonUI {

  @Override
  public void installUI (JComponent c) {
    super.installUI(c);
    AbstractButton button = (AbstractButton) c;
    button.setOpaque(false);
    button.setBorder(BorderFactory.createEmptyBorder (5, 15, 5, 15));
  }

  @Override
  public void paint (Graphics g, JComponent c) {
    AbstractButton b = (AbstractButton) c;
    paintBackground(g, b, b.getModel().isPressed () ? true : false);
    super.paint(g, c);
  }

  private void paintBackground (final Graphics g, final JComponent c, boolean fade) {
    final Dimension size = c.getSize();
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    //draws normal button
    g.setColor (c.getBackground ());
    g.fillRoundRect (0, 0, size.width, size.height - 5, 10, 10);

    if (fade) {
      Timer timer = new Timer (50, new ActionListener () {
        int i = 0;//starting opacity
        int limit = 15;//opacity limit

        public void actionPerformed (ActionEvent ae) {
          if (i <= limit) {
            System.out.println ("background color: " + c.getBackground () + " alpha: " + c.getBackground ().getAlpha () + " new fade in color: " + getAlphaColor (c.getBackground (), i) + " fade in alpha: " + i);
            g.setColor (getAlphaColor (c.getBackground (), i));
            g.fillRoundRect(0, 0, size.width, size.height - 5, 10, 10);
            i++;
          }
          else {
            ((Timer) ae.getSource ()).stop ();
          }
        }});

      timer.start ();
    }
  }

  private Color getAlphaColor (Color color, int newAlpha) {
    return new Color (color.getRed (), color.getGreen (), color.getBlue (), newAlpha);
  }

  public static void main (String[] args) {
    JFrame f = new JFrame("Button UI Test");
    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    JPanel p = new JPanel();
    p.setBackground(Color.WHITE);
    f.setContentPane(p);

    for (int i = 1; i <= 5; i++) {
      final JButton button = new JButton("Button #" + i);

      button.setBackground(Color.BLACK);
      button.setForeground(Color.WHITE);

      button.setUI(new StyledButtonUI());
      p.add(button);
    }

    f.pack();
    f.setLocation(500, 500);
    f.setVisible(true);
  }
}

【问题讨论】:

    标签: java swing timer jbutton transparency


    【解决方案1】:

    不确定我是否会为此更改 UI。您绝对不应该在 painting() 方法中启动 Timer。您无法控制 Swing 何时确定组件需要重新绘制。例如,当您将鼠标移到按钮上时,它会重新绘制以实现翻转效果。

    下面是一个类的示例,该类可以在组件获得焦点时淡化任何组件的背景:

    import java.awt.*;
    import java.awt.event.*;
    import java.util.Hashtable;
    import java.util.ArrayList;
    import javax.swing.*;
    
    public class Fader
    {
        //  background color when component has focus
        private Color fadeColor;
    
        //  steps to fade from original background to fade background
        private int steps;
    
        //  apply transition colors at this time interval
        private int interval;
    
        //  store transition colors from orginal background to fade background
        private Hashtable backgroundColors = new Hashtable();
    
        /*
         *  Fade from a background color to the specified color using
         *  the default of 10 steps at a 50 millisecond interval.
         *
         *  @param fadeColor the temporary background color
         */
        public Fader(Color fadeColor)
        {
            this(fadeColor, 10, 50);
        }
    
        /*
         *  Fade from a background color to the specified color in the
         *  specified number of steps at the default 5 millisecond interval.
         *
         *  @param fadeColor the temporary background color
         *  @param steps     the number of steps to fade in the color
         */
        public Fader(Color fadeColor, int steps)
        {
            this(fadeColor, steps, 50);
        }
    
        /*
         *  Fade from a background color to the specified color in the
         *  specified number of steps at the specified time interval.
         *
         *  @param fadeColor the temporary background color
         *  @param steps     the number of steps to fade in the color
         *  @param intevral  the interval to apply color fading
         */
        public Fader(Color fadeColor, int steps, int interval)
        {
            this.fadeColor = fadeColor;
            this.steps = steps;
            this.interval = interval;
        }
    
        /*
         *  Add a component to this fader.
         *
         *  The fade color will be applied when the component gains focus.
         *  The background color will be restored when the component loses focus.
         *
         *  @param component apply fading to this component
        */
        public Fader add(JComponent component)
        {
            //  Get colors to be used for fading
    
            ArrayList colors = getColors( component.getBackground() );
    
            //  FaderTimer will apply colors to the component
    
            new FaderTimer( colors, component, interval );
    
            return this;
        }
    
        /*
        **  Get the colors used to fade this background
        */
        private ArrayList getColors(Color background)
        {
            //  Check if the color ArrayList already exists
    
            Object o = backgroundColors.get( background );
    
            if (o != null)
            {
                return (ArrayList)o;
            }
    
            //  Doesn't exist, create fader colors for this background
    
            ArrayList colors = new ArrayList( steps + 1 );
            colors.add( background );
    
            int rDelta = ( background.getRed() - fadeColor.getRed() ) / steps;
            int gDelta = ( background.getGreen() - fadeColor.getGreen() ) / steps;
            int bDelta = ( background.getBlue() - fadeColor.getBlue() ) / steps;
    
            for (int i = 1; i < steps; i++)
            {
                int rValue = background.getRed() - (i * rDelta);
                int gValue = background.getGreen() - (i * gDelta);
                int bValue = background.getBlue() - (i * bDelta);
    
                colors.add( new Color(rValue, gValue, bValue) );
            }
    
            colors.add( fadeColor );
            backgroundColors.put(background, colors);
    
            return colors;
        }
    
        class FaderTimer implements FocusListener, ActionListener
        {
            private ArrayList colors;
            private JComponent component;
            private Timer timer;
            private int alpha;
            private int increment;
    
            FaderTimer(ArrayList colors, JComponent component, int interval)
            {
                this.colors = colors;
                this.component = component;
                component.addFocusListener( this );
                timer = new Timer(interval, this);
            }
    
            public void focusGained(FocusEvent e)
            {
                alpha = 0;
                increment = 1;
                timer.start();
            }
    
            public void focusLost(FocusEvent e)
            {
                alpha = steps;
                increment = -1;
                timer.start();
            }
    
            public void actionPerformed(ActionEvent e)
            {
                alpha += increment;
    
                component.setBackground( (Color)colors.get(alpha) );
    
                if (alpha == steps || alpha == 0)
                    timer.stop();
            }
        }
    
        public static void main(String[] args)
        {
            // Create test components
    
            JComponent textField1 = new JTextField(10);
            textField1.setBackground( Color.YELLOW );
            JComponent textField3 = new JTextField(10);
            JComponent textField4 = new JTextField(10);
            JComponent button = new JButton("Start");
            JComponent checkBox = new JCheckBox("Check Box");
    
            JFrame frame = new JFrame("Fading Background");
            frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
            frame.getContentPane().add(textField1, BorderLayout.NORTH );
            frame.getContentPane().add(button, BorderLayout.SOUTH );
            frame.getContentPane().add(textField3, BorderLayout.WEST );
            frame.getContentPane().add(textField4, BorderLayout.EAST );
            frame.getContentPane().add(checkBox);
    
            //  Gradual Fading (using defaults)
    
    //      Fader fader = new Fader( new Color(155, 255, 155) );
            Fader fader = new Fader( new Color(155, 255, 155), 10, 50 );
            fader.add( textField1 );
            fader.add( textField3 );
            fader.add( checkBox );
    
            //  Instant Fading
    
            fader = new Fader( new Color(255, 155, 155), 1, 1 );
            fader.add( textField4 );
            fader.add( button );
    
            frame.pack();
            frame.setVisible( true );
        }
    }
    

    您需要对其进行自定义以支持鼠标按下时的淡入淡出。

    【讨论】:

    • 谢谢,这正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    • 2016-04-24
    相关资源
    最近更新 更多