我有两个类,一个扩展JPanel并实现Runnable的主类和类。我试图在actionListener中为同一个JPanel类实例创建两个线程,但我不知道在哪里创建JPanel1对象......
//编辑:Button1是应用程序的开始。之后,按钮2将显示标签的快速动画,单击它时(按钮2)也将启动相同的动画。如果单击其中一个按钮启动运行方法,我该怎么办?
public void run() {
if(isTom){
repaint();
revalidate();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
panel.removeAll();
panel.add(tomLabel1);
repaint();
revalidate();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
panel.add(tomLabel2);
repaint();
revalidate();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
panel.add(tomLabel3);
repaint();
revalidate();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
panel.add(tomLabel4);
repaint();
revalidate();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
panel.add(tomLabel5);
repaint();
revalidate();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
panel.removeAll();
repaint();
revalidate();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
public Game(){
JFrame frame = new JFrame();
Panel1 key = new Panel1();
key.addKeyListener(key);
frame.add(key);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(true);
frame.setVisible(true);
}
public static void main(String[] args) {
new Game();
}
public class Panel1 extends JPanel implements KeyListener,Runnable{
JButton button1 = new JButton("BUTTON1");
JButton button2 = new JButton("BUTTON2");
add(button1);add(button2);
Thread t = new Thread(this); // This works, but i need it inside the actionListener.
button1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("button1");
Thread x = new Thread(j);//'j' is an JPanel1 object. I need something like this i guess
x.setName("Thread x");});
button2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("button2");
Thread y = new Thread(j);
y.setName("Thread y");
});
public void run(){
System.out.println(Thread.currentThread().getName());
}
答案 0 :(得分:1)
首先,Swing不是线程安全的!这意味着您永远不应该从Event Dispatching Thread的上下文之外创建或修改UI!
其次,Swing是一个单线程环境,这意味着你永远不应该在Event Dispatching Thread的上下文中阻塞或执行长时间运行的代码,这将导致UI冻结,直到删除该块。
你的概念是正确的,你的实现是错误的,你应该使用Swing Timer
代替。
使用单个标签并更改其属性(文本/图标,无论如何),而不是删除和添加标签
有关详细信息,请参阅Concurrency in Swing和How to use Swing Timers
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
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 Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
try {
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
private JButton button1;
private JButton button2;
private SplashScreen splashScreen;
public TestPane() throws IOException {
button1 = new JButton("Button One");
button2 = new JButton("Button Two");
JPanel buttons = new JPanel();
buttons.add(button1);
buttons.add(button2);
button1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
splashScreen.run();
}
});
button2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
splashScreen.run();
}
});
splashScreen = new SplashScreen();
setLayout(new BorderLayout());
add(splashScreen);
add(buttons, BorderLayout.SOUTH);
}
}
public static class SplashScreen extends JPanel {
protected static final int IMAGE_COUNT = 4;
private JLabel label;
private Timer timer;
private int delta;
private int count;
private Icon[] icons;
private Dimension preferredSize;
public SplashScreen() throws IOException {
String path = "/images/splash";
String ext = ".png";
icons = new Icon[IMAGE_COUNT];
int maxWidth = 0;
int maxHeight = 0;
for (int index = 0; index < IMAGE_COUNT; index++) {
String name = path + (index + 1) + ext;
System.out.println(name);
icons[index] = new ImageIcon(ImageIO.read(getClass().getResource(name)));
maxWidth = Math.max(maxWidth, icons[index].getIconWidth());
maxHeight = Math.max(maxHeight, icons[index].getIconHeight());
}
preferredSize = new Dimension(maxWidth, maxHeight);
timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (count >= IMAGE_COUNT) {
count = IMAGE_COUNT - 2;
delta = -1;
} else if (count < 0) {
((Timer)e.getSource()).stop();
} else {
label.setIcon(icons[count]);
count += delta;
}
}
});
setLayout(new BorderLayout());
label = new JLabel();
add(label);
}
@Override
public Dimension getPreferredSize() {
return preferredSize;
}
public void run() {
if (!timer.isRunning()) {
delta = 1;
count = 0;
timer.start();
}
}
}
}
答案 1 :(得分:0)
使用Panel1类实例创建一个新的Thread实例:
button1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("button1");
Thread x = new Thread(Panel1.this);
x.start();
x.setName("Thread x");});
使用新的Thread对象重复另一个按钮:
button2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("button2");
Thread y = new Thread(Panel1.this);
y.start();
y.setName("Thread y"); });
Panel1.this指的是当前正在运行的Panel1类的实例,确保你的Threads正在执行该实例的run()。