【问题标题】:Ways to Fade JLabels?淡化 JLabels 的方法?
【发布时间】:2019-03-12 17:16:44
【问题描述】:

我在制作游戏时遇到问题。我正在尝试使用计时器淡化 JLabel。到目前为止,我已经能够将 JLabel 设置为透明,并且我已经能够制作一个工作定时器。但不知何故,我无法将它们结合在一起。我可以将 JLabel 的背景设置为

l.setBackground(new Color(0, 0, 0, 200));

(当然需要 JLabel 来改变颜色) 它有效。 JLabel 是透明的。 但我无法将其放入计时器中以使颜色变淡:

public static void fadeLabel(JLabel lab, int steps, int target) {
    class fade extends Thread {
        public void run() {
            Timer t = new Timer(10, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println(lab.getBackground().getAlpha());
                    lab.setBackground(new 
                    Color(lab.getBackground().getRed(), 
                    lab.getBackground().getGreen(), 
                    lab.getBackground().getBlue(), 
                    lab.getBackground().getAlpha() + steps));
                    if (lab.getBackground().getAlpha() == target) {
                        ((Timer) e.getSource()).stop();
                    }
                }
            });
            t.start();
        }
    }
    new Thread(new fade()).start();
}

相反,它只是从黑色变为透明。中间什么都没有。它还会引发错误java.lang.IllegalArgumentException: Color parameter outside of expected range: Alpha。但是,我已将步长设置为 -5(在这种情况下,它淡出的速率,因为它是负数),如果您还记得,我将 alpha 设置为可被 5 整除的值,我也有一个检查器何时到达目标,以便在到达该目标时停止计时器。有什么我做错了吗? JLabel 的背景更新太快而无法显示?任何帮助都会很棒。

编辑: 我已经修复了java.lang.IllegalArgumentException: Color parameter outside of expected range: Alpha。但是关于 JLabel 不褪色的另一个问题仍然存在,我不知道如何修复它。

【问题讨论】:

  • 您需要提供我可以下载和运行的代码。
  • @Abra 我将提供尽可能多或尽可能少的代码。请问您需要什么?
  • 一个小而完整的程序,使用您已经发布的代码。一个带有 main 方法的 java 类,用于构建您的 Swing GUI 并启动您的标签褪色代码。
  • 您是否希望计时器触发 10 次回调?

标签: java swing transparency jlabel


【解决方案1】:

我没有直接回答你的问题。 A写了一些代码,看看:D

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class MyWindow extends JFrame {

    public MyWindow() {
        initComponents();
    }

    private void initComponents() {

        setTitle( "Fading labels :)" );
        setDefaultCloseOperation( EXIT_ON_CLOSE );
        setSize( 400, 400 );
        setLocationRelativeTo( null );
        setLayout( new FlowLayout() );

        for ( int i = 0; i < 550; i++ ) {
            JLabel lab = new JLabel( "x" );
            add( lab );
            fadeLabel( lab, 10, i / 10, 0 );
        }

    }

    private void fadeLabel( JLabel label, int steps, int skipSteps, int targetAlpha ) {
        new LabelFader( label, steps, skipSteps, targetAlpha ).start();
    }

    private class LabelFader {

        JLabel label;
        int steps;
        int skipSteps;
        int targetAlpha;

        LabelFader( JLabel label, int steps, int skipSteps, int targetAlpha ) {
            this.label = label;
            this.steps = steps;
            this.skipSteps = skipSteps;
            this.targetAlpha = targetAlpha;
        }

        void start() {

            Color startColor = label.getForeground();
            int startAlpha = startColor.getAlpha();
            int deltaAlpha = startAlpha - targetAlpha;

            if ( deltaAlpha > 0 ) {

                int alphaStep = deltaAlpha / steps;

                new Thread( new Runnable() {
                    @Override
                    public void run() {

                        int totalIterations = steps + skipSteps;
                        int currIteration = 1;

                        for ( int i = 0; i < totalIterations; i++ ) {

                            if ( skipSteps == 0 ) {

                                int newAlpha = startAlpha - alphaStep * currIteration++;
                                newAlpha = newAlpha < 0 ? 0 : newAlpha;

                                Color newColor = new Color( 
                                        startColor.getRed(), 
                                        startColor.getGreen(), 
                                        startColor.getGreen(),
                                        newAlpha );

                                label.setForeground( newColor );

                            } else {
                                skipSteps--;
                            }

                            try {
                                Thread.sleep( 100 );
                            } catch ( InterruptedException exc ) {
                                exc.printStackTrace();
                            }

                        }

                        Color newColor = new Color( 
                                startColor.getRed(), 
                                startColor.getGreen(), 
                                startColor.getGreen(),
                                targetAlpha );

                        label.setForeground( newColor );

                    }
                }).start();

            }

        }

    }

    public static void main( String[] args ) {
        EventQueue.invokeLater( new Runnable() {
            public void run() {
                new MyWindow().setVisible( true );
            }
        });
    }

}

