我稍微调整了Quote of the Moment(QOTM),并希望构建一个GUI前端。将对象从DatagramClientHandler
传递到GUI非常简单。但是,GUI引用处理程序似乎很棘手。QuotesGUI
类扩展了JFrame,以利用Netbeans拖放面板轻松添加Swing组件。太冗长了。
显然,解决方案是:
好吧,这取决于有不止一种解决方案。一个可能是
向ChannelHandler注入侦听器,然后将得到通知
收到邮件后。另一种解决方案是发送
收到邮件并注册
对此主题感兴趣的秋千部分,因此他们会收到通知。
https://stackoverflow.com/a/8780410/262852
DatagramClientHandler:
package net.bounceme.dur.netty;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
import java.net.InetSocketAddress;
import java.util.logging.Logger;
import net.bounceme.dur.client.gui.QuotesGUI;
public class DatagramClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
private static final Logger log = Logger.getLogger(DatagramClientHandler.class.getName());
private final QuotesGUI gui = new QuotesGUI();
private volatile Channel channel = null;
DatagramClientHandler() {
log.info("starting..");
gui.setVisible(true);
}
private DatagramPacket getNext() {
DatagramPacket packet = new DatagramPacket(
Unpooled.copiedBuffer("QOTM?", CharsetUtil.UTF_8),
new InetSocketAddress("localhost", 4454));
return packet;
}
@Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
String response = msg.content().toString(CharsetUtil.UTF_8);
log.info(response);
gui.setQuote(response);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.severe(cause.toString());
ctx.close();
}
}
GUI中的示例方法。
public void setQuote(String packet) {
text.setText(packet);
}
最佳答案
首先分开您的责任层...
我可能会先定义某种可以向interface
实例注册的侦听器DatagramClientHandler
。该interface
可以将DatagramClientHandler
中的更改或事件通知感兴趣的各方,并在他们认为合适的情况下处理这些事件...
public interface MessageListener {
public void quoteRecieved(SimpleChannelInboundHandler source, String quote);
public void errorOccured(SimpleChannelInboundHandler source, Throwable cause);
}
然后,您需要为监听器提供支持...
public class DatagramClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
private static final Logger log = Logger.getLogger(DatagramClientHandler.class.getName());
//private final QuotesGUI gui = new QuotesGUI();
private volatile Channel channel = null;
private List<MessageListener> listeners;
DatagramClientHandler() {
listeners = new ArrayList<MessageListener>(25);
//...
}
public synchronized void addMessageListener(MessageListener listener) {
listeners.add(listener);
}
public synchronized void removeMessageListener(MessageListener listener) {
listeners.remove(listener);
}
protected synchronized void fireQuoteRecieved(String quote) {
for (MessageListener listener : listeners) {
listener.quoteRecieved(this, quote);
}
}
@Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
String response = msg.content().toString(CharsetUtil.UTF_8);
log.info(response);
fireQuoteRecieved(response);
}
//...etc...
现在,当您想接收通知时,可以将
MessageListener
实例注册为DatagramClientHandler
实例...您将遇到的问题是,确保您对UI所做的所有更新均在EDT中正确执行...
//...
public void quoteRecieved(SimpleChannelInboundHandler source, final String quote) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
text.setText(packet);
}
});
}
现在,如果您真的想要,可以进一步将代码与另一个
interface
分离。public interface QuoteFactory {
public synchronized void addMessageListener(MessageListener listener);
public synchronized void removeMessageListener(MessageListener listener);
}
然后,这将由
DatagramClientHandler
实现,并且您的用户界面将需要将QuoteFactory
实例传递给它,以便它可以在发生某些事情时注册对通知的兴趣...