#java #swing #transparency #jlabel
#java #swing #прозрачность #jlabel
Вопрос:
У меня возникли проблемы с игрой, которую я создаю. Я пытаюсь отключить JLabel, используя таймер. До сих пор мне удавалось установить JLabel как прозрачный, и я был в состоянии создать работающий таймер. Но почему-то я не могу объединить их вместе. Я могу установить фон JLabel на
l.setBackground(new Color(0, 0, 0, 200));
(l желателен 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 (скорость, с которой он исчезает, в данном случае, исчезает, поскольку она отрицательна), и если вы помните, я установил альфа-значение, кратное пяти, и у меня также есть средство проверки того, когда он достигает цели, чтобы он останавливал таймер при достижении этой цели. Я что-то делаю не так? Слишком быстро обновляется фон JLabel, чтобы его можно было отобразить? Любая помощь была бы отличной.
Редактировать: я исправил java.lang.IllegalArgumentException: Color parameter outside of expected range: Alpha
. Но другая о том, что JLabel не исчезает, все еще существует, и я не знаю, как это исправить.
Комментарии:
1. Вам нужно предоставить код, который я могу загрузить и запустить.
2. @Abra Я предоставлю столько кода, сколько вы захотите, или так мало. Могу я спросить, что все, что вам нужно?
3. Небольшая, полная программа, которая использует код, который вы уже опубликовали. Класс Java с
main
методом, который создает ваш графический интерфейс на Swing и запускает ваш код исчезновения надписей.4. Вы ожидаете, что таймер запустит обратный вызов 10 раз?
Ответ №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 );
}
});
}
}
Комментарии:
1. Спасибо, чувак, я попробую. Не уверен, что использование Thread.sleep(); является лучшим способом, но я попробую это.
2. Возможно ли было бы для вас свести это к одному методу, который вы можете просто ввести в JLabel и требуемые параметры, и он приведет к его исчезновению? Я не лучший специалист по классам и их методам, поэтому, пытаясь превратить это в просто метод, он больше не работает.
3. можете ли вы сделать метод доступным и из других классов? @davidbuzzato
Ответ №2:
A JLabel
по умолчанию не является непрозрачным, поэтому его фон не окрашен. Поэтому изменение цвета фона не будет иметь никакого эффекта — если вы явно не сделали свой JLabel
непрозрачным, вызвав соответствующий метод, как в
lab.setOpaque(true)
Простите меня, но я не смог найти этого в коде, который вы опубликовали.
Кроме того, код, влияющий на графический интерфейс пользователя, должен выполняться в потоке отправки событий (EDT). Ваш код, который изменяет JLabel
цвет фона, выполняется в отдельном потоке. Следовательно, результат выполнения этого кода непредсказуем. javax.swing.Timer
Класс не обязательно запускать в отдельном потоке. Просто создайте Timer
объект, а затем вызовите его start
метод. Итак, просто возьмите свой код, который создает Timer
из Thread
, и вставьте его в остальной код вашего GUI.
Если вам нужна небольшая демонстрационная программа, показывающая, как обесцвечивать текст JLabel
, дайте мне знать.
РЕДАКТИРОВАТЬ: Вот демонстрация, которая удаляет JLabel
текст. A, JFrame
содержащий a JLabel
и a JButton
. Нажмите на, JButton
и JLabel
текст исчезнет, пока не исчезнет совсем.
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());
}
}
Комментарии:
1. Демонстрационная программа была бы прекрасной. И я уже установил непрозрачность 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();
вместо
Комментарии:
1. Я не ожидаю, что буду вызывать это 10 раз. Я понимаю, что между каждым запуском существует задержка в 10 миллисекунд, поэтому я добавил оператор if then, чтобы остановить это. У меня возникли проблемы с тем, почему JLabel не исчезает. Может быть, 10 мс — это слишком быстро для задачи?
2. нет, я точно знаю, что я всего лишь устанавливаю фон JLabel.
3. Да, и именно поэтому не работает. вместо этого вы должны установить передний план JLabel.
4. спасибо, я попробую. Но я думал, что передний план — это текст?
5. да, это просто текст. Я попробовал, JLabel был только белым и вообще не исчезал.