【讨论】:

  • 谢谢大佬,我试试。不确定是否使用 Thread.sleep();是最好的方法,但我会尝试。
  • 您是否可以将其压缩为一个方法,您可以将其放入 JLabel 和所需参数中,然后它会淡化它?我不是最好的类和他们的方法,所以试图把它变成一种方法,它不再起作用了。
  • 你可以让其他类也可以访问该方法吗? @davidbuzzato
【解决方案2】:

JLabel 默认情况下不是不透明的,因此它的背景不会被绘制。因此,更改其背景颜色将无效 - 除非您通过调用相关方法明确使 JLabel 不透明,如

lab.setOpaque(true)

请原谅我在您发布的代码中找不到。

此外,影响 GUI 的代码需要在 Event Dispatch Thread (EDT) 上执行。您更改 JLabel 背景颜色的代码正在单独的线程中运行。因此,运行该代码的结果是不可预测的。 javax.swing.Timer 类不需要在单独的线程中运行。只需创建一个Timer 对象,然后调用它的start 方法。因此,只需将创建 Timer 的代码从 Thread 中取出,并将其与其余的 GUI 代码一起放入。

如果您想要一个演示如何淡化 JLabel 文本的小型演示程序,请告诉我。

编辑:这是淡化JLabel 文本的演示。一个 JFrame 包含一个 JLabel 和一个 JButton。点击JButtonJLabel 文字会淡出直至消失。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.WindowConstants;

/**
 * Tests <i>Swing</i> {@link javax.swing.Timer timer}.
 */
public class LabelDim {
    private int alpha;
    private JButton button;
    private JFrame frame;
    private JLabel label;
    private Timer timer;

    public LabelDim() {
        timer = new Timer(200, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (alpha > 0) {
                    alpha -= 15;
                    label.setForeground(new Color(0, 0, 0, alpha));
                }
                else {
                    timer.stop();
                }
            }
        });
    }

    private void showGui() {
        frame = new JFrame("Dim");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        label = new JLabel("I am a fading label.", SwingConstants.CENTER);
        alpha = label.getForeground().getAlpha();
        label.setFont(label.getFont().deriveFont(24.0f));
        label.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
        frame.add(label, BorderLayout.CENTER);
        button = new JButton("Start");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                timer.start();
            }
        });
        JPanel panel = new JPanel();
        panel.add(button);
        frame.add(panel, BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        LabelDim instance = new LabelDim();
        EventQueue.invokeLater(() -> instance.showGui());
    }
}

【讨论】:

  • 一个演示程序会很可爱。而且我已经将 JLabel 的不透明度设置为 true,很抱歉漏掉了。
【解决方案3】:

第二次编辑:

这是一些有效的示例代码。它会抛出您已经修复的Exception,但这仅用于演示目的:)。

label.setOpaque 及其背景一起玩,告诉你自己会发生什么。如果您需要绘制标签背景,请将该标志设置为 true。

如果你不需要绘制它的背景,不要修改标签的背景,不要将其设置为不透明,修改前景色应该绰绰有余! :)

package main;


import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main extends JFrame {

    JLabel label;
    JButton btn;

    public Main() {
        setSize(500,500);
        setLayout(new FlowLayout());
        label = new JLabel("My super awesome label");
        //label.setOpaque(true); //Play with these lines and see what happens
        //label.setBackground(Color.BLUE); //Play with these lines and see what happens

        btn = new JButton("Click me");
        btn.setSize(200,200);
        btn.addActionListener(
                (ActionEvent evt) -> {
                    Timer t = new Timer(100,
                            (ActionEvent event) -> {
                                Color foreground = label.getForeground();
                                Color background = label.getBackground();

                                foreground = decreaseAlpha(foreground);
                                background = decreaseAlpha(background);

                                label.setForeground(foreground);
                                label.setBackground(background);
                            }
                        );

                    t.start();
                }
        );

        this.add(label);
        this.add(btn);
    }

    public static void main(String[] args) {
        (new Main()).setVisible(true);
    }

    public Color decreaseAlpha(Color original) {
        return new Color(original.getRed(), original.getGreen(), original.getBlue(), original.getAlpha() - 10);
    }
}

编辑:

您可能正在更改标签的背景而不是前景...

Timer t = new Timer(10, (ActionEvent evt)-> {
    l.setForeground(new 
        Color(l.getForeground().getRed(), 
        l.getForeground().getGreen(), 
        l.getForeground().getBlue(), 
        l.getForeground().getAlpha() - 1)
    );
    l.invalidate();
});
t.start();

成为l你的标签

另外,不要这样做:

new Thread(new fade()).start();

您的fade 类已经是Thread,因为它正在扩展它。请改用(new fade()).start();

【讨论】:

  • 我不希望调用它 10 次。我知道每次触发之间有 10 毫秒的延迟,这就是为什么我添加了 if then 语句来停止它。我遇到的问题是为什么 jLabel 没有褪色。会不会是 10ms 对这个任务来说太快了?
  • 不,我确定我只是在设置 JLabel 的背景。
  • 是的,这就是为什么不起作用。您应该改为设置 JLabel 的前景。
  • 谢谢,我会试试的。但我认为前景是文字?
  • 是的,它只是文本。我试了一下,JLabel只有白色,一点也不褪色。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-22
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
  • 2010-09-13
  • 1970-01-01
相关资源
最近更新 更多