Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何避免嵌套ActionListener?_Java_Swing_User Interface - Fatal编程技术网

Java 如何避免嵌套ActionListener?

Java 如何避免嵌套ActionListener?,java,swing,user-interface,Java,Swing,User Interface,在我的程序中,我希望用户: 自行选择/打开数据库(如Access) 从数据库中选择一个表 从表中选择列 在我的代码中,我有一个类可以执行以下操作: mntmOpenDatabase.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { //open the database //display tables as buttons

在我的程序中,我希望用户:

  • 自行选择/打开数据库(如Access)
  • 从数据库中选择一个表
  • 从表中选择列
  • 在我的代码中,我有一个类可以执行以下操作:

    mntmOpenDatabase.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            //open the database
            //display tables as buttons
            tableButton.addActionListener(new ActionListener() { // select a table
                public void actionPerformed(ActionEvent e) {
                    //display the columns of the table selected as buttons
                        colButton.addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {// add to the list of columns to be exported }
    
    public class OpenDataBaseListener implements ActionListener{
            @Override
            public void actionPerformed(ActionEvent e){
                   //your event handling here
            }
    }
    
    public class TableButtonListener implements  ActionListener{
            @Override
            public void actionPerformed(ActionEvent e){
                //your logic   
            }
    }
    

    这会产生一大块代码。有更干净、更简单的方法吗?

    解决方案是重构:

    • 为代码创建一个单独且可单独测试的类以打开数据库
    • 以及用于显示此数据的单独且可单独测试的类
    • 在ActionListener中,创建这些类的实例,或者与它们交互(如果它们已经存在)
    • 学习M-V-C(模型视图控制)设计模式的基本原理,并使用它们。你不必屈从于它们,上帝知道它们有很多变体,但它们的总体指导原则至少应该得到尊重
    • 努力使您的GUI或视图尽可能地变得愚蠢。它知道如何显示其数据,它有允许控件更新其显示的设施,并且它知道当用户与控件交互时如何通知控件,这就是它
    • 侧面建议1:确保所有数据库交互都在后台线程中完成
    • 附带建议2:确保几乎所有Swing交互都是在Swing EDT(事件调度线程)上完成的
    请看这个类似但更完整的问题和答案:。答案是最好的,我希望我能给他们投上无数次的票

    例如,上面的代码可以简单到:

    mntmOpenDatabase.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            control.openDatabase();
        }
    }
    

    在您的示例中,您将在每个ActionEvent上实例化并添加新的侦听器。实际上,您应该配置它一次。大概是这样的:

    mntmOpenDatabase.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            //open the database
            //display tables as buttons
            tableButton.addActionListener(new ActionListener() { // select a table
                public void actionPerformed(ActionEvent e) {
                    //display the columns of the table selected as buttons
                        colButton.addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {// add to the list of columns to be exported }
    
    public class OpenDataBaseListener implements ActionListener{
            @Override
            public void actionPerformed(ActionEvent e){
                   //your event handling here
            }
    }
    
    public class TableButtonListener implements  ActionListener{
            @Override
            public void actionPerformed(ActionEvent e){
                //your logic   
            }
    }
    
    等等

    当您创建侦听器时,您应该注册一次:

    mntmOpenDatabase.addActionListener(new OpenDataBaseListener());
    tableButton.addActionListener(new TableButtonListener());
    colButton.addActionListener(new ColButtonListener());
    

    所以我最后做了一些关于MVC的研究。我想我已经有了基本的想法,但是我仍然在想,我应该把ActionListeners放在哪里?在控制器内部还是视图内部?关于这一点似乎有不同的看法。@ForeverLearning:那是因为两者都可以很好地工作。在我看来,如果ActionListener在视图中,那么它们非常简单,它们所做的只是调用一个等价的控制方法,如我上面所示。否则,您可以将控件注入到视图中。听起来不错。我想我会试试的。但是,创建一个包含所有动作侦听器的动作类是一个好主意,还是将它们与组件放在同一个类中就可以了?