2012-08-17 103 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