java - 在重写的 JTable 中的构造函数之前调用的方法

标签 java

我有一个扩展 JScrollPane 的类,它正在创建另一个扩展 JTable 的类的对象。基本上看起来像这样:

class CustomScrollPane{
   private CustomTable table

   public CustomScrollPane(..){
   table = new CustomTable(this);
   ..
   }
   public void scrollToBottom(){
      ...
   }
}

在 CustomTable 类中,我重写 tableChanged:

public class CustomTable extends JTable{

private CustomScrollPane scrollPane;

public CustomTable(CustomScrollPane scrollPane){
    super();
    this.scrollPane = scrollPane;
}

@Override
public void tableChanged(TableModelEvent e) {
    super.tableChanged(e);
    scrollPane.scrollToBottom();
}

当我运行此命令时,我在 tableChanged() 中的scrollPane 上收到 NullPointerException,这怎么可能?在构造函数中设置的scrollPane怎么可能为null?在调试器中运行它表明 tableChanged() 在构造函数之前被调用。添加条件

     if (scrollPane != null)

实际上解决了问题,因为稍后会调用构造函数。另外,定义 JTable 的构造,例如:

        table = new JTable(){
        @Override
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            final Component c = super.prepareRenderer(new CustomTableCellRenderer(), row, column);
            if (c instanceof JComponent){
                ((JComponent) c).setOpaque(true);
            }
            return c;
        }

        @Override
        public void paint(Graphics g) {
            int scrolling = scrollPane.getViewport().getViewPosition().y;
            super.paint(g);
            g.drawImage(image.getImage(), -30, -50 + scrolling, null, null);
        }

        @Override
        public void tableChanged(TableModelEvent e) {
            super.tableChanged(e);
            scrollPane.scrollToBottom();
        }
    };

直接在 CustomScrollPane 构造函数中也可以。为什么不能将其分解为一个单独的类?

最佳答案

看起来 JTable 构造函数调用了 tableChanged(...) 方法 - 这意味着它是在您能够初始化 scrollPane 实例变量之前调用的。

首先,我建议你看一下本书Java Puzzlers中的一些益智游戏。 - 特别是谜题 51:有什么意义,也许还有谜题 53:做你的事。他们应该帮助您了解正在发生的事情。基本上,CustomTable 构造函数的第一行调用 JTable 构造函数(通过 super())。 JTable 构造函数正在尝试调用 tableChanged - 它已被覆盖。重写的 tableChanged 尝试操作 scrollPane...但所有这些都发生在构造函数 (super()) 的第 1 行 - this.scrollPane =scrollPane 执行之前,因此 scrollPane 仍然为 null。

接下来,我建议使用 observer pattern 。这里有两个对象 - 滚动 Pane 和自定义表格 - 当另一个对象发生更改时需要通知其中一个对象。这就是教科书上的观察者模式。这是粗略的想法:

文件CustomTable.java

public class CustomTable extends JTable {

    // No more scroll pane; only observers
    private List<ChangeListener> listeners = [];

    // no more scroll pagne
    public CustomTable(){
        super();
    }

    @Override
    public void tableChanged(TableModelEvent e) {
        super.tableChanged(e);
        this.fireChangeEvent();
    }

    /* new methods */

    public void addChangeListener(ChangeListener listener) {
        listeners.add(listener);
    }

    public void removeChangeListener(ChangeListener listener) {
        // ...
    }

    private void fireChangeEvent() {
        for(String l : listeners ){
            l.onChange();
        }
    }
}

文件CustomScrollPane.java

class CustomScrollPane implements ChangeListener{
   private CustomTable table

   public CustomScrollPane(/*...*/){
       table = new CustomTable();
       table.addChangeListener(this);
       //...
   }

   public void scrollToBottom(){
      //...
   }

   /* new methods */

  @Override
  public void onChange() {
      scrollToBottom();
  }
}

关于java - 在重写的 JTable 中的构造函数之前调用的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12875112/

相关文章:

java - Perl 中的链接 HashMap

java - 查找另一个字符串中的多个字符串

java - 对私有(private)方法的递归对象访问

java - RESTful 服务契约

java - 解析android中的xml文件,获取给定节点的所有属性

java - 从 JSP 页面中的 HashMap 获取 URL 值(使用 Struts2)

java - jni 不支持类型如 void*、unsigned int*、.... 怎么办?

java - 获取选定 JTable 单元格的位置?

java - 确定对象是否为整数

java - 舍入至 2 的最高次方(仅限二元运算)