1

我正在做我的聊天项目。我已经编写了无需 GUI 即可工作的服务器和客户端,只需控制台 UI。现在,在处理客户端 GUI 时(使用 Netbeans 提供的工具,而不是我自己编写的代码),我一直遇到绑定问题。

ClientGui课堂内我有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

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、接口实现和触发事件调用等所需的代码。

更新

很好!谢谢你。为什么我不能绑定,所以我不必使用setEnabled(value)方法(使启用的属性跟踪布尔表达式“property”(connection != null && !connection.isClosed())。另外,由于这个技巧我必须做setConnected(value),即使这在运行时解决取决于在连接上,我什至不知道旧值(当然,我可以做私人 voidsetConnected(booleanvalue)并根据这些地方发生的情况用真或假来调用它。似乎我使用属性的想法是错误的,最好这样做与动作或事件。

4

2 回答 2

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();
        .....
于 2012-08-17T19:45:26.573 回答
0

Melasse 框架减轻了在模型/视图(ui 组件)之间进行这种绑定的痛苦,在大多数情况下,甚至无需编写额外的匿名类: https ://github.com/cchantep/melasse

于 2014-01-01T02:34:45.123 回答