gpt4 book ai didi

java - Swing 中的同步

转载 作者:行者123 更新时间:2023-11-30 06:15:41 24 4
gpt4 key购买 nike

有什么方法可以使事件调度线程与 swing.TimerSwingWorkernew Thread() 创建的另一个线程同步?我希望 EDT 等待另一个线程工作(例如在屏幕上移动对象)并在完成此工作后立即执行一些任务。是否可以?我必须使用另一个线程,因为如果我尝试在 EDT 中更改对象的坐标,我在屏幕上看不到运动。

最佳答案

您不想在 EDT 上同步或让它加入其他线程,因为这可能会卡住您的程序。最好的办法可能是使用监听器类型的结构来通知 Swing 代码后台线程已完成,例如可以通过将 PropertyChangeListener 添加到 SwingWorker 并监听“state”属性更改为 SwingWorker.StateValue.DONE。如果您确实使用了它,请务必在您的 PropertyChangeListener 中调用您的 SwingWorker 上的 get() 以捕获所有可能已发生的异常从后台线程中抛出。

For example


编辑
您在评论中声明:

But I'll try to explain. User presses the button. I want some JPanel object to continuously move to another place on screen as a result of button press. This movement will take about 0.4 seconds and I really don't want any button to respond during this time. Movement is provided by coordinates change + Thread.sleep(5). Seems it's impossible to realize this movement in Event Dispatch Thread. Am I right?

  1. 是的,如果您使用 Swing Timer,则很有可能在 EDT 上进行运动。 Swing 计时器使用后台线程在幕后 重复调用其 ActionListener 的 actionPerformed 方法,但有延迟。使用它的关键是它的 actionPerformed 方法中的所有代码都在 EDT 上调用。
  2. 如果您想停用按钮,则通过调用 setEnabled(false) 将按钮设置为禁用 1(或更好,它是 Action)。动画完成后撤消此操作。

例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.*;

public class MoveBall extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = PREF_W;
private static final int BALL_W = 40;
private static final int BALL_H = BALL_W;
private static final Color BALL_COLOR = Color.red;
public static final int TIMER_DELAY = 20;
private int ballX = BALL_W / 2;
private int ballY = BALL_H / 2;
private BufferedImage ballImg;
private ButtonAction buttonAction = new ButtonAction("Start Animation");
private Timer timer;

public MoveBall() {
ballImg = new BufferedImage(BALL_W, BALL_H, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = ballImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(BALL_COLOR);
g2.fillOval(1, 1, BALL_W - 2, BALL_H - 2);
g2.dispose();

add(new JButton(buttonAction));
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (ballImg != null) {
int x = ballX - BALL_W / 2;
int y = ballY - BALL_H / 2;
g.drawImage(ballImg, x, y, null);
}
}

@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}

private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name);
int mnemonic = (int)name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}

@Override
public void actionPerformed(ActionEvent e) {
ballX = BALL_W / 2;
ballY = BALL_H / 2;
repaint();
setEnabled(false);
new Timer(TIMER_DELAY, new TimerListener()).start();
}
}

private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (ballX + BALL_W / 2 >= getWidth()) {
stopBall(e);
} else if (ballY + BALL_H / 2 >= getHeight()) {
stopBall(e);
} else {
ballX++;
ballY++;
}
repaint();
}

private void stopBall(ActionEvent e) {
buttonAction.setEnabled(true);
((Timer) e.getSource()).stop();
}
}

private static void createAndShowGui() {
MoveBall mainPanel = new MoveBall();

JFrame frame = new JFrame("MoveBall");
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();
}
});
}
}

关于java - Swing 中的同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28400047/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com