Java中“父”组件的调用方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/429114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:31:21  来源:igfitidea点击:

Calling methods of "parent" component in Java

javaclassmethods

提问by Mel

I have the following situation I think would be best to show in sample program code. I have a Java class that extends JPanel. In this class are two objects which are two more JPanels. In one of the JPanelobjects is a JTableobject. I added a listener to this JTablethat detects a double click. When it detects a double click, I want to fire a method in the top class. How do I reference this method in Java?

我有以下情况,我认为最好在示例程序代码中显示。我有一个扩展JPanel. 在这个类中有两个对象,它们是另外两个JPanels。其中一个JPanel对象是一个JTable对象。我为此添加了一个侦听器来JTable检测双击。当它检测到双击时,我想在顶级类中触发一个方法。如何在 Java 中引用此方法?

public class TopPanel extends JPanel {

  JPanel OnePanel;
  JPanel TwoPanel;

  public void MethodToFire;

}

public class OnePanel extends JPanel {

  JTable TheTable;

}

public class TheTable extends JTable {

  public TheTable {
    this.addMouseListener(new MouseAdapter(){
      public void mouseClicked(MouseEvent e){
          if (e.getClickCount() == 2){ SYNTAX CALLING THE METHOD IN TopPanel  }
      }
    } );
  }
}

采纳答案by David Koelle

One way to solve this is to use composition instead of inheritance. You could pass the JPanel into your subclass of the JTable.

解决这个问题的一种方法是使用组合而不是继承。您可以将 JPanel 传递到 JTable 的子类中。


public class TopPanel extends JPanel 
{
  private TheTable table;

  public TopPanel()
  {
    table = new TheTable(this);
  }

  public void methodToFire() { }
}

public class TheTable extends JTable 
{
  private TopPanel panel;

  public TheTable(TopPanel panel)
  {
    this.panel = panel;

    this.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        doThing();
      }
    } );
  }

  private void doThing()
  {
    this.panel.methodToFire(); 
  }
}

回答by James Schek

To access a method on the Outer class, you need to use the syntax of Outer.this.method().

要访问 Outer 类上的方法,您需要使用 Outer.this.method() 的语法。

So in this case, to access a method on the "TheTable" class from the listener, you should use TheTable.this.callMethod().

因此,在这种情况下,要从侦听器访问“TheTable”类上的方法,您应该使用TheTable.this.callMethod().

I assume that TopPanelhas added to it the TheTable. In this case, you could do something like:

我认为TopPanel已将TheTable. 在这种情况下,您可以执行以下操作:

mouseClicked(...) {
   TopTable t = (TopTable)TheTable.this.getParent();
   t.MethodToFire();
}

This is a direct answer to the question, not necessarily the "best" way to do it. A type-safe composition approach would be a better long-term solution.

这是对问题的直接回答,不一定是“最佳”方法。类型安全的组合方法将是更好的长期解决方案。

回答by Uri

I don't think that Java has a direct syntax for doing that, unless you start playing with reflection (which is of course possible, but I don't consider it very clean).

我不认为 Java 有这样做的直接语法,除非你开始玩反射(这当然是可能的,但我认为它不是很干净)。

At the point where you want to make the call, your "this" refers to an anonymous subclass of MouseAdapter.

在您要进行调用时,您的“this”指的是 MouseAdapter 的匿名子类。

The cleanest approach may be to create a private method, let's call it X, in TheTable, and have the adapter call that function.

最简洁的方法可能是创建一个私有方法,让我们在 TheTable 中将其称为 X,然后让适配器调用该函数。

Now, because that method X is in the TheTable, it doesn't know that it is inside a panel so it doesn't have any way of activating that function. If you are sure that every table is inside a panel, then you can add a panel reference field to your Table class, initialize it when it is created (you may need to modify the constructor on OnePanel), and then make the call from the method in TheTable.

现在,因为该方法 X 在 TheTable 中,所以它不知道它在面板内,因此它没有任何方法来激活该功能。如果您确定每个表都在一个面板内,那么您可以在您的 Table 类中添加一个面板引用字段,在创建时对其进行初始化(您可能需要修改 OnePanel 上的构造函数),然后从TheTable 中的方法。

If the panel method you are ultimately trying to explore not part of JPanel, you may need to create and pass interfaces.

如果您最终尝试探索的面板方法不是 JPanel 的一部分,您可能需要创建和传递接口。

回答by Anthony Rizk

Seems like you're going a round-about way - why not just do everything from the outermost class? This is one reason listeners exist, after all:

看起来你在走一条迂回的路——为什么不从最外面的班级开始做所有的事情?毕竟,这是听众存在的原因之一:


    public class TopPanel {
        public TopPanel() {
            // Construct everything here
            OnePanel.TheTable.addMouseListener(new MouseAdapter(){
              public void mouseClicked(MouseEvent e){
                 if (e.getClickCount() == 2){ MethodToFire }
              }
              } );

        }

    }

回答by David Koelle

You could make your TheTable fire an event when the mouse is pressed, which your TopPanel could listen for. This has the benefit of not making the Table and Panel classes both dependent on each other.

你可以让你的 TheTable 在按下鼠标时触发一个事件,你的 TopPanel 可以监听。这样做的好处是不会使 Table 和 Panel 类相互依赖。

The code is a little more involved, but the decoupling may be worth it.

代码有点复杂,但解耦可能是值得的。

public class TopPanel extends JPanel 
{
  private TheTable table;

  public TopPanel()
  {
    table = new TheTable(this);
    table.addTheTableListener(new TheTableListener() {
      public void tableSelected() {  // or tableSelected(TableSelectionEvent e) if you want to make a TableSelectionEvent
        methodToFire();
      }
    });
  }

  public void methodToFire() { }
}

public class TheTable extends JTable 
{
  private TopPanel panel;
  private EventListenerList listeners;

  public TheTable(TopPanel panel)
  {
    this.panel = panel;
    listeners = new EventListenerList();

    this.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        fireTableSelected();
      }
    } );
  }

  public void addTheTableListener(TheTableListener l) {
    listeners.add(l);
  }

  // also write removeListener

  private void fireTableSelected()
  {
    for (TheTableListener l : listeners) {
      l.tableSelected(); 
  }
}

public interface TheTableListener extends EventListener
{
    public void tableSelected();
}