我有一个扩展 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/