2013-03-04 36 views
6

這是我的代碼:爲什麼JTextField.setText將火前的changedUpdate的DocumentListener的中的removeUpdate()()?

import javax.swing.*; 
import javax.swing.event.DocumentEvent; 
import javax.swing.event.DocumentListener; 
import javax.swing.text.Document; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

public class Frame extends JFrame { 

    private JTextField txt1 = new JTextField(10); 
    private JTextField txt2 = new JTextField(10); 
    private JButton btn = new JButton("Set Text"); 

    public Frame() { 
     super("Latihan"); 
     setLayout(new FlowLayout()); 
     btn.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       txt1.setText("TEST"); txt2.setText("TEST2"); 
      } 
     }); 

     txt1.getDocument().addDocumentListener(new TheDocumentListener("txt1")); 
     txt2.getDocument().addDocumentListener(new TheDocumentListener("txt2")); 

     add(txt1); 
     add(txt2); 
     add(btn); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     pack(); 
     setVisible(true); 
    } 

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

class TheDocumentListener implements DocumentListener { 

    private String source; 

    public TheDocumentListener(String source) { 
     this.source = source; 
    } 
    @Override 
    public void insertUpdate(DocumentEvent e) { 
     System.out.println("insertUpdate from " + source); 
    } 

    @Override 
    public void removeUpdate(DocumentEvent e) { 
     System.out.println("removeUpdate from " + source); 
    } 

    @Override 
    public void changedUpdate(DocumentEvent e) { 
     System.out.println("changedUpdate from " + source); 
    } 
} 

當我在JButton的點擊,第一次,只有insertUpdate()將被稱爲:

insertUpdate from txt1 
insertUpdate from txt2 

但如果我再次點擊該按鈕,removeUpdate()將被稱爲前insertUpdate()

removeUpdate from txt1 
insertUpdate from txt1 
removeUpdate from txt2 
insertUpdate from txt2 

這是預期的行爲,或者一些錯誤在我的代碼?

我可以insertUpdate執行JTextField.setText時正在叫的唯一方法?我想確保removeUpdate僅在用戶刪除文本字段中的文本時被調用。怎麼做?

回答

5

這是字符串替換的預期行爲。 setText()實際上所做的是刪除整個字符串並設置一個新字符串。這裏是JTextField.setText()實現:

public void setText(String t) { 
    try { 
     Document doc = getDocument(); 
     if (doc instanceof AbstractDocument) { 
      ((AbstractDocument)doc).replace(0, doc.getLength(), t,null); 
     } 
     else { 
      doc.remove(0, doc.getLength()); 
      doc.insertString(0, t, null); 
     } 
    } catch (BadLocationException e) { 
    UIManager.getLookAndFeel().provideErrorFeedback(JTextComponent.this); 
    } 
} 

正如你所看到的,AbstractDocument.replace()AbstractDocument文檔執行。否則,執行remove()insert()

AbstractDocument.replace()文檔:

刪除文本的區域偏離到偏移+長度,並且 文本替換它。它是由執行情況本 是如何實現的,一些實現可將此視爲兩個不同的 操作:a刪除後插入,其他人可能治療 替換爲一個原子操作。

所以它依賴於文件執行。例如PlainDocument繼承了AbstractDocument的基本實現。 A PlainDocument是文本字段的默認文檔。

如果需要的話,也可能安裝文件過濾器,您可以隨時創建你自己的文件執行。有關詳細信息,請參閱Using Text Components教程。不知道,但是你試圖實現這種行爲變化的原因是什麼。

+1

原因是模擬JTextField綁定,因爲setText()沒有綁定。當涉及到相互綁定時,它應該是:更改爲其他綁定屬性將傳播到JTextField.text;並調用JTextField.text應傳播到綁定的屬性。但是現在真正發生的變化是JTextField.text有時會觸發1或2個文檔偵聽器事件,並且很難決定何時停止相互綁定。 – jocki 2013-03-05 04:21:59

相關問題