2012-07-24 65 views
3

我使用ListSelectionListener從選定行更新我的JTextField(countryTxt)。觸發valueChanged事件後從JTable刪除行

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它trows我和ArrayIndexOutOfBounds例外。當我不在我的表格中選擇一行並單擊button時,一切正常。當valueChanged事件沒有被觸發時,顯然我可以刪除一行。所以我的問題是:如何在valueChanged事件觸發後刪除一行。提前致謝。

+1

1)爲了更快地獲得更好的幫助,請發佈[SSCCE](http://sscce.org/)。 2)*「請幫忙?」*請提出一個(具體的)問題。 – 2012-07-25 00:04:28

+0

嗯......問題是:爲什麼刪除後我的數據不能添加到表中? – 2012-07-25 00:12:04

+0

好問題。爲什麼不把它編輯成..問題。 SSCCE呢? – 2012-07-25 00:18:39

回答

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

我測試了它,它完美的工作,沒有例外!在8小時內,我會給你100分。 :) 萬分感謝! – 2013-02-18 16:29:35

+0

太好了,謝謝!樂意效勞! – 808sound 2013-02-18 16:33:59

3

幾個意見:

  • 通過鍵盤或鼠標選擇一行正確地更新countryTxt領域。

  • 您可以使用控制> - 標籤到標籤出表,回到你的panel

  • 請勿使用setBounds();請使用pack()

  • 我測試了您的示例沒有MigLayout,但我認爲這與您的發現無關。

3

看一看在getLeadSelectionIndex()方法

返回從最近調用中的第二個索引參數對setSelectionInterval(),addSelectionInterval()或removeSelectionInterval()的

的javadoc的

這不是你所期望的。你最好使用JTable#getSelectedRow()這當然仍然需要你檢查它是否與-1不同。