2012-08-17 98 views
1

我正在處理我的聊天項目。我編寫了沒有GUI的服務器和客戶端,只是控制檯UI。現在,在處理客戶端GUI(使用Netbeans提供的工具,而不是我自己編寫的代碼)時,我堅持了綁定問題。將Swing GUI組件的屬性綁定到自定義類方法(屬性)

裏面的ClientGui class我有Client對象。在我的GUI中,我希望禁用輸入文本字段,直到客戶端未連接到聊天服務器。我試圖綁定(通過Netbeans GUI)我的輸入文本框的屬性啓用該客戶端對象的方法isConnected()(返回boolean)。 isConnected不只是返回某個變量的值,而是組合的布爾表達式。所以當用戶單擊連接時,它會成功,但輸入文本字段不會將其狀態更改爲啓用狀態。

因此,當我得到它,我必須與事件和聽衆合作,並在我的Client類中通知?但是,那麼綁定點又是什麼呢,因爲我可以在我的Client上觸發事件,並且我的輸入字段可以偵聽客戶端連接的事件?

所以我提供了我的代碼塊。

Client類:(您可能會看到行動的聽衆和事件的某些行,我沒有刪除它們,只是試行)

public class Client { 
    private ClientListener listener; 
    private ClientSender sender; 
    private Socket connection; 

    private boolean finnish = false; 
    private PropertyChangeEvent connected; 

    public Client(String hostname, int port) throws UnknownHostException, IOException { 
     connection = new Socket(hostname, port); 
    } 

    public void start() { 
     try { 
      connected = new PropertyChangeEvent(this, "connected", null, connection); 

      sender = new ClientSender(new ObjectOutputStream(connection.getOutputStream())); 
      Thread senderThread = new Thread(sender); 
      senderThread.start(); 
      Logger.getLogger(Client.class.getName()).log(Level.INFO, "Sender thread has started"); 

      listener = new ClientListener(new ObjectInputStream(connection.getInputStream())); 
      Thread listenerThread = new Thread(listener); 
      listenerThread.start(); 
      Logger.getLogger(Client.class.getName()).log(Level.INFO, "Listener thread has started"); 


     } catch (IOException ex) { 
      Logger.getLogger(Client.class.getName()).log(Level.SEVERE, "IO problems", ex); 
     } 
    } 

    public ClientSender getSender() { 
     return sender; 
    } 

    public void stop() { 
     sender.stop(); 
     listener.stop(); 
    } 

    public boolean isConnected() { 
     return connection != null && !connection.isClosed(); 
    } 
} 

Client GUI類:

public class ClientGui extends javax.swing.JFrame { 
    private Client client; 

    public boolean getConnected() { 
     System.out.println(client != null && client.isConnected()); 
     return client != null && client.isConnected(); 
    } 

    /** 
    * Creates new form ClientGui 
    */ 
    public ClientGui() { 
     initComponents(); 
    } 

    // GENERATED CODE 

private void tfUserInputKeyPressed(java.awt.event.KeyEvent evt) { 
    if (evt.getKeyCode() == KeyEvent.VK_ENTER) { 
     Message message = new Message("user", tfUserInput.getText()); 
     client.getSender().add(message); 

     tfUserInput.setText(""); 
    } 
} 

private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) { 
    try { 
     client = new Client(tfHostname.getText(), Integer.parseInt(tfPort.getText())); 
     client.start(); 

    } catch (UnknownHostException ex) { 
     Logger.getLogger(ClientGui.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (IOException ex) { 
     Logger.getLogger(ClientGui.class.getName()).log(Level.SEVERE, null, ex); 
    } 

} 

// and somewhere GUI generated code of my binding (also tried with custom code, but no success) 
org.jdesktop.beansbinding.Binding binding = 
org.jdesktop.beansbinding.Bindings.createAutoBinding 
(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, this, 
org.jdesktop.beansbinding.ELProperty.create("${connected}"), listConversation, 
org.jdesktop.beansbinding.BeanProperty.create("enabled"), "listConversationBinding"); 

bindingGroup.addBinding(binding); 

事實上,這是一個JList,但沒關係,因爲我想要這樣的綁定少數組件。 在這裏,我嘗試在GUI窗體中使用僞造方法,該窗體調用客戶端連接(這是因爲不知道如何將Client作爲組件添加)。

我在論壇上看到過,每處都有關於豆類的說法等等。我希望我的Client類具有儘可能少的GUI所需的代碼,接口實現和調用事件觸發事件等。

UPDATE

非常好!謝謝。爲什麼我不能綁定,所以我不必使用setEnabled(value)方法(使該屬性能夠跟蹤布爾表達式「屬性」(connection != null && !connection.isClosed())。另外,由於這個技巧,我必須做setConnected(value),即使解決了這個問題在運行時取決於連接,我什至不知道舊值(當然,我可以做私人無效setConnected(booleanvalue),並根據在這些地方發生的事情真正或假的調用。似乎我的使用財產的想法是錯了,最好在GU用行動或事件做。

回答

3

您應該添加PropertyChangeSupportClient

final PropertyChangeSupport pcs = new PropertyChangeSupport(this); 

    public void addPropertyChangeListener(PropertyChangeListener listener) { 
      this.pcs.addPropertyChangeListener(listener); 
    } 


     boolean connected; 

public boolean isConnected() { 
    return connected; 
} 

public void setConnected(boolean connected) { 
    boolean oldValue = this.connected; 
    this.value = connected; 
    this.pcs.firePropertyChange("connected", oldValue, newValue); 
} 

..... 


    public Client(String hostname, int port) throws UnknownHostException, IOException { 
    connection = new Socket(hostname, port); 
    setConnected(connection != null && !connection.isClosed()); 
} 

public class ClientGui extends javax.swing.JFrame implements PropertyChangeListener 
    ..... 
    propertyChanged(..){ 
     tfUserInput.setEnabled(true); 
    } 

    private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) { 
     try { 
      client = new Client(tfHostname.getText(), Integer.parseInt(tfPort.getText())); 
      client.addPropertyChangeListener(this); 
      client.start(); 
     ..... 
+0

謝謝!請檢查我的第一篇文章中的更新,以下是一些問題:) – EEE 2012-08-17 20:11:59

+0

這不是在GUI設計模式下使用NetBeans IDE的屬性。它只是一個bean屬性。該bean是'Client',該屬性已連接。看看這個http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html#bound'setConnected'修改屬性的真實值,所以它被激發了事件。舊值是事件發生前的值。只要你使用線程,你可能想使用'SwingWorker'而不是'PropertyChangeSupport'。 – 2012-08-17 20:42:03

+0

非常感謝羅馬! – EEE 2012-08-18 07:39:08