我在这里挣扎......我正在使用MVC设计模式构建一个带有Java swing的小卡路里计算器应用程序。
出于某种原因,我的辅助视图(SettingsView.java)的actionPerformed方法没有做任何事情,但对于我的主视图(UserDetailsView.java),它们工作正常。
这是我的Controller课程。 (简化了方法中的代码)
import com.willemdebruyn.macronutrientcalculator.model.Model;
import com.willemdebruyn.macronutrientcalculator.view.SettingsView;
import com.willemdebruyn.macronutrientcalculator.view.UserDetailsView;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Controller
{
private UserDetailsView userDetailsView;
private SettingsView settingsView;
private Model model;
private double requiredCalories;
public Controller(UserDetailsView userDetailsView, SettingsView settingsView, Model model)
{
this.userDetailsView = userDetailsView;
this.settingsView = settingsView;
this.model = model;
this.userDetailsView.addCalorieCalculationListener(new CalorieCalculationListener()); // Here I add the listeners for my main view, they work just fine
this.userDetailsView.addMacroCalculationListener(new MacroCalculationListener());
this.settingsView.addApplySettingsListener(new ApplySettingsListener()); // This is the one that doesn't work
}
class CalorieCalculationListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
System.out.println("This prints...");
}
}
class MacroCalculationListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
System.out.println("This prints as well...");
}
}
class ApplySettingsListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
System.out.println("This never prints...");
}
}
}
这是在我的UserDetailsView中添加ActionListener的方法,它按预期工作
public void addCalorieCalculationListener(ActionListener listenForCalorieButton)
{
caloriesButton.addActionListener(listenForCalorieButton);
}
public void addMacroCalculationListener(ActionListener listenForMacroButton)
{
macrosButton.addActionListener(listenForMacroButton);
}
以下是我的SettingsView中的代码,用于添加ActionListener(不起作用的那个)
public void addApplySettingsListener(ActionListener listenForApplyButton)
{
applyButton.addActionListener(listenForApplyButton);
}
我错过了什么吗?
编辑: 按要求设置ViewView代码
import java.awt.event.ActionListener;
public class SettingsView extends javax.swing.JFrame
{
/**
* Creates new form SettingsView
*/
public SettingsView()
{
initComponents();
myInit();
}
/**
* 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()
{
jLabel3 = new javax.swing.JLabel();
jInternalFrame1 = new javax.swing.JInternalFrame();
jInternalFrame2 = new javax.swing.JInternalFrame();
jLabel2 = new javax.swing.JLabel();
metricRadioButton = new javax.swing.JRadioButton();
imperialRadioButton = new javax.swing.JRadioButton();
jInternalFrame3 = new javax.swing.JInternalFrame();
jLabel4 = new javax.swing.JLabel();
jLabel5 = new javax.swing.JLabel();
jLabel6 = new javax.swing.JLabel();
jLabel7 = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
jComboBox1 = new javax.swing.JComboBox<>();
carbsTextField = new javax.swing.JTextField();
proteinsTextField = new javax.swing.JTextField();
fatsTextField = new javax.swing.JTextField();
applyButton = new javax.swing.JButton();
jLabel3.setText("jLabel3");
jInternalFrame1.setVisible(true);
javax.swing.GroupLayout jInternalFrame1Layout = new javax.swing.GroupLayout(jInternalFrame1.getContentPane());
jInternalFrame1.getContentPane().setLayout(jInternalFrame1Layout);
jInternalFrame1Layout.setHorizontalGroup(
jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
jInternalFrame1Layout.setVerticalGroup(
jInternalFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jInternalFrame2.setVisible(true);
jLabel2.setFont(new java.awt.Font("Dialog", 1, 16)); // NOI18N
jLabel2.setText("Measuring System:");
metricRadioButton.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
metricRadioButton.setText("Metric (cm/kg)");
metricRadioButton.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
metricRadioButtonActionPerformed(evt);
}
});
imperialRadioButton.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
imperialRadioButton.setText("Imperial (in/lbs)");
imperialRadioButton.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
imperialRadioButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout jInternalFrame2Layout = new javax.swing.GroupLayout(jInternalFrame2.getContentPane());
jInternalFrame2.getContentPane().setLayout(jInternalFrame2Layout);
jInternalFrame2Layout.setHorizontalGroup(
jInternalFrame2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jInternalFrame2Layout.createSequentialGroup()
.addGap(113, 113, 113)
.addGroup(jInternalFrame2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(imperialRadioButton)
.addComponent(metricRadioButton)
.addComponent(jLabel2))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jInternalFrame2Layout.setVerticalGroup(
jInternalFrame2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jInternalFrame2Layout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(metricRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(imperialRadioButton)
.addGap(0, 16, Short.MAX_VALUE))
);
jInternalFrame3.setVisible(true);
jLabel4.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
jLabel4.setText("Carbs:");
jLabel5.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
jLabel5.setText("Proteins:");
jLabel6.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
jLabel6.setText("Fats:");
jLabel7.setFont(new java.awt.Font("Dialog", 1, 16)); // NOI18N
jLabel7.setText("Custom Macros:");
jLabel1.setFont(new java.awt.Font("Dialog", 1, 16)); // NOI18N
jLabel1.setText("Macro Nutrients Split:");
jComboBox1.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "<Carbs/Proteins/Fats>", "50/30/20", "80/10/10", "Custom" }));
javax.swing.GroupLayout jInternalFrame3Layout = new javax.swing.GroupLayout(jInternalFrame3.getContentPane());
jInternalFrame3.getContentPane().setLayout(jInternalFrame3Layout);
jInternalFrame3Layout.setHorizontalGroup(
jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jInternalFrame3Layout.createSequentialGroup()
.addGap(110, 110, 110)
.addGroup(jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jInternalFrame3Layout.createSequentialGroup()
.addComponent(jLabel7)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jInternalFrame3Layout.createSequentialGroup()
.addGroup(jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel5)
.addComponent(jLabel6)
.addComponent(jLabel4))
.addGap(18, 18, 18)
.addGroup(jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(fatsTextField)
.addComponent(proteinsTextField)
.addComponent(carbsTextField))))
.addComponent(jLabel1)))
.addContainerGap(111, Short.MAX_VALUE))
);
jInternalFrame3Layout.setVerticalGroup(
jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jInternalFrame3Layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jLabel7)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel4)
.addComponent(carbsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel5)
.addComponent(proteinsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jInternalFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel6)
.addComponent(fatsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 38, Short.MAX_VALUE))
);
applyButton.setText("Apply");
applyButton.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
applyButtonActionPerformed(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()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jInternalFrame2)
.addComponent(jInternalFrame3)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(applyButton)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jInternalFrame2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jInternalFrame3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(applyButton)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void myInit()
{
// Metric radio button should be selected on default
metricRadioButton.setSelected(true);
// Disable textFields on startup
carbsTextField.setEditable(false);
proteinsTextField.setEditable(false);
fatsTextField.setEditable(false);
}
private void metricRadioButtonActionPerformed(java.awt.event.ActionEvent evt)
{
// When metric radio button is selected, deselect the imperial radio button
imperialRadioButton.setSelected(false);
}
private void imperialRadioButtonActionPerformed(java.awt.event.ActionEvent evt)
{
// When imperial radio button is selected, deselect the metric radio button
metricRadioButton.setSelected(false);
}
private void applyButtonActionPerformed(java.awt.event.ActionEvent evt)
{
System.out.println("Apply button clicked");
}
public void addApplySettingsListener(ActionListener listenForApplyButton)
{
applyButton.addActionListener(listenForApplyButton);
}
public String getMeasuringSystem()
{
if (metricRadioButton.isSelected() && !imperialRadioButton.isSelected())
return "Metric";
else if (imperialRadioButton.isSelected() && !metricRadioButton.isSelected())
return "Imperial";
return "No Selection made";
}
// Variables declaration - do not modify
private javax.swing.JButton applyButton;
private javax.swing.JTextField carbsTextField;
private javax.swing.JTextField fatsTextField;
private javax.swing.JRadioButton imperialRadioButton;
private javax.swing.JComboBox<String> jComboBox1;
private javax.swing.JInternalFrame jInternalFrame1;
private javax.swing.JInternalFrame jInternalFrame2;
private javax.swing.JInternalFrame jInternalFrame3;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JRadioButton metricRadioButton;
private javax.swing.JTextField proteinsTextField;
// End of variables declaration
}
编辑2:这是我的包含主要方法的课程
import com.willemdebruyn.macronutrientcalculator.controller.Controller;
import com.willemdebruyn.macronutrientcalculator.model.Model;
import com.willemdebruyn.macronutrientcalculator.view.SettingsView;
import com.willemdebruyn.macronutrientcalculator.view.UserDetailsView;
public class App
{
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 ex) {
java.util.logging.Logger.getLogger(UserDetailsView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(UserDetailsView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(UserDetailsView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(UserDetailsView.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
UserDetailsView userDetailsView = new UserDetailsView();
SettingsView settingsView = new SettingsView();
Model model = new Model();
Controller controller = new Controller(userDetailsView, settingsView, model);
userDetailsView.setVisible(true); // SettingsView gets openend from this view
}
}
编辑3:UserDetailsView.java
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class UserDetailsView extends JFrame
{
private boolean calorieCalculationPerformed;
public UserDetailsView()
{
initComponents();
myInit();
}
/**
* 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()
{
// I removed the generated code, apparently my post exeeded the allowed limit
}
private void myInit()
{
// Disable macros button on startup, will enable again after caloric needs have been calculated
macrosButton.setEnabled(false);
}
private void maleRadioButtonActionPerformed(java.awt.event.ActionEvent evt)
{
// When male button is selected, deselect the female radio button
femaleRadioButton.setSelected(false);
}
private void femaleRadioButtonActionPerformed(java.awt.event.ActionEvent evt)
{
// When female button is selected, deselect the male radio button
maleRadioButton.setSelected(false);
}
private void caloriesButtonActionPerformed(java.awt.event.ActionEvent evt)
{
calorieCalculationPerformed = true;
System.out.println("Calories button gets clicked");
if (heightField.getText().isEmpty() || weightField.getText().isEmpty() || ageField.getText().isEmpty())
{
JOptionPane.showMessageDialog(this, "Please fill in all the fields before performing the calculation.");
calorieCalculationPerformed = false;
}
else if ((!maleRadioButton.isSelected() && !femaleRadioButton.isSelected()))
{
JOptionPane.showMessageDialog(this, "Please select your gender.");
calorieCalculationPerformed = false;
}
else if (activityComboBox.getSelectedItem().toString() == "<Select>")
{
JOptionPane.showMessageDialog(this, "Please select your activity level.");
calorieCalculationPerformed = false;
}
else if (goalComboBox.getSelectedItem().toString() == "<Select>")
{
JOptionPane.showMessageDialog(this, "Please select your fitness goal.");
calorieCalculationPerformed = false;
}
// Only when caloric requirements have been calculated will the user be able to calculate macronutrient requirements
if (calorieCalculationPerformed)
macrosButton.setEnabled(true);
else
macrosButton.setEnabled(false);
}
private void macrosButtonActionPerformed(java.awt.event.ActionEvent evt)
{
if (heightField.getText().isEmpty() || weightField.getText().isEmpty() || ageField.getText().isEmpty())
{
JOptionPane.showMessageDialog(this, "Please fill in all the fields before performing the calculation.");
}
else if ((!maleRadioButton.isSelected() && !femaleRadioButton.isSelected()))
{
JOptionPane.showMessageDialog(this, "Please select your gender.");
}
else if (activityComboBox.getSelectedItem().toString() == "<Select>")
{
JOptionPane.showMessageDialog(this, "Please select your activity level.");
calorieCalculationPerformed = false;
}
else if (goalComboBox.getSelectedItem().toString() == "<Select>")
{
JOptionPane.showMessageDialog(this, "Please select your fitness goal.");
}
}
private void settingsButtonActionPerformed(java.awt.event.ActionEvent evt)
{
SettingsView settingsView = new SettingsView();
settingsView.setVisible(true);
}
public void addCalorieCalculationListener(ActionListener listenForCalorieButton)
{
caloriesButton.addActionListener(listenForCalorieButton);
}
public void addMacroCalculationListener(ActionListener listenForMacroButton)
{
macrosButton.addActionListener(listenForMacroButton);
}
public double getUserHeight()
{
if (!heightField.getText().isEmpty())
return Double.parseDouble(heightField.getText());
return 0.0;
}
public double getUserWeight()
{
if (!weightField.getText().isEmpty())
return Double.parseDouble(weightField.getText());
return 0.0;
}
public int getUserAge()
{
if (!ageField.getText().isEmpty())
return Integer.parseInt(ageField.getText());
return 0;
}
public String getUserGender()
{
if (femaleRadioButton.isSelected() && !maleRadioButton.isSelected())
{
return "female";
}
else if(maleRadioButton.isSelected() && !femaleRadioButton.isSelected())
{
return "male";
}
else return "No selection made";
}
public String getUserActivityLevel()
{
return (String) activityComboBox.getSelectedItem();
}
public String getUserGoal()
{
return (String) goalComboBox.getSelectedItem();
}
public void displayNutritionalInfo(String message)
{
JOptionPane.showMessageDialog(this, message);
}
public void displayErrorMessage(String errorMessage)
{
JOptionPane.showMessageDialog(this, errorMessage);
}
// Variables declaration - do not modify
private javax.swing.JComboBox<String> activityComboBox;
private javax.swing.JTextField ageField;
private javax.swing.JButton caloriesButton;
private javax.swing.JRadioButton femaleRadioButton;
private javax.swing.JComboBox<String> goalComboBox;
private javax.swing.JTextField heightField;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JButton macrosButton;
private javax.swing.JRadioButton maleRadioButton;
private javax.swing.JButton settingsButton;
private javax.swing.JTextField weightField;
// End of variables declaration
}