我正在使用JFrame,我希望显示图像并暂停代码,直到用户按下任意键。按下该键后,图像将关闭,代码将继续运行。
我做了什么:
创建了一个标志
final boolean[] flag = {true};
在JFrame对象中添加了一个addKeyListener,用于更改标志
frame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
frame.setVisible(false);
frame.dispose();
flag[0] = false;
}
});
等待循环直到标记为
while (flag[0]){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
这是有效的,但我知道它有点资源。
还有其他方法可以进行等待循环吗?是否有听众的倾听者?
第二次尝试,使用 CountDownLatch :
设置闩锁
final CountDownLatch latch = new CountDownLatch(1);
倒计时 for(JFrame frame:framesList){
frame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
frame.setVisible(false);
frame.dispose();
latch.countDown();
}
});
等待
latch.await();
答案 0 :(得分:2)
因此,您希望显示图像并在窗口关闭之前停止执行。这只是尖叫模态对话给我。模态对话框将停止代码执行从可见的位置开始,它将在此处执行,以便不阻止事件调度线程并使整个问题停止尖叫并挂起程序。有关详细信息,请参阅How to use dialogs
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Image;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
BufferedImage img = ImageIO.read(...);
ImageShower.show(null, img);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public static class ImageShower extends JPanel {
private JLabel label = new JLabel();
public ImageShower() {
setLayout(new BorderLayout());
add(label);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "close");
am.put("close", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
Window window = SwingUtilities.windowForComponent(ImageShower.this);
if (window != null) {
window.dispose();
}
}
});
}
public void setImage(Image img) {
label.setIcon(new ImageIcon(img));
}
public static void show(Component owner, Image img) {
Window parent = null;
if (owner != null) {
parent = SwingUtilities.windowForComponent(owner);
}
JButton close = new JButton("Close");
close.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton) e.getSource();
Window window = SwingUtilities.windowForComponent(btn);
if (window != null) {
window.dispose();
}
}
});
JDialog dialog = new JDialog(parent, Dialog.ModalityType.APPLICATION_MODAL);
ImageShower shower = new ImageShower();
shower.setImage(img);
dialog.add(shower);
dialog.add(close, BorderLayout.SOUTH);
dialog.getRootPane().setDefaultButton(close);
dialog.pack();
dialog.setLocationRelativeTo(owner);
dialog.setVisible(true);
}
}
}
"但是等等,可能图片很大,需要时间加载,我不想在加载时冻结用户界面 ......
好的,为此,我希望使用SwingWorker
,它可以在后台加载图像,但提供了简单的方法来确保图像在EDT的上下文中正确显示...
public class ImageLoadAndShow extends SwingWorker<Void, Image> {
@Override
protected Void doInBackground() throws Exception {
BufferedImage img = ImageIO.read(...);
publish(img);
return null;
}
@Override
protected void process(List<Image> chunks) {
Image img = chunks.get(chunks.size() - 1);
ImageShower.show(null, img);
}
}
不是,如果图片无法加载,您就不会知道它,因为doInBackground
方法会将Exception
传递出方法。您需要使用PropertyChangeListener
和SwingWorker
get
方法的组合来捕获它,只需记住,get
是阻塞的,所以在里面调用它EDT的上下文将一直阻止,直到工人完成
&#34;但是当对话框关闭时我需要执行其他操作&#34;
有几种方法可以实现这一点,具体取决于您想要做什么,对于此示例,我已经坚持使用SwingWorker
,因为它很容易复制并粘贴基本结构,但您可以使用Runnable
Thread
public class ImageLoadShowAndWait extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() throws Exception {
BufferedImage img = ImageIO.read(...);
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
ImageShower.show(null, img);
}
});
return null;
}
}
现在,如果这些都不符合您的要求......那么我想知道您实际在做什么:P,看看Foxtrot提供了一个API,它允许您在EDT中异步执行代码而不会阻塞它(整齐地),但这将阻止代码执行,直到它完成为止
问题是我希望它在按下任意键时关闭JFrame
KeyListener
会给你一些问题,也许不是今天,也许不是明天,但它最终会在你面前爆发。我提供的示例绑定 Escape 键来处置窗口。它也使得&#34;关闭&#34;按下默认按钮,它提供 Space 和/或 Enter 键以及一个很好的可视队列给用户。
如果您想使用KeyListener
,这取决于您,但您的核心问题似乎并未围绕它展开,而是能够显示窗口并暂停代码执行直到它关闭