Vaadin,通过 setContent() 切换内容不显示
Vaadin, Switching Content via setContent() not displaying
Vaadin 7.6.2
举个例子:
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
public class MyClass extends Panel {
TextField myField = new TextField();
HorizontalLayout hLayout = new HorizontalLayout( myField );
VerticalLayout vLayout = new VerticalLayout( myField );
Button button = new Button( "Press Me" );
public MyClass() {
super();
applySettings();
}
private void applySettings() {
button.addClickListener(new ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
setContent( hLayout );
}
});
vLayout.addComponent( button );
this.setContent( vLayout );
}
}
当我单击按钮时,vLayout 消失,但 hLayout(带有 myField
)没有出现。我缺少哪一步?或者,是否有其他方法可以做到这一点?
如果我添加辅助文本字段,如下所示:
TextField myField = new TextField();
TextField myField2 = new TextField(); // tf2
HorizontalLayout hLayout = new HorizontalLayout( myField );
VerticalLayout vLayout = new VerticalLayout( myField2 ); // tf2
它似乎有效,但我想要实现的是能够使用切换布局中的字段(及其数据)动态切换我的布局。
嗯,看来我可能已经解决了。
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
public class MyClass extends Panel {
TextField myField = new TextField();
HorizontalLayout hLayout = new HorizontalLayout();
VerticalLayout vLayout = new VerticalLayout();
Button button = new Button( "Press Me" );
public MyClass() {
super();
applySettings();
}
private void applySettings() {
button.addClickListener(new ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
vLayout.removeAllComponents(); // this is optional
hLayout.addComponent( myField );
setContent( hLayout );
}
});
vLayout.addComponents( myField, button );
this.setContent( vLayout );
}
}
如果我不在布局构造函数中添加 myField
,而是稍后在代码中添加它,似乎可以工作。
更新
经过更多测试后,似乎无论最后为给定字段调用 addComponent()
哪个布局,该布局都会获取该字段的句柄。这种行为看起来很奇怪,如果有人能解释这是为什么?那将是有启发性的。
一个组件不能同时有 2 个 parent(在你的例子中是 hLayout
& vLayout
),因此如果它已经有一个,Vaadin 会把它从前一个 parent 并将其作为 child 添加到当前 child。这是继承自AbstractComponentContainer的addComponent
方法:
/**
* This only implements the events and component parent calls. The extending
* classes must implement component list maintenance and call this method
* after component list maintenance.
*
* @see com.vaadin.ui.ComponentContainer#addComponent(Component)
*/
@Override
public void addComponent(Component c) {
// Make sure we're not adding the component inside it's own content
if (isOrHasAncestor(c)) {
throw new IllegalArgumentException(
"Component cannot be added inside it's own content");
}
if (c.getParent() != null) {
// If the component already has a parent, try to remove it
AbstractSingleComponentContainer.removeFromParent(c);
}
c.setParent(this);
fireComponentAttachEvent(c);
markAsDirty();
}
如果你在 debug mode, you can somewhat see an image of the composition tree in your browser by adding ?debug
to your URL, something like http://localhost:8080/?debug
Vaadin 7.6.2
举个例子:
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
public class MyClass extends Panel {
TextField myField = new TextField();
HorizontalLayout hLayout = new HorizontalLayout( myField );
VerticalLayout vLayout = new VerticalLayout( myField );
Button button = new Button( "Press Me" );
public MyClass() {
super();
applySettings();
}
private void applySettings() {
button.addClickListener(new ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
setContent( hLayout );
}
});
vLayout.addComponent( button );
this.setContent( vLayout );
}
}
当我单击按钮时,vLayout 消失,但 hLayout(带有 myField
)没有出现。我缺少哪一步?或者,是否有其他方法可以做到这一点?
如果我添加辅助文本字段,如下所示:
TextField myField = new TextField();
TextField myField2 = new TextField(); // tf2
HorizontalLayout hLayout = new HorizontalLayout( myField );
VerticalLayout vLayout = new VerticalLayout( myField2 ); // tf2
它似乎有效,但我想要实现的是能够使用切换布局中的字段(及其数据)动态切换我的布局。
嗯,看来我可能已经解决了。
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
public class MyClass extends Panel {
TextField myField = new TextField();
HorizontalLayout hLayout = new HorizontalLayout();
VerticalLayout vLayout = new VerticalLayout();
Button button = new Button( "Press Me" );
public MyClass() {
super();
applySettings();
}
private void applySettings() {
button.addClickListener(new ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
vLayout.removeAllComponents(); // this is optional
hLayout.addComponent( myField );
setContent( hLayout );
}
});
vLayout.addComponents( myField, button );
this.setContent( vLayout );
}
}
如果我不在布局构造函数中添加 myField
,而是稍后在代码中添加它,似乎可以工作。
更新
经过更多测试后,似乎无论最后为给定字段调用 addComponent()
哪个布局,该布局都会获取该字段的句柄。这种行为看起来很奇怪,如果有人能解释这是为什么?那将是有启发性的。
一个组件不能同时有 2 个 parent(在你的例子中是 hLayout
& vLayout
),因此如果它已经有一个,Vaadin 会把它从前一个 parent 并将其作为 child 添加到当前 child。这是继承自AbstractComponentContainer的addComponent
方法:
/**
* This only implements the events and component parent calls. The extending
* classes must implement component list maintenance and call this method
* after component list maintenance.
*
* @see com.vaadin.ui.ComponentContainer#addComponent(Component)
*/
@Override
public void addComponent(Component c) {
// Make sure we're not adding the component inside it's own content
if (isOrHasAncestor(c)) {
throw new IllegalArgumentException(
"Component cannot be added inside it's own content");
}
if (c.getParent() != null) {
// If the component already has a parent, try to remove it
AbstractSingleComponentContainer.removeFromParent(c);
}
c.setParent(this);
fireComponentAttachEvent(c);
markAsDirty();
}
如果你在 debug mode, you can somewhat see an image of the composition tree in your browser by adding ?debug
to your URL, something like http://localhost:8080/?debug