2016-09-21 53 views
0

我有四個小類:一個從JFrame延伸並具有GUI形式,第二 - 從他延伸幷包含按鈕工作邏輯。第三類調用秒的類方法,當第二 - 給他打電話:))。我在第二課第二種方法中的問題:按鈕無法啓用!我點擊 - 它禁用,但是,當調用方法enableButton - 什麼也沒有!JButton無法啓用,當exdending GUI形式


第一類:

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


爲什麼會出現這種情況,如何解決?

+3

爲了得到更好的幫助,請儘快發佈[mcve]不是整個班級 – Frakcool

+0

@Frakcool,但還需要什麼?我編寫了所有使用的代碼並描述了問題。 – bukashka101

+1

正是!你寫了**所有**代碼!我們不需要所有的代碼,儘可能簡單地從頭開始創建一個新項目,一個按鈕和'onImageCreated'方法,如果你可以使用一個,你可以儘可能多地做到這一點。這就是爲什麼我沒有要求你的整個代碼,但一個最小的例子,仍然可運行 – Frakcool

回答

1

顯然,OP已經解決了他的問題,但我認爲這是一個有趣的和常見的問題,所以我創建了我的推薦方法的Minimal, Complete and Verifiable Example,供將來參考。

您可以在下面查看,或者您可以從the GitHub repository獲得完整的項目。

(評論,建議,修改和反饋,也歡迎!)


主要的JFrame:

/** 
* @author Rodrigo Legendre Lima Rodrigues (AKA ArchR/AlmightyR) 
* <[email protected]> 
*/ 
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) 
* <[email protected]> 
*/ 
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     
} 
0

問題是,我稱之爲首先呼我(),並啓用按鈕,然後 - 我關閉他們的聽衆......