为什么我不能在构建 UI 后修改 vaadin 组件状态?

Why can't I modify a vaadin components state after construction of UI?

我有一个 vaadin UI,它必须是动态的(字段的可见性应根据用户的选择而改变)。我尝试了不同的修改组件状态的方法,如 setEnabled()、setLabel()、...

我有一个 ComboBox,用户可以在其中从 en Enum 中选择值。我向 ComboBox 添加了一个 ValueChangeListener,我在其中尝试修改某些 TextFields 的标签和其他属性(setLabel()、setEnabled()、...)。

我的 ComboBox 有一个像这样的 ValueChangeListener:

myComboBox.addValueChangeListener(event -> refreshLabels(event.getValue()));

首先我写了一个这样的方法:

private void refreshLabels(MyEnum e){
   switch(e){
   case OPTION1: textField1.setLabel("some Text");
                 textField2.setLabel("some Text");
   case OPTION2: textField1.setLabel("some other Text");
                 textField2.setLabel("some other Text");
   }
}

但是用这个方法,Labels不会被更新

然后我又写了一个更新标签的程序:

private String getNewLabel(MyEnum e){
   switch(e){
   case OPTION1: return "some Text";
   case OPTION2: return "some other Text";
   default: return "";
   }
}

我还更改了 ComboBox 的 ValueChangeListener:

myComboBox.addValueChangeListener(event -> textField1.setLabel(getNewLabel(event.getValue())));

使用此代码,我的标签已更新。

如您所见,我有一个解决方法,但使用此解决方法,我必须为每个字段编写一个 getNeLabel 方法,因为更新 ComboBox 时所有字段都需要不同的标签。我不明白,为什么我的第一种方法不起作用,而第二种方法却起作用。在这两种情况下,组件都已添加到布局并显示在 UI 上,当标签更改时。有人可以向我解释一下吗?

实际上,您的第一种方法并没有错,组合框应该正确地 更新 文本字段标签的值。问题出在 switch 块中的代码片段中。你忘了在那里添加 break; 。因此,如果存在 any 匹配,则值始终设置为第二个(最后一个)选项。 (在第二种情况下,您通过从方法返回来终止 switch 的执行,因此它在那里工作)

来自oracle tutorial

Each break statement terminates the enclosing switch statement. Control flow continues with the first statement following the switch block. The break statements are necessary because without them, statements in switch blocks fall through: All statements after the matching case label are executed in sequence, regardless of the expression of subsequent case labels, until a break statement is encountered.

这对我来说是正确的:

 TextField textField1 = new TextField("first");
 TextField textField2 = new TextField("second");
//Some method here
 ComboBox<MyEnum> cb=new ComboBox<>();
 cb.setItems(MyEnum.values());
 cb.addValueChangeListener(event->{
        refreshLabels(event.getValue());
 });
 add(cb);
 add(textField1);
 add(textField2);
//End of a method here
 private void refreshLabels(MyEnum e){
             switch(e){
             case FIRST: textField1.setLabel("some Text");
                     textField2.setLabel("some Text");
                     break;
             case SECOND: textField1.setLabel("some other Text");
                     textField2.setLabel("some other Text");
                     break;
             }
     }