在为Java Swing元素实现ActionListener时,如何解决静态引用错误?
我是一个相当新手的Java程序员,正在尝试使用JavaSwing元素创建一个简单的用户界面,该元素接受用户输入,并(最终)验证输入的日期的格式是否正确
我目前正在尝试使用一个主“createTextbox”类,该类生成表单,同时使用一个实现ActionListener的类来读取用户的输入,并在单击按钮时验证日期。我遇到的问题是,当我尝试在ActionListener类中从CreateTextbox引用我的字段时,我得到了一个错误,因为在静态上下文中引用我的字段是非静态的。但是,我不想将字段定义为静态字段,因为我希望用户能够更改输入并再次单击按钮
以下是我的CreateTextbox类:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class CreateTextbox extends JFrame{
JTextField stringEntry, dateEntry;
JLabel stringEntryLabel, dateEntryLabel;
JButton print;
public CreateTextbox(){
setLayout(null);
stringEntry = new JTextField(1);
stringEntry.setBounds(100,20,100,20);
add(stringEntry);
stringEntryLabel = new JLabel("String Name:");
stringEntryLabel.setBounds(10,20,100,20);
add(stringEntryLabel);
dateEntry = new JTextField(1);
dateEntry.setBounds(100,50,100,20);
add(dateEntry);
dateEntryLabel = new JLabel("Date:");
dateEntryLabel.setBounds(10,50,100,20);
print = new JButton("Validate");
print.setBounds(20,260,100,20);
print.addActionListener(new MyAction());
add(print);
}
public static void main (String[] args)
{
CreateTextbox me = new CreateTextbox();
me.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
me.setVisible(true);
me.setLocation(550, 500);
me.setSize(700, 700);
me. setTitle("Create Textbox");
}
}
以及ActionListener类:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
public class MyAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
String strInput = CreateTextbox.stringEntry.getText();
String strDate = CreateTextbox.dateEntry.getText();
valiDate(strDate);
}
public void valiDate(String date) {
//code to validate the date
}
}
我猜这有一个我忽略的非常简单的解决方案。我看过几篇像Non-static variable cannot be referenced from a static context这样的帖子,但我仍然很难找到解决方案
# 1 楼答案
既然你们已经说你们正在学习,我将试着用“为什么和为什么不”来给你们一个教学上的答案,可能有点太长了,但希望它能帮助你们
当您引用
CreateTextbox.stringEntry
时,您引用的是一个类变量,这是一个静态变量,因为您实际上在语句的第一部分告诉我们的是一个类,而不是一个对象,这是该类的所有实例所共有的另一方面,当您执行
this.stringEntry
操作时,您引用的是对象的变量,它不同于that.stringEntry
,并且它们是其所有者对象的属性。必须指出的是,一般来说,让您的变量可见是一种不好的做法(当然有时不这样做是合理的),而是让其他人通过“getter”访问它们,即允许您访问内部变量的方法:getStringEntry():JTextField
,getDateEntry():JTextField
。但同样,您不想让其他人获得您的组件,因为当您只想公开其值时,可以从外部操纵它们,所以只需公开它们各自的文本:然后,在另一个类中有一个
ActionListener
。当ActionListener
的事件被触发时,该方法接收一个ActionEvent
,其中包含对发起事件的对象的引用,并且可以通过方法getSource()
访问该对象。当您有一个外部类时,您希望使用该类“附加”到CreateTextbox
,因此您希望在源中接收CreateTextbox
,因此您可以像这样访问实例:请注意,您现在正在访问对象(类的一个实例化),而不是静态地访问类(在所有实例中都是通用的)
但是您将这个操作添加到一个按钮,因此您将收到一个
JButton
作为源,它是您正在实现的内容的一个内部组件,因此这应该会让您认为您最好使用一个内部类<请注意,这通常是不正确的,也不是必需的,我是从一个好的设计角度讲的,您确实可以在外部类中实现这一点让我添加一个建议,使用Action
而不是ActionListener
,这没有多大区别,但很有用,因为它封装了不同组件要使用的整个操作,并使其跨组件层次结构以及名称、图标等可用一旦移动到类内部,您就可以选择声明内部类
static
,并使其独立于实例;或者不,这样您就可以访问变量。显然你的是第二个案子这是您的方法在内部类中的外观,还原为原始代码,但注意到原始的
CreateTextbox.stringEntry
(静态引用)现在是CreateTextbox.this.stringEntry
(访问实例)最后,它可能是这样的:
让我补充一点,您应该看看文章"How to Use Formatted Text Fields",因为Java已经有了自己的方法来验证文本字段中的日期和其他值
# 2 楼答案
我将内联listener类。这样您就可以访问实例变量,即使它们是私有的