我有四个小班:一个从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表格照片(我找不到代码,除了在记事本中打开它)):
为什么会发生这种情况以及如何解决?
答案 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()并启用按钮然后 - 我在听众中禁用它们......