【问题标题】:Performing action when closing JFrame关闭 JFrame 时执行操作
【发布时间】:2011-04-23 12:58:45
【问题描述】:

在我的程序中,我有一个包含一个按钮的主 JFrame。单击此按钮时,会出现一个新的 JFrame,我可以在其中更改一些信息。每当我完成编辑时,我都会按下新 JFrame 上的保存按钮,它会保存更改并处理 JFrame。现在完成此操作后,我还想在主 JFrame 中执行一个操作,但前提是某些内容发生了变化。如果我打开新的 JFrame 并再次关闭它而不使用保存按钮,我不想在主框架中做任何事情。 我已经尝试在网上搜索解决方案,但似乎没有任何用处..

到目前为止我得到的代码示例: 主框架...


public class MainFrame extends JFrame
 {
     public MainFrame()
     {
         super("Main Frame");
         JButton details = new JButton("Add Detail");
         add(details);
         details.addActionListener(new ActionListener(){
             public void actionPerformed(ActionEvent e)
             {
                 new DetailFrame().setVisible(true);
             }
         });
     }
 }

详细框架...


 public class DetailFrame extends JFrame
 {
     public DetailFrame()
     {
         super("Detail Frame");
         JButton save = new JButton("Save");
         add(save);
         save.addActionListener(new ActionListener(){
             public void actionPerformed(ActionEvent e)
             {
                 // Save whatever content
                 dispose();
             }
         });
     }
 }

所以当我点击细节框架上的“保存”按钮时,我想在主框架中做一些事情,而当点击细节框架上的“x”时,我不想做任何事情..

希望有人能够帮助我,对不起我的英语..

【问题讨论】:

    标签: java dispose jframe


    【解决方案1】:

    您可以将 MainFrame 句柄传递给 DetailFrame 构造函数。然后,在单击 Save 按钮时,DetailFrame 将调用 MainFrame 中的一个函数并将更改传递给它。

    另一种方法是在 DetailFrame 中创建一个public boolean 变量,并在单击“保存”按钮时将其设置为true。这样 MainFrame 将知道 DetailFrame 是否已关闭或已保存。

    编辑:更多想法:

    使用JDialog 而不是JFrameJDialog.setVisible 是模态的,即它会阻塞调用函数,直到对话框关闭;这样您就可以在同一个“详细信息”按钮侦听器中处理对话框的结果。

    要在调用后访问对话框,请将对话框存储在单独的变量中。先构造对话框,然后显示,然后通过分析变量来处理结果。

    将编辑结果存储在DetailFrame(或者我们称之为DetailDialog)的其他公共变量中。这应该仅在单击“保存”按钮时发生。这甚至可以允许不使用布尔变量(取决于您正在编辑的值的类型)。

    DetailDialog dlg = new DetailDialog();
    dlg.setVisible(true);
    if(dlg.approvedResult != null) {
        // process the result...
    }
    

    编辑:抱歉,JDialog 默认不是模态的。需要调用一个特殊的super 构造函数来使其成为模态。

    此外,在这里您必须将MainFrame 的引用传递给对话框构造函数,但您仍然可以将其声明为简单的JFrame 并避免不必要的依赖。

    要从匿名 ActionListener 中获取对封闭 MainFrame 的引用,请使用 MainFrame.this

    为了能够在创建按钮后更改按钮文本,您必须将按钮存储在成员变量中。

    主框架...

    public class MainFrame extends JFrame
    {
        private JButton details = new JButton("Add Detail");
    
        public MainFrame()
        {
            super("Main Frame");
            getContentPane().add(details);
            details.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e)
                {
                    DetailDialog dlg = new DetailDialog(MainFrame.this);
                    dlg.setVisible(true);
                    if(dlg.approved){
                        details.setText("Edit Detail");
                    }
                }
            });
        }
    }
    

    详细对话框...(不是框架)

    public class DetailDialog extends JDialog
    {
        public boolean approved = false;
    
        public DetailDialog(JFrame parent)
        {
            super(parent,"Detail Dialog",true);        // modal dialog parented to the calling frame
            JButton save = new JButton("Save");
            getContentPane().add(save);
            save.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e)
                {
                    // Save whatever content
                    approved = true;
                    dispose();
                }
            });
        }
    }
    

    【讨论】:

    • 我尝试了使用公共布尔值的东西,但由于某种原因,我无法从 MainFrame 访问它。我不确定将句柄传递给 DetailFrame 构造函数是什么意思?
    • 我编辑了答案,请参阅上面的更多详细信息。事实上,将MainFrame 传递给对话框并不是最好的主意,因为它在类之间添加了太多的依赖关系;使用公共变量的方法更好,因为它允许您在不同的地方使用相同的对话框。
    • 我现在尝试了上述方法,但仍然无法正常工作。在我的代码中,对话框似乎不是模态的 - 打开对话框的函数会立即执行,而不是等到对话框已关闭..
    • 终于在设置对话框可见之前调用 setModal(true) 函数让它工作了。
    • @Simon: "终于通过调用 setModal(true) 让它工作了" 这可以在构造函数中完成。顺便说一句 - 我的回复中首先提到了对话的方式。你错过了吗?
    【解决方案2】:

    使用 windowadapter 类在主框架中创建细节框架,并为其添加一个窗口侦听器。通过检查更改、处理这些更改来实现 windowclosure 事件,然后处理详细信息框架。这一切都在大型机中完成。

    细节框架应该在关闭集上不做任何事情,以防止细节框架在您记录更改之前被释放。

    您可能希望将检查细节框架中的更改作为返回包含有趣数据的类的方法。这样你的 windowlistener 就可以小而精了。

    【讨论】:

    • 我不太明白.. 我想要做的确切的事情是,将“添加详细信息”按钮的文本更改为“编辑详细信息”,但只有当一个细节是补充..你能不能给出一个你上面描述的代码示例?
    【解决方案3】:

    忘记第二个JFrame。改用模态对话框。它将阻止输入直到被解雇。一旦被解雇,唯一要做的就是决定是否更新原始数据。 JOptionPane 具有一些内置功能,可以轻松实现。如果用户按下Cancelesc键,showInputDialog()方法将返回null作为结果。

    import java.awt.BorderLayout;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.border.EmptyBorder;
    
    class EditInfo {
    
        public static void main(String[] args) {
    
            Runnable r = new Runnable() {
                public void run() {
                    final JFrame f = new JFrame("Uneditable");
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
                    JPanel p = new JPanel(new BorderLayout(10,10));
    
                    final JTextField tf = new JTextField("Hello World!", 20);
                    tf.setEnabled(false);
                    p.add(tf, BorderLayout.CENTER);
    
                    JButton edit = new JButton("Edit");
                    edit.addActionListener( new ActionListener(){
                        public void actionPerformed(ActionEvent ae) {
                            String result = JOptionPane.showInputDialog(
                                f,
                                "Edit text",
                                tf.getText());
                            if (result!=null) {
                                tf.setText(result);
                            }
                        }
                    } );
                    p.add(edit, BorderLayout.EAST);
    
                    p.setBorder(new EmptyBorder(10,10,10,10));
    
                    f.setContentPane(p);
                    f.pack();
                    f.setLocationByPlatform(true);
                    f.setVisible(true);
                }
            };
            SwingUtilities.invokeLater(r);
        }
    }
    

    如果需要同时编辑JOptionPane 中的多个字段,请使用JPanel 将它们全部包含在内,然后将它们放入showMessageDialog() 调用中。检查基于整数的返回结果以确定用户是否同意更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-10
      • 2012-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多