[英]How to return values from an ActionListener which is not in inner class
我在Java和StackOverflow中都是新手,因此,如果我做錯了什么,請原諒。 我將立即糾正!
我的問題是 :如何將實現ActionListener
類中的變量返回到另一個類的變量中?
實現ActionListener
的類不是內部類。
我自願省略進口。
這里是一個例子:
File_A.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());
}
}
File_B.java
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;
}
}
如何在File_A.java
的path
變量中返回File_B.java
的path
變量?
我試圖編寫一個返回它的方法,但是該方法未出現在所有方法的列表中,因此無法調用。 我也嘗試用Gui
擴展Pick_Something
並保護path
但是我遇到了StackOverflowError
。
有人看到我做錯了或對如何做有想法嗎?
我會建議使用回叫,一些Java的8位的java.util.function
用品你,其實是Consumer<String>
將工作完全在這里。 創建原始類的消費,並有ActionListener的類調用它.accept(...)
方法,直接傳遞信息從監聽器類與低耦合的GUI。 例如,如果你的GUI具有一個JTextField稱為filePathTxtField
你要填寫由ActionListener的獲得所選擇的用戶的文件路徑,一個,那么消費者可能看起來像這樣:
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);
}
}
我的問題是:如何將實現ActionListener的類中的變量返回到另一個類的變量中?
你不能
快速查看ActionListener
的JavaDocs將向您顯示該方法未返回值。 我非常確定,即使這樣做也將一文不值,因為您的代碼唯一知道該方法已被觸發的時間是實際調用該方法的時間。
解決方案? 將“模型”傳遞給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
,因為這將搶奪該功能並長期使您的生活更加困難
這是我嘗試過的,希望對您有所幫助。 在此示例中,偵聽器類將所選路徑返回到主窗口。
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); } } }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.