【问题标题】:Passing a value between components在组件之间传递值
【发布时间】:2011-06-09 02:52:37
【问题描述】:

我有一个JDialog,它调用一个AsbtractAction,它调出一个JFileChooser,这样用户就可以选择一个目录。这些都是单独的类。从JFileChooser 传递值的正确方法是什么,以便我可以在JDialog 中显示目录的路径?

编辑:更新了问题。

【问题讨论】:

  • P. - 你的意思是JFileChooser 对吗?
  • 确切:)。将立即编辑问题。

标签: java swing parameter-passing


【解决方案1】:

这是一个不完整的示例,但我想可以让您了解如何实现您所需要的。重要的一点是引用您希望选择回来的属性,例如YourDialog.this.selectedFile=file;

如何在代码中放置如下:

   public class YourDialog extends JDialog implements ActionListener {
          protected File selectedFile=null;
          //Constructor
          public YourDialog(JFrame frame, boolean modal, String message) {
                //... create button and added to the panel
                someButton.addActionListener(new AbstractAction {
                    public void actionPerformed(ActionEvent e) {
                            final JFileChooser fc = new JFileChooser();
                            int returnVal = fc.showOpenDialog(YourDialog.this);
                            if (returnVal == JFileChooser.APPROVE_OPTION) {
                                File file = fc.getSelectedFile();

                                // HERE IS THE TRICK I GUESS !!
                                YourDialog.this.selectedFile=file;
                            }
                    }

                });
          }
    }

希望对您有所帮助,很抱歉没有发布完整的示例。

编辑

本质上,我们没有向 AbstractAction 传递任何参数。事实上,AbstractAction 可以通过像YourDialog.this.somePropertyOrMethod 这样的访问来访问“调用者”的任何非私有属性。这是因为AbstractActionYourDialog 类的匿名类。

【讨论】:

  • 不用担心。我很欣赏它,它回答了这个问题。因此,一种方法是将引用传递给构造函数,然后进行回调。顺便说一句,我需要这样做,因为 AsbtractAction 是独立的,可以在其他组件中使用。
  • 本质上我们没有向 AbstractAction 传递任何参数。事实上,AbstractAction 可以通过像 YourDialog.this.somePropertyOrMethod 这样的访问来访问“调用者”的任何非私有属性。这是因为 AbstractAction 是 YourDialog 类的匿名类。
  • 编辑添加了我认为实际上反映了一些优点的最后评论。
【解决方案2】:

我不是这方面的专家,但我相信有两种常见的方法可以将值从一个对象传递到另一个对象(可能还有更多),将值从一个对象推送到其他并通过将值从一个拉到另一个。通过推动我的意思是这样做的明显方式,其中类一具有对类二的引用并调用类2中的方法将值传入。在您的示例中, AbstractAction 具有对 GUI 的引用并调用 GUI 中的方法来设置 JTextField,如下所示:

  public void actionPerformed(ActionEvent arg0) {
     String text = "Text from MyPushAction";
     guiPanel.setPushPathFieldText(text); 
  }

另一种方式更复杂,GUI 有一个注册到操作的侦听器,并在通知属性已更改时从 GUI 中提取信息。这可能不是您何时使用它的最佳示例,但它可能是解耦代码的有用方法。这方面的一个例子有点复杂。以下是两者的示例:

import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import javax.swing.*;

public class FuSwing {
    private static void createAndShowUI() {
        GuiPanel guiPanel = new GuiPanel();

        JFrame frame = new JFrame("FuSwing");
        frame.getContentPane().add(guiPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}

class GuiPanel extends JPanel {
    private MyPullAction myPullAction = new MyPullAction();
    private JTextField pushPathField = new JTextField(20);
    private JButton pushActionButton = new JButton(new MyPushAction(this));
    private JTextField pullPathField = new JTextField(20);
    private JButton pullActionButton = new JButton(myPullAction);

    public GuiPanel() {
        add(pushActionButton);
        add(pushPathField);
        add(Box.createHorizontalStrut(15));
        add(pullActionButton);
        add(pullPathField);

        myPullAction.addPropertyChangeListener(new PropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals(MyPullAction.TEXT_PROPERTY)) {
                    pullPathField.setText(evt.getNewValue().toString());
                }
            }
        });
    }

    public void setPushPathFieldText(String text) {
        pushPathField.setText(text);
    }
}

class MyPushAction extends AbstractAction {
    private GuiPanel guiPanel;

    public MyPushAction(GuiPanel guiPanel) {
        super("Push Action");
        this.guiPanel = guiPanel;
    }

    public void actionPerformed(ActionEvent arg0) {
        String text = "Text from MyPushAction";
        guiPanel.setPushPathFieldText(text);
    }

}

class MyPullAction extends AbstractAction {
    public static final String TEXT_PROPERTY = "text";
    private String text = "";
    private PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    public MyPullAction() {
        super("Pull Action");
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(listener);
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        String oldText = this.text;
        this.text = text;
        PropertyChangeEvent evt = new PropertyChangeEvent(this, TEXT_PROPERTY, oldText, text);
        pcs.firePropertyChange(evt);
    }

    public void actionPerformed(ActionEvent e) {
        setText("Text from MyPullAction");
    }
}

【讨论】:

  • 方法 1 很简单,击败了我想到的第一个解决方案,即在 Asbtraction 上调用一个方法,然后尝试读取一个属性(不保证该值会被更新)。但是,它使类相互依赖,并且如果要重用 AbstractAction,则解耦是要走的路。第二种解决方案听起来很像观察者模式。我会看看 PropertyChangeSupport。
  • 那是因为它观察者模式。
猜你喜欢
  • 1970-01-01
  • 2021-06-08
  • 2016-07-20
  • 1970-01-01
  • 1970-01-01
  • 2021-04-13
  • 2020-04-30
  • 2020-03-25
  • 2018-11-30
相关资源
最近更新 更多