自己写代码 - HelloHi开发流水账 四 不止是String

最起码消息要包含发言人的信息吧,现在这样子连我说的还是对方说的话都区分不出来。String是不能胜任了,新加HiMessage类。 HiMessage放在客户端还是服务端呢?这取决于HiMessage是否要用于异步调用的返回类型。客户端的代码都要编译成Javascript,虽 说我不懂这玩意,但是我感觉它效率肯定快不了,高举云计算的口号,客户端尽量不留逻辑,得,updateMessages还就返回字符串数组吧,告诉我怎 么显示就行。将来哪怕要更具说话人改颜色,大不了改成用HTML,那也还是字符串。

添加HiMessage类

public class HiMessage {
    private int clientId;
    private String content;
    
    public HiMessage(int clientId, String content) {
        this.setClientId(clientId);
        this.setContent(content);
    }

    public void setClientId(int clientId) {
        this.clientId = clientId;
    }
    public int getClientId() {
        return clientId;
    }

    public void setContent(String content) {
        this.content = content;
    }
    public String getContent() {
        return content;
    }
}


修 改异步接口的实现

    @Override
    public void sendMessage(int clientId, String message) {
        ArrayList<HiMessage> messageList = clientMgr.getClient(clientId).getRoom().getMessageList();
        messageList.add(new HiMessage(clientId, message));
    }

    @Override
    public String[] updateMessage(int clientId, int lastIndex) {
        ArrayList<HiMessage> messageList = clientMgr.getClient(clientId).getRoom().getMessageList();
        if (lastIndex >= messageList.size()) {
            return null;
        }
        String[] messageArray = new String[messageList.size() - lastIndex];
        for (int i = lastIndex; i < messageList.size(); i++) {
            HiMessage message = messageList.get(i);
            String messageStr = "";
            if (clientId == message.getClientId()) {
                messageStr += "You:";
            } else {
                messageStr += "Stranger:";
            }
            messageStr += message.getContent();
            messageArray[i - lastIndex] = messageStr;
        }
        return messageArray;
    }


现 在已经能区分消息是谁发的了。不过还是有点丑,很明显客户端需要对消息数据做一些处理,现在我突然强烈怀疑返回纯字符串的接口设计。原本想即使要更改显示 的方式,也可以以HTML的方式返回纯字符串。啊,这让我想起了jsp,我不怎么喜欢这个。也许CS之间通信就应该只有数据本身,单纯的数据。改,让 updateMessage返回HiMessage[]类型。然后在客户端就可以得到消息的发布者的clientId,和自己的一对比就知道是自己发的, 还是别人发的。现在,客户端已经有能力自己规定如何显示消息了。也许是时候包装一下了。

创建了一个HiMessageUi类,继承 Composite,负责显示得到的消息,呃,前面的发信人最好换个颜色和字体,然后换一行再空出几个像素开始显示消息正文应该比较好。尝试了很久,利用 Chrome看了看Omegle和web qq的实现,发现GWT的接口不太够用了,什么padding之类的都没有,虽然也可以在Java代码里取得DOM对象进行操作,不过貌似GWT2.0有 了一种叫UiBinder的东西。趁机看了下,感觉还不错,决定用这个来做UI了。

创建UiBinder HiMessageUi

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui">
    <ui:style>
        /* Add CSS here. See the GWT docs on UI Binder for more details */
        .message {
            padding: 5px;
        }
        .sender {
            color: blue;
        }
        .content {
            padding-left: 12px;
            word-break: break-all;
            word-wrap: break-word;
        }
    </ui:style>
    <g:HTMLPanel styleName="{style.message}">
        <g:HTML styleName="{style.sender}" ui:field="sender"/>
        <g:HTML styleName="{style.content}" ui:field="content"/>
    </g:HTMLPanel>
</ui:UiBinder>

 

public class HiMessageUi extends Composite {

    private static HiMessageUiUiBinder uiBinder = GWT
            .create(HiMessageUiUiBinder.class);

    interface HiMessageUiUiBinder extends UiBinder<Widget, HiMessageUi> {
    }

    @UiField
    HTML sender;
    
    @UiField
    HTML content;

    public HiMessageUi(String sender, String content) {
        initWidget(uiBinder.createAndBindUi(this));
        // Can access @UiField after calling createAndBindUi
        this.sender.setText(sender);
        this.content.setText(content);
    }
}

然后修改updateMessage

                @Override
                public void onSuccess(HiMessage[] result) {
                    if (result != null && result.length != 0) {
                        for (HiMessage message : result) {
                            if (message.getClientId() == clientId) {
                                contentPanel.add(new HiMessageUi("You:", message.getContent()));
                            } else {
                                contentPanel.add(new HiMessageUi("Stanger:", message.getContent()));
                            }
                            lastIndex++;
                        }
                        scrollPanel.scrollToBottom();
                    }
                }

感觉还不错。索性彻底把Ui都改成UiBinder的方 式。

