Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用于netty客户端的MVC前端_Java_Swing_User Interface_Model View Controller_Netty - Fatal编程技术网

Java 用于netty客户端的MVC前端

Java 用于netty客户端的MVC前端,java,swing,user-interface,model-view-controller,netty,Java,Swing,User Interface,Model View Controller,Netty,我对当前的引用()做了一些修改,并希望构建一个GUI前端。将对象从DatagramClientHandler传递到GUI非常简单。然而,GUI引用处理程序似乎很难 QuotesGUI类扩展了JFrame,以利用Netbeans拖放调色板轻松添加Swing组件。这很冗长 显然,解决办法是: 这要看情况而定,因为有不止一种解决方案。一个可能是 将侦听器注入ChannelHandler,然后该处理程序将收到通知 一旦收到消息。另一个解决方案可能是发送 一旦收到消息,将事件发送到主题,并注册 对该主题感

我对当前的引用()做了一些修改,并希望构建一个GUI前端。将对象从
DatagramClientHandler
传递到GUI非常简单。然而,GUI引用处理程序似乎很难

QuotesGUI
类扩展了JFrame,以利用Netbeans拖放调色板轻松添加Swing组件。这很冗长

显然,解决办法是:

这要看情况而定,因为有不止一种解决方案。一个可能是 将侦听器注入ChannelHandler,然后该处理程序将收到通知 一旦收到消息。另一个解决方案可能是发送 一旦收到消息,将事件发送到主题,并注册 对该主题感兴趣的swing部件,因此他们会得到通知

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

首先,将你的责任分层

我可能会首先定义某种监听器
接口
,它可以注册到
DatagramClientHandler
的实例中。此
接口
将允许相关方收到有关
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...
现在,如果您真的想,您可以进一步使用另一个
接口
来解耦代码

public interface QuoteFactory {
    public synchronized void addMessageListener(MessageListener listener);
    public synchronized void removeMessageListener(MessageListener listener);
}

然后,这将由
DatagramClientHandler
实现,您的UI需要将
QuoteFactory
的实例传递给它,以便它可以在发生某些事情时注册对通知的兴趣…

如果将层分开,GUI应该不(实际)了解处理程序。它还要求您违反Swing的单线程规则(从EDT上下文之外更新UI)。相反,您可以设置一个侦听器
接口
,它可以响应处理程序中的更改并进行适当的更改。这也可以由一个
SwingWorker
来支持,它允许处理程序在一个单独的线程中工作,但提供了安全地更新/通知UI的方法…@MadProgrammer是的,这是我的问题。就用伪代码,你能详细说明一下吗?当然,我想把这些层分开--我只是不知道怎么分开。
//...
public void quoteRecieved(SimpleChannelInboundHandler source, final String quote) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            text.setText(packet);
        }
    });
}
public interface QuoteFactory {
    public synchronized void addMessageListener(MessageListener listener);
    public synchronized void removeMessageListener(MessageListener listener);
}