以下代码将向JFrame添加3个JLabel,然后删除3个JLabel。 2秒后,它将重新绘制3个JLabel。
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class RepaintFrameTest extends JFrame {
private JPanel panel = new JPanel();
private JLabel labelOne = new JLabel("label1");
private JLabel labelTwo = new JLabel("label2");
private JLabel labelThree = new JLabel("label3");
public RepaintFrameTest() {
panel.add(labelOne);
panel.add(labelTwo);
panel.add(labelThree);
add(panel);
pack();
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(1024,768);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String args[]) {
RepaintFrameTest frameOne = new RepaintFrameTest();
frameOne.getContentPane().removeAll();
frameOne.getContentPane().validate();
frameOne.getContentPane().repaint();
new Thread(new RepaintThread()).start();
}
}
class RepaintThread implements Runnable {
@Override
public void run() {
try {
Thread.sleep(2000);
}catch (InterruptedException interruptedException) {
System.out.println( "Thread is interrupted when it is sleeping" +interruptedException);
}
RepaintFrameTest frameTwo = new RepaintFrameTest();
frameTwo.getContentPane().validate();
frameTwo.getContentPane().repaint();
}
}
我遇到的一个小问题是它重新绘制到新帧(frameTwo)而不是旧帧(frameOne)。
如何制作它以重新绘制现有框架而不是重新绘制新框架?
答案 0 :(得分:3)
add(new JLabel(), BLANK_COMPONENT);
next()
,传入主要的CardLayout-using组件:cardLayout.next(myMainJPanel);
例如,
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;
public class RepaintTest extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final int LABEL_COUNT = 3;
private static final String LABEL_PANEL = "label panel";
private static final Object BLANK_COMPONENT = "blank component";
private static final int TIMER_DELAY = 2000;
private CardLayout cardLayout = new CardLayout();
public RepaintTest() {
JPanel labelPanel = new JPanel();
for (int i = 0; i < LABEL_COUNT; i++) {
labelPanel.add(new JLabel("Label " + (i + 1)));
}
setLayout(cardLayout);
add(labelPanel, LABEL_PANEL);
add(new JLabel(), BLANK_COMPONENT);
new Timer(TIMER_DELAY, new TimerListener()).start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.next(RepaintTest.this);
}
}
private static void createAndShowGui() {
RepaintTest mainPanel = new RepaintTest();
JFrame frame = new JFrame("RepaintTest");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
答案 1 :(得分:2)
您违反了Swing的单线程规则......
有关详细信息,请参阅Concurrency in Swing。
基本上,您不应该从事件调度线程以外的任何线程上下文更新任何UI组件。
相反,您应该使用SwingWorker
,或者可能更适合您的问题javax.swing.Timer
问题是,正如您已经清楚注意到的那样,frameTwo
的引用与frameOne
的引用无关,它们是完全独立的对象,因此每个引用都没有任何共同点。其他
您需要做的是将您想要更新的对象的某种引用传递给进行更新的类......
在此示例中,我只是在reapplyLabels
中创建了RepaintFrameTest
方法,并使用Swing Timer
设置为2秒延迟,以调用此方法...
就个人而言,我更倾向于传递一个interface
,因为它暴露较少并且解耦代码,但这只是一个简单的例子......
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RepaintFrameTest extends JFrame {
private JPanel panel = new JPanel();
private JLabel labelOne = new JLabel("label1");
private JLabel labelTwo = new JLabel("label2");
private JLabel labelThree = new JLabel("label3");
public RepaintFrameTest() {
add(panel);
}
public void reapplyLabels() {
panel.add(labelOne);
panel.add(labelTwo);
panel.add(labelThree);
revalidate();
repaint();
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
RepaintFrameTest frame = new RepaintFrameTest();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer timer = new Timer(2000, new RepaintAction(frame));
timer.setRepeats(false);
timer.start();
}
});
}
public static class RepaintAction implements ActionListener {
private RepaintFrameTest frame;
public RepaintAction(RepaintFrameTest frame) {
this.frame = frame;
}
@Override
public void actionPerformed(ActionEvent e) {
frame.reapplyLabels();
}
}
}
虽然没有足够的背景来进行完整的judement调用,但我也同意HovercraftFullOfEels,CardLayout
会达到相同的结果,可能会减少混乱......