Java JFrame在单独的类中,ActionListener呢?

Java JFrame在单独的类中,ActionListener呢?,java,swing,actionlistener,Java,Swing,Actionlistener,我试图将Swing GUI与实际代码分离。简而言之,我希望用户启动一个流程(基于用户的选择);在这种情况下,将不再需要JFrame 我不明白的是如何将用户从GUI.class中选择的内容与Main.class共享 你对我有什么建议吗 这是我的密码: public class Main { public static void main(String[] args) { // Show GUI java.awt.EventQueue.invokeLater(new Runnab

我试图将Swing GUI与实际代码分离。简而言之,我希望用户启动一个流程(基于用户的选择);在这种情况下,将不再需要JFrame

我不明白的是如何将用户从GUI.class中选择的内容与Main.class共享

你对我有什么建议吗

这是我的密码:

public class Main {
  public static void main(String[] args) {
    // Show GUI
    java.awt.EventQueue.invokeLater(new Runnable() {
      public void run() {
        GUI gui = new GUI(templates);
        gui.setVisible(true);
      }
    });

    // Kick off a process based on the user's selection
  }
}

public class GUI extends JFrame {
  private static final long serialVersionUID = 1L;

  public GUI(Object[] objects) {
    setTitle("GUI");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 350, 100);
    setLocationRelativeTo(null);

    JPanel cp = new JPanel();
    cp.setBorder(new EmptyBorder(10, 10, 10, 10));
    setContentPane(cp);

    JLabel lbl = new JLabel("Selection:");
    cp.add(lbl);

    final JComboBox<String> comboBox = new JComboBox<String>(new String[] { "One", "Two", "Three" });
    comboBox.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        setVisible(false);
        dispose();
        // Share the selected item with Main.class
      }
    });
    cp.add(comboBox);
  }
}
公共类主{
公共静态void main(字符串[]args){
//显示图形用户界面
invokeLater(new Runnable()){
公开募捐{
GUI=新GUI(模板);
setVisible(true);
}
});
//根据用户的选择启动流程
}
}
公共类GUI扩展JFrame{
私有静态最终长serialVersionUID=1L;
公共GUI(对象[]对象){
setTitle(“GUI”);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
立根(100100350100);
setLocationRelativeTo(空);
JPanel cp=新的JPanel();
cp.setboorder(新的空订单(10,10,10,10));
setContentPane(cp);
JLabel lbl=新的JLabel(“选择:”);
cp.add(lbl);
最终JComboBox组合框=新的JComboBox(新字符串[]{“一”、“二”、“三”});
comboBox.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
setVisible(假);
处置();
//与Main.class共享所选项目
}
});
cp.add(组合框);
}
}

您可以创建一个对象来存储选择结果,并将其传递给GUI类的构造函数。在关闭UI之前,在该对象中设置选择结果,然后您的主类可以访问该值:

public class SelectionResult {
    private String selectionResult;

    public void setSelectionResult(final String selectionResult) {
        this.selectionResult = selectionResult;
    }

    public String getSelectionResult() {
        return this.selectionResult;
    }
}
然后,您可以这样修改GUI构造函数:

private final SelectionResult selectionResult;

public GUI(Object[] objects, SelectionResult selectionResult) {
    this.selectionResult = selectionResult;
    ...
在主类中创建SelectionResult对象,并将其传递给GUI类的构造函数。在GUI类ActionListener中,可以使用所选值调用setSelectionResult()方法,该值将从主类中可用


在等待在UI中设置值时,需要添加代码使主方法等待,然后根据选择继续执行逻辑。

这样做的一个好方法是使用
回调
机制

要遵循的步骤:

  • 创建一个回调接口

    interface Callback {
        void execute(Object result);
    }
    
  • GUI
    类将实现
    回调
    接口,但不提供任何实现

  • 制作
    GUI
    class
    abstract

    abstract class GUI extends JFrame implements Callback
    
  • 现在创建一个
    GUI
    类的对象,提供
    回调
    接口的实际实现

  • 在这里您可以使用匿名类

    GUI gui = new GUI() {
    
        @Override
        public void execute(Object result) {
            System.out.println("You have selected " + result);
        }
    
    };
    
  • 您可以在
    回调的
    execute()
    方法中传递任何内容

    comboBox.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            setVisible(false);
            dispose();
            // Share the selected item with Main.class
            // Callback
            execute(comboBox.getSelectedItem());
        }
    });
    
这里,
Main
类负责捕获
GUI
类指示的
Callback
的响应


代码如下:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Main {
    public static void main(String[] args) {
        // Show GUI
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                GUI gui = new GUI() {

                    @Override
                    public void execute(Object result) {
                        System.out.println("You have selected " + result);
                    }

                };
                gui.setVisible(true);
            }
        });

        // Kick off a process based on the user's selection
    }
}

interface Callback {
    void execute(Object result);
}

abstract class GUI extends JFrame implements Callback {
    private static final long serialVersionUID = 1L;

    public GUI() {
        setTitle("GUI");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 350, 100);
        setLocationRelativeTo(null);

        JPanel cp = new JPanel();
        cp.setBorder(new EmptyBorder(10, 10, 10, 10));
        setContentPane(cp);

        JLabel lbl = new JLabel("Selection:");
        cp.add(lbl);

        final JComboBox comboBox = new JComboBox(new String[] { "One", "Two", "Three" });
        comboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setVisible(false);
                dispose();
                // Share the selected item with Main.class
                execute(comboBox.getSelectedItem());
            }
        });
        cp.add(comboBox);
    }

}

保持框架;用.Djomrton更改内容,非常感谢!事实上,我没有考虑过传递一个物体!但是,让主要方法等待的好方法是什么?有什么比while(true){if(gui==null){break;}}}更合适的吗?您可以使用信号量,并将其作为构造函数参数传递:信号量信号量=新信号量(0);设置选择结果后,在GUI类中对其调用.release()方法,并在希望等待的主方法中对其调用.aquire()方法。非常感谢您的精彩解释!这确实为我提供了一个新的视角。我可以扩展我的问题吗?同样来自设计模式Perspektive:如果我想根据用户的选择进行一些计算并动态更新GUI,我的第一个想法是简单地嵌套另一个计算对象并使GUI对象保持静态(以便计算对象可以访问GUI对象)。你有什么建议吗?除非我完全理解你的代码,否则我不能说。尽量用最小的修改来编写代码,以避免回归。显然,您指的是我的评论的早期版本。我想要避免的(尽管回归可能是错误的术语)是:public void run(){gui=new gui(){(a)Override public void execute(对象结果){Calculations calc=new Calculations(结果){(a)Override public void execute(对象结果){gui.update(结果)}是的,有很多方法可以做到这一点。如果整个应用程序中只有一个
GUI
实例,那么您可以将其设置为静态。我认为
计算
也可以被视为实用程序类,因此您可以在其中定义静态方法。为什么要为
计算
实现
回调
接口?当源收到来自目标的更改通知时,请使用
回调