我是Java和 StackOverflow 中的新手,所以,如果我做错了什么,请原谅。我会立即纠正!
我的问题是:如何将实现ADDENDUM
的类中的变量返回到另一个类的变量中?
实现ActionListener
的类不是内部类。
我自愿省略进口。
这里有个例子:
File_A.java
ActionListener
File_B.java
public class Gui extends JFrame {
private JButton myButton;
private String path;
some other properties...
public Gui () {
myButton = new JButton("Some Text");
myButton.AddActionListener(new Pick_Something());
}
}
如何在public class Pick_Something implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser selectElement = new JFileChooser();
String path;
int status = selectElement.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION)
path = selectElement.getSelectedFile().getAbsolutePath();
else
path = null;
}
}
的{{1}}变量中返回File_B.java
的{{1}}变量?
我试图编写一个返回它的方法,但是该方法未出现在所有方法的列表中,因此无法调用。而且我还尝试将path
扩展为File_A.java
,并保护path
,但是我有一个Pick_Something
。
有人看到我做错了,或者对如何做有想法吗?
答案 0 :(得分:3)
我建议使用回调,这是Java-8的java.util.function
为您提供的,实际上,Consumer<String>
在这里可以很好地工作。在原始类中创建您的Consumer,并让ActionListener类调用其.accept(...)
方法,以较低的耦合将信息直接从侦听器类传递到GUI。例如,如果您的Gui拥有一个名为filePathTxtField
的JTextField,您希望用用户选择的文件路径(由ActionListener获得的路径)填充该JTextField,则使用者可能看起来像这样:
Consumer<String> consumer = (String text) -> {
filePathTxtField.setText(text);
};
这将在Gui类中创建,然后通过构造函数参数传递到ActionListener类:
// in the Gui class's constructor
button.addActionListener(new PickSomething(consumer));
// the PickSomething class and its constructor
class PickSomething implements ActionListener {
private Consumer<String> consumer;
public PickSomething(Consumer<String> consumer) {
this.consumer = consumer;
}
然后,actionPerformed方法可能类似于:
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser selectElement = new JFileChooser();
String path;
// get the path String and set it
int status = selectElement.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION) {
path = selectElement.getSelectedFile().getAbsolutePath();
} else {
path = null;
}
// pass the path String into the Gui by calling the call-back method, passing it in
consumer.accept(path);
}
整个过程看起来像:
import java.util.function.Consumer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
@SuppressWarnings("serial")
public class Gui extends JPanel {
private JTextField filePathTxtField = new JTextField(45);
private int foo = 0;
public Gui() {
filePathTxtField.setFocusable(false);
add(filePathTxtField);
JButton button = new JButton("Get File Path");
Consumer<String> consumer = (String text) -> {
filePathTxtField.setText(text);
};
button.addActionListener(new PickSomething(consumer));
add(button);
}
private static void createAndShowGui() {
Gui mainPanel = new Gui();
JFrame frame = new JFrame("Gui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.function.Consumer;
import javax.swing.JFileChooser;
public class PickSomething implements ActionListener {
private Consumer<String> consumer;
public PickSomething(Consumer<String> consumer) {
this.consumer = consumer;
}
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser selectElement = new JFileChooser();
String path;
int status = selectElement.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION) {
path = selectElement.getSelectedFile().getAbsolutePath();
} else {
path = null;
}
consumer.accept(path);
}
}
答案 1 :(得分:2)
我的问题是:如何将实现ActionListener的类中的变量返回到另一个类的变量中?
你不能。
快速浏览JavaDocs for ActionListener
将向您显示该方法未返回值。我非常确定,即使这样做也将一文不值,因为您的代码唯一知道该方法已被触发的时间是实际被调用的时间。
解决方案?将“模型”传递给ActionListener
实现...
首先定义一个简单的interface
或合同...
public PathPicker {
public void setPath(File path);
}
然后更新PickSomething
以接受此interface
...的实例...
public class PickSomething implements ActionListener {
private PathPicker picker;
public PickSomething(PathPicker picker) {
this.picker = picker;
}
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser selectElement = new JFileChooser();
int status = selectElement.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION) {
picker.setPath(selectElement.getSelectedFile());
} else {
picker.setPath(null);
}
}
}
现在,您所要做的就是实现PathPicker
接口,在创建时将其引用传递给PickSomething
,然后等待其调用setPath
。
这通常称为“委托”(并且ActionListener
也是其中的一个示例),其中实际负责将“委托”到其他对象。从很简单的意义上讲,它也是“可观察性”的一个示例,其中PickSomething
的一个实例可以PathPicker
的观察者来观察其状态(选择了路径)。
它也使代码解耦,因为PathPicker
并不关心路径的设置,仅在设置路径时通知它。
File
是文件系统文件或路径的抽象表示。它具有许多非常酷的功能,使使用文件系统变得更加轻松和简单。
许多API也引用了File
来执行其操作。您应该尽可能避免将File
转换为String
,因为从长远来看,您将抢劫该功能并使生活更加困难
答案 2 :(得分:0)
这是我尝试过的方法,希望对您有所帮助。在此示例中,侦听器类将所选路径返回到主窗口。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ActionListenerTester {
private String path;
private JLabel status;
public static void main(String [] args) {
new ActionListenerTester().gui();
}
private void gui() {
JFrame frame = new JFrame();
frame.setTitle("An External Listener");
JLabel title = new JLabel("Get My Paths:");
JButton button = new JButton("Get Path");
button.addActionListener(new MyActionListener(this));
status = new JLabel("Click the button to get path...");
Container pane = frame.getContentPane();
pane.setLayout(new GridLayout(3, 1));
pane.add(title);
pane.add(button);
pane.add(status);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(500, 300);
frame.setVisible(true);
}
public void setPath(String path) {
this.path = path;
status.setText(path);
}
}
class MyActionListener implements ActionListener {
private ActionListenerTester gui;
public MyActionListener(ActionListenerTester gui) {
this.gui = gui;
}
public void actionPerformed(ActionEvent e) {
JFileChooser selectElement = new JFileChooser();
String path = "";
int status = selectElement.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION) {
path = selectElement.getSelectedFile().getAbsolutePath();
}
path = path.isEmpty() ? "No path selected!" : path;
gui.setPath(path);
}
}
java.util.Observer
和Observable
对象。 GUI主类是观察者,而动作侦听器类中的选定路径是可观察的。当可观察对象(路径)更新时,将向观察者(GUI主类)发送路径值。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Observer;
import java.util.Observable;
public class ActionListenerTester2
implements Observer {
private String path;
private JLabel status;
public static void main(String [] args) {
new ActionListenerTester2().gui();
}
private void gui() {
JFrame frame = new JFrame();
frame.setTitle("An External Listener 2");
JLabel title = new JLabel("Get My Paths:");
JButton button = new JButton("Get Path");
button.addActionListener(new MyActionListener(this));
status = new JLabel("Click the button to get path...");
Container pane = frame.getContentPane();
pane.setLayout(new GridLayout(3, 1));
pane.add(title);
pane.add(button);
pane.add(status);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(500, 300);
frame.setVisible(true);
}
/*
* Observer interface's overridden method.
* This method runs when the Observable object notifies
* its observer objects (in this case, ActionListenerTester2)
* about the update to the observable.
*/
@Override
public void update(Observable o, Object arg) {
path = (String) arg;
status.setText(path);
}
}
class MyActionListener implements ActionListener {
private PathObservable observable;
public MyActionListener(ActionListenerTester2 gui) {
observable = new PathObservable();
observable.addObserver(gui);
}
public void actionPerformed(ActionEvent e) {
JFileChooser selectElement = new JFileChooser();
String path = "";
int status = selectElement.showOpenDialog(null);
if (status == JFileChooser.APPROVE_OPTION) {
path = selectElement.getSelectedFile().getAbsolutePath();
}
System.out.println("Path: " + path);
path = path.isEmpty() ? "No path selected!" : path;
observable.changeData(path);
}
/*
* When the Observable object changes, the notifyObservers()
* method informs all the Observer objects - in this example
* the main gui class: ActionListenerTester2.
*/
class PathObservable extends Observable {
PathObservable() {
super();
}
void changeData(Object data) {
// the two methods of Observable class
setChanged();
notifyObservers(data);
}
}
}