Java 侦听器的代码执行顺序

Java 侦听器的代码执行顺序,java,gwt,listener,vaadin,onclicklistener,Java,Gwt,Listener,Vaadin,Onclicklistener,我已将问题缩小到以下简单的代码片段: this.addClickListener(new ClickListener(){ @Override public void buttonClick(ClickEvent event) { Label spinner = new Label(); spinner.addStyleName("spinner"); ((HorizontalL

我已将问题缩小到以下简单的代码片段:

    this.addClickListener(new ClickListener(){

        @Override
        public void buttonClick(ClickEvent event) {

            Label spinner = new Label();
            spinner.addStyleName("spinner");

            ((HorizontalLayout) event.getButton().getParent()).replaceComponent(event.getButton(), spinner);

        }

    });
它所做的是创建一个加载指示器,并相应地用它替换单击的按钮:

  • 单击=)
  • 好的,让我们(当然也是简化的)通过添加行
    getSaveListener().saveClick()来执行另一个侦听器。总体而言,代码如下所示:

        this.addClickListener(new ClickListener(){
    
            @Override
            public void buttonClick(ClickEvent event) {
    
                Label spinner = new Label();
                spinner.addStyleName("spinner");
    
                ((HorizontalLayout) event.getButton().getParent()).replaceComponent(event.getButton(), spinner);
    
                getSaveListener().saveClick();
    
            }
    
        });
    
    public void replaceComponent(Component oldComponent, Component newComponent) {
    
        // Gets the locations
        int oldLocation = -1;
        int newLocation = -1;
        int location = 0;
        for (final Iterator<Component> i = components.iterator(); i.hasNext();) {
            final Component component = i.next();
    
            if (component == oldComponent) {
                oldLocation = location;
            }
            if (component == newComponent) {
                newLocation = location;
            }
    
            location++;
        }
    
        if (oldLocation == -1) {
            addComponent(newComponent);
        } else if (newLocation == -1) {
            Alignment alignment = getComponentAlignment(oldComponent);
            float expandRatio = getExpandRatio(oldComponent);
    
            removeComponent(oldComponent);
            addComponent(newComponent, oldLocation);
            applyLayoutSettings(newComponent, alignment, expandRatio);
        } else {
            // Both old and new are in the layout
            if (oldLocation > newLocation) {
                components.remove(oldComponent);
                components.add(newLocation, oldComponent);
                components.remove(newComponent);
                components.add(oldLocation, newComponent);
            } else {
                components.remove(newComponent);
                components.add(oldLocation, newComponent);
                components.remove(oldComponent);
                components.add(newLocation, oldComponent);
            }
    
            markAsDirty();
        }
    }
    
    “SaveListener”的设置如下:

        bu.addSaveClickListener(new SaveClickListener() {
    
            @Override
            public void saveClick() {
    
                System.out.println("Yes1");
    
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                System.out.println("Yes2");
    
            }
    
        });
    
    所需的行为是按钮变为微调器,写入“Yes1”,等待4秒,最后写入“Yes2”

  • 单击=)
  • “是的1”
  • “等待”
  • “是的”
  • 问题是它在微调器之前先执行“saveClick”操作:

  • 单击=)
  • “是的1”
  • “等待”
  • “是的”
  • 为什么在“ClickListener”(
    .buttonClick()
    )之前执行“SaveListener”(
    .saveClick()
    )?我怎样才能纠正这个问题


    附加测试: 结果分为:

  • 单击=)
  • “纺纱工!”
  • “是吗?”
  • “是的1”
  • “等待”
  • “是的”

  • 更换部件
    .replaceComponent()
    如下所示:

        this.addClickListener(new ClickListener(){
    
            @Override
            public void buttonClick(ClickEvent event) {
    
                Label spinner = new Label();
                spinner.addStyleName("spinner");
    
                ((HorizontalLayout) event.getButton().getParent()).replaceComponent(event.getButton(), spinner);
    
                getSaveListener().saveClick();
    
            }
    
        });
    
    public void replaceComponent(Component oldComponent, Component newComponent) {
    
        // Gets the locations
        int oldLocation = -1;
        int newLocation = -1;
        int location = 0;
        for (final Iterator<Component> i = components.iterator(); i.hasNext();) {
            final Component component = i.next();
    
            if (component == oldComponent) {
                oldLocation = location;
            }
            if (component == newComponent) {
                newLocation = location;
            }
    
            location++;
        }
    
        if (oldLocation == -1) {
            addComponent(newComponent);
        } else if (newLocation == -1) {
            Alignment alignment = getComponentAlignment(oldComponent);
            float expandRatio = getExpandRatio(oldComponent);
    
            removeComponent(oldComponent);
            addComponent(newComponent, oldLocation);
            applyLayoutSettings(newComponent, alignment, expandRatio);
        } else {
            // Both old and new are in the layout
            if (oldLocation > newLocation) {
                components.remove(oldComponent);
                components.add(newLocation, oldComponent);
                components.remove(newComponent);
                components.add(oldLocation, newComponent);
            } else {
                components.remove(newComponent);
                components.add(oldLocation, newComponent);
                components.remove(oldComponent);
                components.add(newLocation, oldComponent);
            }
    
            markAsDirty();
        }
    }
    
    public void replaceComponent(组件旧组件、组件新组件){
    //获取位置
    int oldLocation=-1;
    int newLocation=-1;
    int位置=0;
    for(final Iterator i=components.Iterator();i.hasNext();){
    最终组件=i.下一个();
    如果(组件==旧组件){
    oldLocation=位置;
    }
    如果(组件==新组件){
    新地点=地点;
    }
    位置++;
    }
    如果(oldLocation==-1){
    添加组件(新组件);
    }else if(newLocation==-1){
    对齐对齐=getComponentAlignment(旧组件);
    浮动expandRatio=getExpandRatio(oldComponent);
    移除组件(旧组件);
    添加组件(新组件、旧位置);
    applyLayoutSettings(新组件、对齐、扩展比率);
    }否则{
    //布局中既有旧的也有新的
    如果(旧位置>新位置){
    组件。移除(旧组件);
    组件。添加(新位置、旧组件);
    组件。移除(新组件);
    组件。添加(旧位置、新组件);
    }否则{
    组件。移除(新组件);
    组件。添加(旧位置、新组件);
    组件。移除(旧组件);
    组件。添加(新位置、旧组件);
    }
    markAsDirty();
    }
    }
    
    从:

    替换组件

    • 公共void替换组件(组件oldComponent, 组件(新组件)
    在不改变位置的情况下,将容器中的零部件替换为另一个零部件

    此方法将零部件替换为另一个零部件,以使新零部件取代旧零部件的位置。如果 旧组件不在容器中,新组件将添加到 集装箱。如果两个组件都已在容器中, 他们的位置互换了。组件附加和分离事件应 注意添加和删除

    • 指定人:

      接口组件容器中的replaceComponent

    参数:

    • oldComponent:将被替换的旧组件
    • 新组件:要更换的新组件

    正如cfrick指出的,侦听器执行完成后,客户端UI将被更新,这是正常的Vaadin行为。在您的示例中,侦听器执行长时间运行的操作(睡眠)。完成后,将更新UI,以便显示最后一个状态

    Vaadin文件涵盖了以下主题:

    这里有一个很好的例子。其思想是在单独的线程中运行该操作,并通过轮询或Vaadin推送更新UI


    备注:由于这个问题已经由cfrick以评论的形式回答,我将以社区维基的形式提供。

    保存按钮看起来很酷。。。。你从哪里得到的?@tharindu_DG几乎就是VAADIN valo facebook的“友好”按钮,带有一个令人敬畏的图标。另外,spinner是原始的VAADIN valo facebook spinner:什么是HorizontalLayout?你知道关于replaceComponent函数的详细信息吗?在我看来,你似乎忽视了vaadin在那里的工作方式。单击按钮将被发送到服务器。然后,服务器在所有单击处理程序中执行您要求的所有操作,但它只是在完成所有操作后返回客户端稍后呈现的绝对最后状态。如果希望具有这种异步行为,您可能希望在计算完成时启用轮询(客户机每隔n毫秒轮询服务器一次以查看状态更改),或者您可能希望调查vaadin-push@cfrick同样,你的评论是正确的答案。你能把它寄出去吗?很明显,一旦Vaadin处理完请求,UI就会在浏览器中重新绘制。他需要启用推送或轮询。