簡體   English   中英

如何從不在內部類中的ActionListener返回值

[英]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.javapath變量中返回File_B.javapath變量?

我試圖編寫一個返回它的方法,但是該方法未出現在所有方法的列表中,因此無法調用。 我也嘗試用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的類中的變量返回到另一個類的變量中?

你不能

快速查看ActionListenerJavaDocs將向您顯示該方法未返回值。 我非常確定,即使這樣做也將一文不值,因為您的代碼唯一知道該方法已被觸發的時間是實際調用該方法的時間。

解決方案? 將“模型”傳遞給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);
    }
}



替代方式:

當它不是內部類時,這是從操作偵聽器類返回值的另一種方法。 到主要的GUI類。 這使用java.util.ObserverObservable對象。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM