当前位置: 首页 > 知识库问答 >
问题:

从默认表模型中删除行后使用行的数据

梁马鲁
2023-03-14

是的,我知道,这听起来很愚蠢。但在我说明我的问题之前。

我有一个包含大量 J 表的 GUI。我有各种默认表模型,每个JTable一个。所以,1:1。对于每个默认表模型,我都创建了一个表模型管理器。

对于在GUI中插入和删除元素,我只创建了两个方法,addVehicle和removeVehicle:

public void addVehicle(final DefaultTableModel model, final String s1, final String s2) {
    Runnable addV = new Runnable() {
        @Override
        public void run() {
            model.addRow(new Object[] { s1, s2 });
        } 
    };
    SwingUtilities.invokeLater(addV);
}


public void removeVehicle(final DefaultTableModel model, final int index) {
    if (row!=null){
        String s1= row.elementAt(0).toString();
        Runnable removeV = new Runnable() {
            @Override
            public void run() {
                model.removeRow(index);
            }
        };
        SwingUtilities.invokeLater(removeV);
    }
}

这些方法是完美的,自动识别正确的表模型。

但我有一个必要性:因为我有很多JTable(和相应的DefaultTableModels),并且当我从表中添加/删除一行时,第三方软件必须得到信息,所以我创建了几个TableModelListener。

例如,侦听器1:

TableModelListener listener1 = new TableModelListener() {
    public void tableChanged(TableModelEvent e) {
        DefaultTableModel m = (DefaultTableModel) e.getSource();
        int row = e.getLastRow();
        switch (e.getType()) {
            case (TableModelEvent.INSERT): {
                System.out.println("Insert! Key: "+m.getValueAt(row, 0));

                // My agent, the third-party software: 
                shipperAgent.newTruck((String) m.getValueAt(row, 0));
            } break;

            case (TableModelEvent.DELETE): {
                System.out.println("Delete! Key:"+m.getValueAt(row, 0));

                // My agent, the third-party software: 
                shipperAgent.removeTruck((String)m.getValueAt(row, 0));
            } break;

            case (TableModelEvent.UPDATE): {
                // ...
            } break;
        }
    }
};

另一个例子是听众2(我只给你们看了一个片段...):

            case (TableModelEvent.INSERT): {
                System.out.println("Activate! Key: "+m.getValueAt(row, 0));

                // My agent, the third-party software: 
                shipperAgent.activateTruck((String) m.getValueAt(row, 0));
            } break;

            case (TableModelEvent.DELETE): {
                System.out.println("Deactivate! Key:"+m.getValueAt(row, 0));

                // My agent, the third-party software: 
                shipperAgent.deactivateTruck((String)m.getValueAt(row, 0));
            } break;

这就是问题所在:对于插入是可以的,但是对于删除就不行了。我知道为什么:当我从GUI中移除一行时,该行被删除并在switch(case tablemodelent。DELETE)处理另一行(紧接在我删除的那一行之后)。此外,如果这一行是最后一行(因为后面没有更多的行),我会得到一个NullPointerException。

在侦听器中,如何在实际删除一行之前使用它?(或者其他高明的方式?)

共有1个答案

吴单鹗
2023-03-14

…当我从表中添加/删除一行时,第三方软件必须得到信息,我创建了几个TableModelListener。

如果你看到TableModelEvent API,就没有办法从事件本身获取数据,你所拥有的只是作为事件源的TableModel。话虽如此,当触发表模型事件时,模型中的更改已经完成,您对此无能为力,因此您无法获得已删除的行的值,因为这些值将不再存在。

但是,如果您的关注点是通知这个第三方软件以保持一致性,那么您应该在从表模型中删除行之前考虑这样做。

public void removeVehicle(final DefaultTableModel model, final int index) {
    String value = (String)model.getValueAt(index, 0);
    shipperAgent.deactivateTruck(value);
    // If everything went ok, then remove the row from the table model.
    // Of course, do it in the Event Dispatch Thread.
    model.removeRow(index);
}

通过这种方式,您甚至可以协调第三方软件和您的应用程序:如果该行所代表的卡车无法停用,则不要删除表模型中的该行,而是显示一些错误消息。

但是我想集中与代理(第三方软件)的通信,并将其与代码的其余部分分开,而不是传播它。

嗯,这是完全有道理的,我相信有不止一种方法可以实现这一点,但是恕我直言,你的设计需要另一个转折来满足这些要求:

    < li >在第三方代理和您的表模型之间只有一个协调点。 < li >不要写很多实际上做同样事情的方法:DRY原则 < li >在正确的时间处理行动。 < li >所有的责任都必须明确划分。

我在想,一些接近中介模式的东西(不完全是这种模式,而是一些接近的东西)可能会帮助您封装协调逻辑并解耦同一事务中涉及的第三方代理和表模型。例如,考虑这个原型类:

