我已经适应了片刻的引用(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);
}
答案 0 :(得分:1)
首先分开你的责任层......
我可能首先定义一些可以在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
...
您将遇到的问题是确保您对用户界面所做的任何更新都是在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
执行此操作,您的UI将需要传递QuoteFactory
的实例,以便在发生某些事情时可以注册通知...