当exdending GUI表单时,JButton无法启用

时间:2016-09-21 20:09:58

标签: java swing

我有四个小班:一个从JFrame延伸并具有GUI形式,第二个 - 从他延伸并包含按钮工作逻辑。第三类调用第二类方法,第二类 - 调用他:))。我在第二类第二种方法中的问题:按钮无法启用!我点击 - 它已禁用,但是,在调用方法enableButton时 - 什么都没做!

头等舱:

public class ClassParent extends JFrame {
    protected JButton button;
    private JPanel mainJPanel;

    public ClassParent() {
        super("Window");

        setContentPane(mainJPanel);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    public void showWindow() {
        setVisible(true);
    } 
}

第二课:

public class ClassChildren extends ClassParent {
    private CallerClass callerClass;

    public ClassChildren(CallerClass callerClass) {
        super();
        this.callerClass = callerClass;
        callerClass.setClassChildren(this);

        button.addActionListener(a -> {
            callerClass.callMe();
            button.setEnabled(false);
        });
    }

    public void enableButton() {
        button.setEnabled(true);
    }
}

第三课:

public class CallerClass {
    private ClassChildren classChildren;

    public void setClassChildren(ClassChildren classChildren) {
        this.classChildren = classChildren;
    }

    public void callMe() {
        classChildren.enableButton();
    }
}

主要课程:

public class Main {
    public static void main(String[] args) {
        new ClassChildren(new CallerClass()).showWindow();
    }
}

和GUI表格照片(我找不到代码,除了在记事本中打开它)):

enter image description here

为什么会发生这种情况以及如何解决?

2 个答案:

答案 0 :(得分:1)

显然OP已经解决了他的问题,但我认为这是一个有趣且常见的问题,因此我已经创建了Minimal, Complete and Verifiable Example我推荐的方法,以供将来参考。< / p>

您可以在下方查看,也可以从the GitHub repository获取完整的项目。

(欢迎提出评论,建议,修改和反馈!)

主要JFrame:

/**
 * @author Rodrigo Legendre Lima Rodrigues (AKA ArchR / AlmightyR)
 * <rodrigolegendre.developer@gmail.com>
 */
public class Main extends javax.swing.JFrame {

    /**
     * A public method so we can enable/disable state from outside the class
     * (while keeping the components encapsulated).
     *
     * @param enabled The input state the components should assume.
     */
    public void setInputState(boolean enabled) {
        this.startProcessButton.setEnabled(enabled);
    }

    /**
     * Creates new form Main
     */
    public Main() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        startProcessButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Primary Frame");

        startProcessButton.setText("Process");
        startProcessButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startProcessButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(startProcessButton, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(startProcessButton)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    @SuppressWarnings("Convert2Lambda")
    private void startProcessButtonActionPerformed(java.awt.event.ActionEvent evt) {                                                   
        //We need a non-annonymous reference for this frame to use within our annonymous 'run()'.
        Main main = this;

        //Here is were we disable input for (the components of) this frame before running the secondary frame.
        this.setInputState(false);

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Secondary(main).setVisible(true);
            }
        });
    }                                                  

    /**
     * @param args the command line arguments
     */
    @SuppressWarnings("Convert2Lambda")
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton startProcessButton;
    // End of variables declaration                   
}

辅助JFrame:

/**
 *
 * @author Rodrigo Legendre Lima Rodrigues (AKA ArchR)
 * <rodrigolegendre.developer@gmail.com>
 */
public class Secondary extends javax.swing.JFrame {

    /**
     * A variable to hold a reference to the main frame. We need this to enable
     * the input of main again after this frame's work is done.
     */
    private Main main;

    /**
     * A self-reference to this frame. We need this to hide the frame from
     * within the worker, after it's job is done.
     */
    private Secondary secondary;

    /**
     * A SwingWorker executes a process without interfering with the UI's
     * execution, which could otherwise cause delays or complete "locking" of
     * the visual and input processes.
     */
    SwingWorker<Integer, Integer> swingWorker = new SwingWorker<Integer, Integer>() {
        @Override
        @SuppressWarnings("SleepWhileInLoop")
        protected Integer doInBackground() throws Exception {
            //Execute the process...
            for (int i = 0; i <= 100; i++) {
                progressBar.setValue(i);
                Thread.sleep(100);
            }

            //We handle reactivating the main frame's inputs on the closing event,
            //to make sure they get enabled after this frame is closed,
            //regardless of sucess, cancelation or failure.

            //We close and dispose of the secondary frame.
            //Note: We have set default close behavior for this frame to be disposing, so we simply send it a closing event.
            secondary.dispatchEvent(new WindowEvent(secondary, WindowEvent.WINDOW_CLOSING));

            //Alternatively:
            //main.setInputState(true);
            //secondary.setVisible(false);
            //secondary.dispose();

            return 100;
        }
    };

    /**
     * In order to start the process while keeping all related code contained
     * within this class, we make it listen to it's own WindowOpened event.
     *
     * In order to avoid calling an overridable method ('addListener()') from
     * the constructor, which could be "forgotten" on extensions, we create a
     * private method to initialize all self-listeners.
     */
    private void initSelfListeners() {
        WindowListener taskStarterWindowListener = new WindowListener() {
            @Override
            public void windowOpened(WindowEvent e) {
                //This starts the process when the window opens.
                System.out.println("Performing task...");
                swingWorker.execute();
            }

            //<editor-fold defaultstate="collapsed" desc="UNUSED EVENTS/METHODS">
            @Override
            public void windowClosing(WindowEvent e) {
                //Do nothing.
            }

            @Override
            public void windowClosed(WindowEvent e) {
                //Do nothing.
            }

            @Override
            public void windowIconified(WindowEvent e) {
                //Do nothing.
            }

            @Override
            public void windowDeiconified(WindowEvent e) {
                //Do nothing.
            }

            @Override
            public void windowActivated(WindowEvent e) {
                //Do nothing.
            }

            @Override
            public void windowDeactivated(WindowEvent e) {
                //Do nothing.
            }
//</editor-fold>
        };

        //Here is where the magic happens. We make (a listener within) the frame start listening to the frame's own WindowOpened event.
        this.addWindowListener(taskStarterWindowListener);
    }

    /**
     * Creates new form Secondary
     */
    @SuppressWarnings("LeakingThisInConstructor")
    private Secondary() {
        initComponents();
        initSelfListeners();
        this.secondary = this;
    }

    public Secondary(Main main) {
        this();
        this.main = main;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        processingLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Secondary Frame");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        processingLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        processingLabel.setText("Processing...");

        progressBar.setStringPainted(true);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(processingLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(processingLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    private void formWindowClosing(java.awt.event.WindowEvent evt) {                                   
        //When the window is closed, we enable the input in the main frame again.
        //This is advantageous as it handles most cases in one go...
        //The cases were the window closes after the process is complete,
        //the cases there the window closes due to cancelation,
        //or the cases where it is closed by the user (after an error message) after a failure.
        main.setInputState(true);
    }                                  

    /**
     * @param args the command line arguments
     */
    @SuppressWarnings("Convert2Lambda")
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Secondary.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Secondary().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JLabel processingLabel;
    private javax.swing.JProgressBar progressBar;
    // End of variables declaration                   
}

答案 1 :(得分:0)

问题在于我首先调用callMe()并启用按钮然后 - 我在听众中禁用它们......