【问题标题】:Deleting row from JTable after valueChanged event is triggered触发 valueChanged 事件后从 JTable 中删除行
【发布时间】:2012-07-23 08:43:43
【问题描述】:

我正在使用 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();
            }
        });
    }
}

但是当我选择一行并单击 button 时,它会引发我和 ArrayIndexOutOfBounds 异常。当我没有在表中选择一行并单击button 时,一切正常。显然,当valueChanged 事件未触发时,我可以删除一行。所以我的问题是:如何在valueChanged 事件触发后删除一行。提前致谢。

【问题讨论】:

  • 1) 为了尽快获得更好的帮助,请发帖 SSCCE。 2) “请帮忙?” 请提出一个(具体的)问题。
  • 嗯...问题是:为什么我不能在删除数据后将它们添加到表中?
  • 好问题。为什么不将其编辑到 ..question 中。 SSCCE 怎么样?
  • 我“怀疑”它与 int lead = model.getLeadSelectionIndex(); 未返回预期值有关。尝试并确保显示方法只接受可接受范围内的行索引(row >= 0 && row model.getMinSelectionIndex() 代替(这是通过JTablegetSelectedRow() 方法)跨度>
  • 你是对的!我把你的 (row >= 0 && row

标签: java swing jtable listselectionlistener


【解决方案1】:

看看getLeadSelectionIndex()方法的javadoc

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

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

【讨论】:

    【解决方案2】:

    一些观察:

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

    • 您可以使用 Control>-Tab 跳出表格并返回到您的panel

    • 不要使用setBounds();请使用pack()

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

    【讨论】:

      【解决方案3】:

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

      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();
                  }
              });
          }
      }
      

      【讨论】:

      • 我测试了它,它运行良好,没有例外! 8小时后我会给你100分。 :) 非常感谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-02
      • 1970-01-01
      相关资源
      最近更新 更多