新建UiBinder HiChatUi

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui">
    <ui:style>
        .important {
            font-weight: bold;
        }
    </ui:style>
    <g:HTMLPanel>
        <g:DecoratorPanel>
            <g:VerticalPanel>
                <g:ScrollPanel width="500px" height="400px" ui:field="scrollPanel">
                    <g:VerticalPanel ui:field="contentPanel"/>
                </g:ScrollPanel>
                <g:TextArea width="500px" height="120px" ui:field="inputText"/>
            </g:VerticalPanel>
        </g:DecoratorPanel>
    </g:HTMLPanel>
</ui:UiBinder>

再把原来的HelloUi里面相关的内容移到HiChatUi里面

public class HiChatUi extends Composite {

    private static HelloHiUiUiBinder uiBinder = GWT
            .create(HelloHiUiUiBinder.class);

    interface HelloHiUiUiBinder extends UiBinder<Widget, HiChatUi> {
    }

    @UiField
    VerticalPanel contentPanel;
    @UiField
    TextArea inputText;
    @UiField
    ScrollPanel scrollPanel;
    
    private int clientId = -1;
    private HelloServiceAsync service = GWT.create(HelloService.class);
    private int lastIndex = 0;
    
    private Timer timer = new Timer() {

        @Override
        public void run() {
            update();
        }
        
    };
    
    public HiChatUi() {
        initWidget(uiBinder.createAndBindUi(this));
        timer.scheduleRepeating(2000);//ms
    }

    @UiHandler("inputText")
    void onKeyPress(KeyPressEvent event) {
        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
            sendMessage();
        }
    }
    private void initClientId() {
        service.getClientId(new AsyncCallback<Integer>() {

            @Override
            public void onFailure(Throwable caught) {
                // TODO Auto-generated method stub
                
            }

            @Override
            public void onSuccess(Integer result) {
                clientId = result;
            }
            
        });
    }
    
    private void update() {
        if (clientId == -1) {
            initClientId();
        } else {
            service.updateMessage(clientId, lastIndex, new AsyncCallback<HiMessage[]>() {

                @Override
                public void onFailure(Throwable caught) {
                    // TODO Auto-generated method stub
                    
                }

                @Override
                public void onSuccess(HiMessage[] result) {
                    if (result != null && result.length != 0) {
                        for (HiMessage message : result) {
                            if (message.getClientId() == clientId) {
                                contentPanel.add(new HiMessageUi("You:", message.getContent()));
                            } else {
                                contentPanel.add(new HiMessageUi("Stanger:", message.getContent()));
                            }
                            lastIndex++;
                        }
                        scrollPanel.scrollToBottom();
                    }
                }
            
            });
        }

    }
    
    private void sendMessage() {
        String input = inputText.getText();
        if (!input.isEmpty()) {
            service.sendMessage(clientId, input, new AsyncCallback<Void>() {

                @Override
                public void onFailure(Throwable caught) {
                    // TODO Auto-generated method stub
                    
                }

                @Override
                public void onSuccess(Void result) {
                    inputText.setText("");
                    update();
                }
                
            });
        }
    }
}


实际上两个类区别并不大,不过一个是在构造函数里写代码画 Ui,另一个是在xml里面定义Ui,稍微直观一点罢了。原来的HelloUi可以删掉了。















































引用\[1\]和\[2\]中提到了一个错误信息:'NoneType' object has no attribute 'find_all',而引用\[3\]中提供了一个可能导致这个错误的代码片段。这个错误通常发生在使用BeautifulSoup库进行网页解析时。它表示在解析过程中找不到指定的元素或属性。具体来说,'NoneType' object表示在解析过程中找不到目标元素,因此无法使用find_all()方法。 这个错误通常有以下几个可能的原因: 1. 网页的HTML结构发生了变化,导致目标元素无法被正确解析。这可能是因为网页的更新或改版导致的。 2. 使用的选择器或属性名称不正确,无法匹配到目标元素。在使用find()或find_all()方法时,需要确保选择器或属性名称与目标元素的实际情况相匹配。 3. 网页加载过程中出现了错误,导致无法正确获取到网页内容。这可能是网络连接问题或网页服务器问题导致的。 要解决这个错误,可以尝试以下几个方法: 1. 检查网页的HTML结构,确保目标元素存在并且可以被正确解析。 2. 检查选择器或属性名称是否正确,可以通过查看网页源代码或使用开发者工具来确认。 3. 检查网络连接是否正常,可以尝试重新运行代码或使用其他网络环境进行测试。 总之,'NoneType' object has no attribute 'find_all'错误通常是由于解析过程中找不到目标元素导致的,需要仔细检查代码和网页结构来解决。 #### 引用[.reference_title] - *1* *3* [python爬虫遇到 ‘NoneType‘ object has no attribute ‘find_all‘ 问题](https://blog.csdn.net/L_xuewuzhijing/article/details/128615159)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [‘NoneType‘ object has no attribute ‘find_all‘问题解决](https://blog.csdn.net/hellohi1/article/details/117718557)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值