Java模式对话框不会阻止代码执行

时间:2014-06-29 02:52:24

标签: java swing jdialog

基本上......我使用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();

2 个答案:

答案 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); 
        }
}