我正在处理我的聊天项目。我编写了无需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
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,接口实现和触发事件调用等所需的最少代码。
更新
非常好!谢谢。为什么我不能绑定所以我不必使用setEnabled(value)
方法(使该启用的属性跟踪布尔表达式“property”(connection != null && !connection.isClosed()
)。另外,由于这个技巧,我必须做setConnected(value)
,即使这在运行时根据连接解决了,我甚至无法知道旧值(当然我可以做私有空setConnected(booleanvalue)
并用true或false调用它取决于在那些地方发生的事情。似乎我的使用财产的想法是错误的,更好地处理行动或事件。
答案 0 :(得分: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();
.....
答案 1 :(得分:0)
Melasse框架缓解了模型/视图(ui组件)之间的这种绑定,在大多数情况下甚至无需编写额外的匿名类:https://github.com/cchantep/melasse