Java JLayeredPane内容在刷新时闪烁



我在NetBeans中有一个项目,它使用分层窗格来显示重叠的面板,根据需要在它们之间切换。启动后,程序在其中一个面板上显示介绍动画(在单独的线程上运行),通过以下方式实现:

public class IntroPanel extends javax.swing.JPanel implements Runnable {
private boolean finished;
private int opacity;
private JLabel[] labels = new JLabel[3];
public IntroPanel() {
initComponents();
labels[0] = jLabel1;
labels[1] = jLabel2;
labels[2] = jLabel3;
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
for(JLabel label : labels)
label.setForeground(new Color(200,200,200,opacity));
}
@Override
public void run(){
while (!finished) {            
while (opacity < 255) {
try {
Thread.sleep(30);
opacity += 5;
repaint();
} catch (InterruptedException ex) {
Logger.getLogger(IntroPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
repaint();
Thread.sleep(3000);
} catch (InterruptedException ex) {
Logger.getLogger(IntroPanel.class.getName()).log(Level.SEVERE, null, ex);
}
while (opacity > 0) {
try {
Thread.sleep(30);
opacity -= 5;
repaint();
} catch (InterruptedException ex) {
Logger.getLogger(IntroPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
Logger.getLogger(IntroPanel.class.getName()).log(Level.SEVERE, null, ex);
}
finished = true;
}
}

预期效果是让三个JLabel淡出,在屏幕上停留片刻,然后淡出。前两个标签包含大字体的斜体文本,第三个标签包含小字体。这里的问题:

  1. 前两个标签的文本在淡入或淡出时显示为非斜体,在标签不淡入时仅短暂变为斜体
  2. 第三个标签(小字,非斜体)根本不会褪色,而是在重新绘制循环中快速上下"摇晃">

我读到关于如何更好地编写自己的活动渲染方法,而不是使用paintComponent(),而是用以下内容替换paintComponent:

public void render() {
Graphics g = getGraphics();
for(JLabel label : labels)
label.setForeground(new Color(200,200,200,opacity));
g.dispose();
}

做同样的闪烁。我是不是在这里遗漏了什么,还是循环重新绘制和分层框架无法混合?

  1. 您不应该在该方法内部的paintComponent中执行任何代码。这应该在你项目的另一个区域。paintComponent仅用于绘制,不用于设置状态
  2. while循环应该被Swing Timer取代,这就是setForround调用应该去的地方
  3. 您应该发布一个最小的、完全有效的示例,一个我们可以编译、运行和测试的小程序。您的代码不允许这样做

例如:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class IntroPanel extends JPanel {
private static final int DELAY_TIME = 5;
protected static final Color FG_COLOR = Color.blue;
private List<JLabel> labelList = new ArrayList<JLabel>();
private List<Color> colorList = new ArrayList<>();
public IntroPanel() {
for (int i = 0; i < 255; i++) {
colorList.add(new Color(0, 0, 255, i));
}
for (int i = 0; i < 255; i++) {
colorList.add(new Color(0, 0, 255, 255 - i));
}
setLayout(new GridLayout(0, 1));
JLabel label1 = new JLabel("Label 1");
label1.setFont(label1.getFont().deriveFont(Font.ITALIC, 24));
add(label1);
labelList.add(label1);
JLabel label2 = new JLabel("Label 2");
label2.setFont(label2.getFont().deriveFont(Font.ITALIC, 24));
add(label2);
labelList.add(label2);
JLabel label3 = new JLabel("Label 3");
label3.setFont(label3.getFont().deriveFont(Font.PLAIN, 10));
add(label3);
labelList.add(label3);
new Timer(DELAY_TIME, new ActionListener() {
private int index = 0;
@Override
public void actionPerformed(ActionEvent evt) {
if (index < colorList.size()) {
for (JLabel label : labelList) {
label.setForeground(colorList.get(index));
}
index++;
} else {
((Timer)evt.getSource()).stop();
}
}
}).start();
}
private static void createAndShowGUI() {
IntroPanel paintEg = new IntroPanel();
JFrame frame = new JFrame("IntroPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(paintEg);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

最新更新