我正在使用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
事件后删除一行。提前谢谢。
答案 0 :(得分:3)
一些观察结果:
通过键盘或鼠标选择行正确更新countryTxt
字段。
您可以使用控制> - 标签来跳出表格并返回panel
。
不要使用setBounds()
;请使用pack()
。
我在没有MigLayout
的情况下测试了您的示例,但我认为这与您的发现无关。
答案 1 :(得分:3)
查看getLeadSelectionIndex()
方法
从最近一次调用setSelectionInterval(),addSelectionInterval()或removeSelectionInterval()返回第二个索引参数
这不是你所期望的。您最好使用JTable#getSelectedRow()
,当然这仍需要您检查它是否与-1不同。
答案 2 :(得分:2)
我不得不追踪一个类似的问题,涉及清单前一段时间。这里的主要问题是按钮监听器对model.removeRow(row)
的调用是向模型的选择监听器发送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();
}
});
}
}