public abstract class Coordinator {

    /*
     * protected class members so subclasses can access these directly
     */

    protected ShipperAgent shipperAgent;
    protected DefaultTableModel tableModel;

    public Coordinator(ShipperAgent sa, DefaultTableModel tm) {
        shipperAgent = sa;
        tableModel = tm;
    }

    public abstract void notifyAndAddRow(Object[] rowData);

    public abstract void notifyAndDeleteRow(int rowIndex);
}

由于您已经设法在调用add车辆(…)远程车辆(…)方法时识别出正确的表模型,您可能也可以这样做来识别正确的协调器并委派通知第三方代理和更新表模型的任务。例如:

ShipperAgent sa = new ShipperAgent(...);
DefaultTableModel model1 = new DefaultTableModel(...);
DefaultTableModel model2 = new DefaultTableModel(...);

Coordinator coordinator1 = new Coordinator(sa, model1) {
    @Override
    public void notifyAndAddRow(Object[] rowData) {
        this.shipperAgent.newTruck((String) rowData[0]);
        this.tableModel.addRow(rowData); // do this in the EDT
    }

    @Override
    public void notifyAndDeleteRow(int rowIndex) {
        String truck = (String)this.tableModel.getValueAt(rowIndex, 0);
        this.shipperAgent.removeTruck(truck);
        this.tableModel.removeRow(rowIndex); // do this in the EDT
    }
};

Coordinator coordinator2 = new Coordinator(sa, model2) {
    @Override
    public void notifyAndAddRow(Object[] rowData) {
        this.shipperAgent.activateTruck((String) rowData[0]);
        this.tableModel.addRow(rowData); // do this in the EDT
    }

    @Override
    public void notifyAndDeleteRow(int rowIndex) {
        String truck = (String)this.tableModel.getValueAt(rowIndex, 0);
        this.shipperAgent.removeTruck(truck);
        this.tableModel.removeRow(rowIndex); // do this in the EDT
    }
};

然后您的< code>addVehicle(...)和< code>removeVehicle(...)方法可能如下所示:

public void addVehicle(Coordinator coordinator, String s1, String s2) {
    coordinator.notifyAndAddRow(new Object[]{s1, s2});
}

public void removeVehicle(Coordinator coordinator, int index) {
    coordinator.notifyAndDeleteRow(index);
}

当然,正如我所说,当你调用addVehicle(...)和删除Vehicle(...)方法时,你将不得不设法识别正确的协调器实例,但我认为你现在有解决你的问题所需的抽象。

 类似资料:
  • 我在JavaFX中尝试从表视图中选择单行时遇到了一些问题。 以下是我如何使用数据库中的数据填充表: 但是,当我尝试插入setSelectionMode代码时,出现错误。它告诉我找不到符号符号:方法setSelectionMode(int)位置:class TableView 我记得当我在JavaSwing中创建table时,我用它为table设置了一个模型:DefaultTableModel ta

  • 问题在于,当我点击deletedata-中的userNotes.jsp测试函数中的DELETE按钮时,它会起作用--它会向我显示在按钮上点击的内容的当前值,而不会显示其他内容。它不会从数据库中删除数据,也不会在响应时发送重定向,我需要做什么? userNotes.jsp deletedata-servlet

  • 本文向大家介绍从视图中删除行会从MySQL的基表中删除行吗?,包括了从视图中删除行会从MySQL的基表中删除行吗?的使用技巧和注意事项,需要的朋友参考一下 是的,从视图中删除行从基表中删除行。让我们通过创建一个新表来了解这一点。创建表的查询如下 使用insert命令在表中插入一些记录。查询如下- 使用select语句显示表中的所有记录。查询如下- 以下是输出 让我们创建一个视图。创建视图的查询如下

  • 我已经按照帖子的说明选择了多行 这是我的代码:申请者earch.xhtml 应用程序搜索支持。Java语言 }

  • 问题内容: 我的数据库中有一个表,其中有要删除的重复记录。我不想为此创建具有不同条目的新表。我想要的是从现有表中删除重复的条目,而无需创建任何新表。有什么办法吗? 看到这些都是我的字段: id对于每一行都是唯一的。 L11_data对于相应的动作字段是唯一的。 L11_data具有公司名称,而动作具有行业名称。 因此,在我的数据中,我在L11_data中有各自行业的重复公司名称。 我要拥有的是存储

  • 问题内容: 从视图中删除一行,是否会从创建该视图的基表中删除相应的行?我正在使用MySQL。 问题答案: 是的,它会的。唯一需要注意的是权限。 引用官方文档 有些观点是可更新的。也就是说,您可以在诸如UPDATE,DELETE或INSERT之类的语句中使用它们来更新基础表的内容。为了使视图可更新,视图中的行与基础表中的行之间必须存在一对一的关系。还有某些其他构造会使视图不可更新。