1

私はチャットプロジェクトに取り組んでいます。GUIなしで動作するサーバー側とクライアント側をプログラムしました。コンソールUIだけです。さて、クライアントGUIで作業している間(私が自分でコーディングするのに慣れているのではなく、Netbeansが提供するツールを使用して)、バインディングの問題に固執しました。

ClientGuiクラスの中にはオブジェクトClientがあります。GUIで、クライアントがチャットサーバーに接続されなくなるまで、入力テキストフィールドを無効にします。isConnected()入力テキストフィールドのプロパティを有効にしたクライアントオブジェクトのメソッド(を返す)に( Netbeans GUIを介して)バインドしようとしましたbooleanisConnected変数の値を返すだけでなく、ブール式を組み合わせたものです。したがって、ユーザーがクリックして接続すると成功しますが、入力テキストフィールドの状態は有効に変更されません。

それで、私がそれを得るとき、私はイベントとリスナーと協力して、私の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();
    }
}

ClientGUIクラス:

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)メソッドを使用する必要がないのはなぜですか(有効なプロパティがブール式の「プロパティ」()を追跡するようにしますconnection != null && !connection.isClosed())。また、このトリックのためにsetConnected(value)、実行時に解決されたとしても、実行する必要があります。接続で、古い値を知ることさえできません(もちろん、プライベートvoidsetConnected(booleanvalue)を実行し、それらの場所で何が起こっているかに応じてtrueまたはfalseでこれを呼び出すことができます。プロパティを使用するという私の考えは間違っているようです。アクションやイベントで。

4

2 に答える 2

3

に追加する必要PropertyChangeSupportがありClientます。

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

GUIで

    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フレームワークは、ほとんどの場合、余分な匿名クラスをコーディングすることなく、model / view(uiコンポーネント)間のそのようなバインディングを作成する苦痛を軽減します: https ://github.com/cchantep/melasse

于 2014-01-01T02:34:45.123 に答える