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

触发valueChanged事件后从JTable中删除行

慕容光启
2023-03-14

我正在使用ListSelectionListener从所选行更新我的JTextField(countryTxt)。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

public class App {

    JFrame frame = new JFrame();
    JTable table = new JTable();
    DefaultTableModel model = new DefaultTableModel(new Object[][] {},
            new String[] { "Country", "City", "Street" });
    JButton button = new JButton("Remove");
    JTextField countryTxt = new JTextField();

    int row;

    public App() {
        table.setModel(model);
        data();
        table.getSelectionModel().addListSelectionListener(
                new ListSelectionListener() {
                    @Override
                    public void valueChanged(ListSelectionEvent e) {
                        if (!e.getValueIsAdjusting()) {
                            row = table.getSelectedRow();
                            countryTxt.setText((String) model
                                    .getValueAt(row, 0));
                        }
                    }
                });
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                model.removeRow(row);
            }
        });
        frame.add(countryTxt,BorderLayout.NORTH);
        frame.add(new JScrollPane(table), BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
    }

    public void data() {
        model.addRow(new String[] { "USA", "New York", "First street" });
        model.addRow(new String[] { "Russia", "Moscow", "Second street" });
        model.addRow(new String[] { "Japan", "Osaka", "Osaka street" });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new App();
            }
        });
    }
}

但是,当我选择一行并单击按钮时,它会弹出一个异常。当我没有在表格中选择一行并单击按钮时,一切正常。显然,我可以在未触发事件时删除一行。因此,我的问题是:如何在触发事件后删除一行。提前谢谢。

共有3个答案

闾丘卓
2023-03-14

不久前,我不得不找出一个类似的问题,涉及删除列表。这里的主要问题是按钮侦听器对<代码>模型的调用。removeRow(行)正在向模型的选择侦听器发送一个valueChanged事件,然后该侦听器将尝试使用不存在的选择更新文本字段(即列表索引为-1)。我已经对您的代码进行了这些修复,相关部分都标有注释。此代码允许在不引发异常的情况下选择/删除项目。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

public class App {
    JFrame frame = new JFrame();
    DefaultTableModel model = new DefaultTableModel(new Object[][] {},
            new String[] { "Country", "City", "Street" });
    JTable table = new JTable(model);
    JButton button = new JButton("Remove");
    JTextField countryTxt = new JTextField();

    public App() {
        data();
        table.getSelectionModel().addListSelectionListener(
                new ListSelectionListener() {
                    @Override
                    public void valueChanged(ListSelectionEvent e) {
                        if (!e.getValueIsAdjusting()) {
                            // get the current selected row
                            int i = table.getSelectedRow();
                            // if there is a selected row, update the text field
                            if(i >= 0) {
                               countryTxt.setText((String) model
                                    .getValueAt(i, 0));
                            }
                        }
                    }
                });
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                // get the current selected row
                int i = table.getSelectedRow();
                // if there's no selection, but there are some rows,
                // we'll just delete the first row
                if(i < 0 && model.getRowCount() > 0) {
                   i = 0;
                }

                // if we have a valid row to delete, do the deletion
                if(i >= 0) {
                    countryTxt.setText("");
                    model.removeRow(i);
                    table.revalidate();
                }
            }
        });
        frame.add(countryTxt,BorderLayout.NORTH);
        frame.add(new JScrollPane(table), BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
    }

    public void data() {
        model.addRow(new String[] { "USA", "New York", "First street" });
        model.addRow(new String[] { "Russia", "Moscow", "Second street" });
        model.addRow(new String[] { "Japan", "Osaka", "Osaka street" });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new App();
            }
        });
    }
}
方茂
2023-03-14

几点观察:

>

  • 通过键盘或鼠标选择一行会正确更新Country Txt字段。

    您可以使用控件

    不要使用setBound();请使用pack()

    我在没有MigLayout的情况下测试了您的示例,但我认为这与您的发现无关。

  • 刘兴朝
    2023-03-14

    看看getLeadSelectionIndex()方法的javadoc

    返回最近调用setSelectionInterval()、addSelectionInterval()或removeSelectionInterval()的第二个索引参数

    这不是你所期望的。您最好使用JTable#getSelectedRow(),这当然还需要您检查它是否与-1不同。

     类似资料:
    • 问题内容: 范围:两个表。创建新的顾客时,他们会将有关他们的一些信息存储到第二张表中(这也使用触发器完成,它可以按预期工作)。这是我的表结构和关系的示例。 表1-> 顾客 表2-> patron_info 管理员可以管理顾客。当他们选择移走顾客时,将顾客从 桌子1 移开。此时, 表2 没有任何反应。 我只是想创建一个触发器,以便在表1的项目已删除时从表2中删除。这是我尝试过的… 最初,我尝试删除触

    • 我有一个框架,里面有一张桌子和两个按钮。 1) 重复行2)删除行 表a在第三列中的组合 我有一个场景,我复制空白行并点击最后一排的组合框来选择该行,然后单击删除行按钮…然后在删除后,每当我尝试单击任何单元格时,它都会给我以下错误。 下面是相关框架的源代码。

    • 我正在我的网站上使用Ace编辑器(到目前为止已经很棒了!)。我需要捕捉编辑更改的每一个时刻的一些文本。我给编辑器的id是“ACE_JavaScript_Editor”。当我使用: 每当我向编辑器添加文本时,它就会激发,但当我在编辑器中删除文本时,它不会激发。对于一个看似简单的问题,我还没有找到一个优雅的解决方案。根据我的经验和我在网上读到的东西,“KeyUp”和“KeyDown”在Ace edit

    • 我的Jtable有一个listSelectionListener: 我创建了一个按钮来删除带有事件的Jtable的所有行: 如果我在没有选择任何行的情况下按下按钮,则不会出现错误,但当我选择一行,然后按下按钮时,会出现以下错误: 当表没有ListSseltionListener时,不会发生这种情况。我哪里错了? 提前感谢您的帮助。

    • 我正在使用AbstractTableModel,并试图从JTable中删除所选行。 我能够从表中选择特定的行;但当我单击delete按钮时,所选行变为空(即所选行中的所有数据变为空),最后一行将从JTable中删除。 我认为可能是fireTableRowsDeleted()不起作用。请在这方面帮助我。我已经搜索了stackoverflow,但找不到解决方案。 请在下面找到我的代码。 //删除按钮侦

    • 我正在尝试更新JTable(或data?)的行在我对一行执行删除操作后,当选择另一行时,可以编辑所选行。当前删除该行将使已删除行下方的行上移,但如果选择了该行号并尝试进行编辑,则会返回(JOptionPane),就像未选择任何内容一样。它似乎没有“刷新”数据(?)。 这是一个SCCE,希望有人可以运行它并指出问题。我试着尽可能地缩小它,以便于复制/粘贴: 我在这里看到这个问题的各种形式都有一些不同