基本上......我使用swing制作了一个JDialog。现在我希望它将一个值返回给调用它的JFrame。问题是,每当我调用JDialog的构造函数时,即使我已设置setModal(true)
,它也不会阻止该线程。我错过了一些明显的东西吗?
private final JPanel contentPanel = new JPanel();
private File chosenFile = null;
private JList list;
private File[] files;
public File getInformation()
{
return chosenFile;
}
/**
* Create the dialog.
*/
public PatientPicker(JFrame parent)
{
super(parent);
setModal(true);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setLocationRelativeTo(parent);
setBounds(100, 100, 450, 396);
getContentPane().setLayout(new BorderLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
files = new File(ClientInfo.GetAppData() + "/patients").listFiles(new TextFileFilter());
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton okButton = new JButton("OK");
okButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
if(files.length != 0)
chosenFile = files[list.getSelectedIndex()];
dispose();
}
});
okButton.setActionCommand("OK");
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("Cancel");
cancelButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
dispose();
}
});
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
}
}
}
接下来是我创建它的方式:
PatientPicker patientPicker = new PatientPicker(frmReportGenerator);
File dataFile = patientPicker.getInformation();
答案 0 :(得分:5)
你说:
问题是,每当我调用JDialog的构造函数时,即使我设置了setModal(true),它也不会阻塞线程。我错过了一些明显的东西吗?
构造函数永远不会阻塞事件线程。模态意味着只有在模态对话框中调用setVisible(true)时才会阻止事件线程(根据api)。
无关的问题:你不应该在JButtons上使用MouseListeners,而应该使用ActionListeners。否则你现在会遇到重大问题,例如当你通过空格键按下文件时,当它按下时,没有任何反应,并且在以后的代码中,例如当你禁用按钮时,它仍然是功能,即使它看起来已禁用。
现在,如果您仍然遇到问题,那么您可能希望发布更多代码minimal code example program,以便我们了解并体验您的问题。
修改
你说:
是。用户在JDialog中选择一个文件,我希望它返回到调用它的JFrame。
为什么不直接使用JFileChooser模式对话框?
编辑2
使用JOptionPane的示例:
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class SwingFoo extends JPanel {
private JTextField fileField = new JTextField(20);
private JButton showDialog = new JButton(new ShowDialogAction("Show Dialog",
KeyEvent.VK_D, this));
public SwingFoo() {
fileField.setEditable(false);
fileField.setFocusable(false);
add(new JLabel("File Selected:"));
add(fileField);
add(showDialog);
}
public void setFileFieldText(String text) {
fileField.setText(text);
}
private static void createAndShowGui() {
SwingFoo mainPanel = new SwingFoo();
JFrame frame = new JFrame("SwingFoo");
frame.setDefaultCloseOperation(JFrame.EXIT_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();
}
});
}
}
@SuppressWarnings("serial")
class ShowDialogAction extends AbstractAction {
private SwingFoo swingFoo;
public ShowDialogAction(String name, int mnemonic, SwingFoo swingFoo) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.swingFoo = swingFoo;
}
@Override
public void actionPerformed(ActionEvent e) {
PatientPicker patientPicker = new PatientPicker();
int result = JOptionPane.showConfirmDialog(swingFoo, patientPicker,
"Select Something", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
swingFoo.setFileFieldText(patientPicker.getSelectedItem());
}
patientPicker.setVisible(true);
}
}
@SuppressWarnings("serial")
class PatientPicker extends JPanel {
private static final String[] ITEMS = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Sunday", "Fubar", "Snafu", "DILLIGAF", "BOHICA"};
private JList<String> selectionList = new JList<>(ITEMS);
public PatientPicker() {
add(new JScrollPane(selectionList));
selectionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
public String getSelectedItem() {
return selectionList.getSelectedValue();
}
}
答案 1 :(得分:2)
您需要做的是,一旦用户完成与对话框的交互,假设他们点击了确定按钮,就可以向主窗口发送通知。 您可以通过创建一个匿名类并在Dialog的构造函数中传递它来完成此操作。
让我们假设您使用主窗口中名为openDialogBtn的按钮打开对话框:
openDialogBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new PatientPicker(this, new FileSelectionNotifier() {
public void okButtonPressed(File chosenFile) {
// do whatever you need to do with the file (assign to a member variable
// or call another thread to do some kind of processing
}
});
在对话框窗口中,您需要具有以下内容:
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
// notify that the ok button was pressed
fileSelectionNotifier.okButtonPressed(chosenFile);
}
}