为什么我在Vaadin刷新网页后不能重新设置内容?
Why can't I set the content again after I have fresh the web page in Vaadin?
我遇到了一个奇怪的问题。当我从网络浏览器刷新网页时,我的网络应用程序不会从文本框中删除 text/numbers 或重置复选框。
但是当我刷新网页时,我遇到了问题:
java.lang.IllegalStateException: Can't move a node from one state tree to another. If this is intentional, first remove the node from its current state tree by calling removeFromTree
java.lang.IllegalStateException: Unregistered node was not found based on its id. The tree is most likely corrupted.
和
Assertion error: No child node found with id 28
Assertion error: Node 3 is already registered
那为什么我在Vaadin刷新网页后不能重新设置内容呢?我正在使用 Vaadin 14。如果我不刷新网页,那么我可以随意更改内容。但是只要我不刷新网页,那么我就不会报错。
请注意,我启用了 @PreserveOnRefresh
。没有它,我就不会出错。但是当我刷新页面时 text/values 和所有信息都会消失。
这是我的代码。
@Route("")
@Viewport("width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes, viewport-fit=cover")
@PreserveOnRefresh
public class MainView extends AppLayout {
/**
*
*/
private static final long serialVersionUID = 1L;
public MainView() {
// Get the components
BuildPredictValidateTemplate buildPredictValidateTemplate = new BuildPredictValidateTemplate();
LoadExportTemplate loadExportTemplate = new LoadExportTemplate();
// Create logo and drawer
Image barImage = new Image("img/barImage.png", "Fisherfaces Logo");
barImage.setHeight("55px");
addToNavbar(new DrawerToggle(), barImage);
// Create tabs and add listeners to them
Tab buildPredictValidate = new Tab("Build & Predict & Validate");
buildPredictValidate.getElement().addEventListener("click", e -> {
setContent(buildPredictValidateTemplate.getBuildButtonPredictButtonValidateButtonTextArea());
});
Tab loadExport = new Tab("Load & Export");
loadExport.getElement().addEventListener("click", e -> {
setContent(loadExportTemplate.getSubjectCounterExportButtonUploaders());
});
// Add them and place them as vertical
Tabs tabs = new Tabs(buildPredictValidate, loadExport);
tabs.setOrientation(Tabs.Orientation.VERTICAL);
addToDrawer(tabs);
}
}
和
@Data
//@Component
public class BuildPredictValidateTemplate {
private VerticalLayout buildButtonPredictButtonValidateButtonTextArea;
public BuildPredictValidateTemplate() {
// Create the complete form layout
buildButtonPredictButtonValidateButtonTextArea = createBuildButtonPredictButtonValidateButtonTextArea();
}
private VerticalLayout createBuildButtonPredictButtonValidateButtonTextArea() {
// Text area that works like a terminal
TextArea textTerminal = new TextArea();
textTerminal.setPlaceholder("");
textTerminal.setWidthFull();
textTerminal.setHeightFull();
// Progressbar
ProgressBar progressBar = new ProgressBar();
progressBar.setValue(0);
// Buttons for Builing, Predicting and Validate
Button build = new Button("Build");
build.addClickListener(e -> {
System.out.println("Building");
});
Button predict = new Button("Predict");
predict.addClickListener(e -> {
System.out.println("Predicting");
});
Button validate = new Button("Validate");
validate.addClickListener(e -> {
System.out.println("Validating");
});
// Uploader for prediction
//Upload upload = new PictureUpload().getUpload();
// Add them all now
HorizontalLayout horizon = new HorizontalLayout(build, validate, predict);
return new VerticalLayout(horizon, progressBar, textTerminal);
}
}
还有
@Data
//@Component
public class LoadExportTemplate {
private VerticalLayout subjectCounterExportButtonUploaders;
public LoadExportTemplate() {
// Create layout for the uploads
VerticalLayout uploadsLayout = new VerticalLayout();
// Create subject counter for how many uploaders we should have
NumberField subjectCounter = createSubjectCounter(uploadsLayout);
// Create layout for holding subject counter, export button and uploaders
subjectCounterExportButtonUploaders = createLayoutForSubjectCounterExportButtonUploaders(subjectCounter, uploadsLayout);
}
private VerticalLayout createLayoutForSubjectCounterExportButtonUploaders(NumberField subjectCounter, VerticalLayout uploadsLayout) {
// Create SubjectCounter and ExportButton on a row
Button exportButton = new Button("Export to MATLAB code");
exportButton.addClickListener(e -> {
System.out.println("Exported to MATLAB code.");
});
HorizontalLayout layoutHorizon = new HorizontalLayout(subjectCounter, exportButton);
// Add the uploaders under the horizontal layout
return new VerticalLayout(layoutHorizon, uploadsLayout);
}
private NumberField createSubjectCounter(VerticalLayout uploadsLayout) {
NumberField subjectCounter = new NumberField();
subjectCounter.setValue(1d);
subjectCounter.setHasControls(true);
subjectCounter.setMin(1);
subjectCounter.addValueChangeListener(e-> {
// First clear, then fill with new uploaders
uploadsLayout.removeAll();
for(Double i = 0.0; i < e.getValue(); i++) {
PictureUpload pictureUpload = new PictureUpload();
uploadsLayout.add(pictureUpload.getUpload());
}
});
// Add one to begin with
//PictureUpload pictureUpload = new PictureUpload();
//uploadsLayout.add(pictureUpload.getUpload());
return subjectCounter;
}
}
我相信这是 Vaadin 中的一个错误,至少这不是我所期望的。
我在这里创建了一个问题 https://github.com/vaadin/flow/issues/8286
编辑:
作为解决方法,您可以改为切换可见性。但这需要您将所有组件添加到例如a Div
,并将其设置为内容
例如setContent(new Div(component1, component2));
那么当点击一个选项卡时,您将不得不隐藏除被点击的组件之外的所有组件,例如
getContent().getChildren().forEach(component -> {
boolean visible = component.equals(theComponentIWantToShow);
component.setVisible(visible);
});
我遇到了一个奇怪的问题。当我从网络浏览器刷新网页时,我的网络应用程序不会从文本框中删除 text/numbers 或重置复选框。
但是当我刷新网页时,我遇到了问题:
java.lang.IllegalStateException: Can't move a node from one state tree to another. If this is intentional, first remove the node from its current state tree by calling removeFromTree
java.lang.IllegalStateException: Unregistered node was not found based on its id. The tree is most likely corrupted.
和
Assertion error: No child node found with id 28
Assertion error: Node 3 is already registered
那为什么我在Vaadin刷新网页后不能重新设置内容呢?我正在使用 Vaadin 14。如果我不刷新网页,那么我可以随意更改内容。但是只要我不刷新网页,那么我就不会报错。
请注意,我启用了 @PreserveOnRefresh
。没有它,我就不会出错。但是当我刷新页面时 text/values 和所有信息都会消失。
这是我的代码。
@Route("")
@Viewport("width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes, viewport-fit=cover")
@PreserveOnRefresh
public class MainView extends AppLayout {
/**
*
*/
private static final long serialVersionUID = 1L;
public MainView() {
// Get the components
BuildPredictValidateTemplate buildPredictValidateTemplate = new BuildPredictValidateTemplate();
LoadExportTemplate loadExportTemplate = new LoadExportTemplate();
// Create logo and drawer
Image barImage = new Image("img/barImage.png", "Fisherfaces Logo");
barImage.setHeight("55px");
addToNavbar(new DrawerToggle(), barImage);
// Create tabs and add listeners to them
Tab buildPredictValidate = new Tab("Build & Predict & Validate");
buildPredictValidate.getElement().addEventListener("click", e -> {
setContent(buildPredictValidateTemplate.getBuildButtonPredictButtonValidateButtonTextArea());
});
Tab loadExport = new Tab("Load & Export");
loadExport.getElement().addEventListener("click", e -> {
setContent(loadExportTemplate.getSubjectCounterExportButtonUploaders());
});
// Add them and place them as vertical
Tabs tabs = new Tabs(buildPredictValidate, loadExport);
tabs.setOrientation(Tabs.Orientation.VERTICAL);
addToDrawer(tabs);
}
}
和
@Data
//@Component
public class BuildPredictValidateTemplate {
private VerticalLayout buildButtonPredictButtonValidateButtonTextArea;
public BuildPredictValidateTemplate() {
// Create the complete form layout
buildButtonPredictButtonValidateButtonTextArea = createBuildButtonPredictButtonValidateButtonTextArea();
}
private VerticalLayout createBuildButtonPredictButtonValidateButtonTextArea() {
// Text area that works like a terminal
TextArea textTerminal = new TextArea();
textTerminal.setPlaceholder("");
textTerminal.setWidthFull();
textTerminal.setHeightFull();
// Progressbar
ProgressBar progressBar = new ProgressBar();
progressBar.setValue(0);
// Buttons for Builing, Predicting and Validate
Button build = new Button("Build");
build.addClickListener(e -> {
System.out.println("Building");
});
Button predict = new Button("Predict");
predict.addClickListener(e -> {
System.out.println("Predicting");
});
Button validate = new Button("Validate");
validate.addClickListener(e -> {
System.out.println("Validating");
});
// Uploader for prediction
//Upload upload = new PictureUpload().getUpload();
// Add them all now
HorizontalLayout horizon = new HorizontalLayout(build, validate, predict);
return new VerticalLayout(horizon, progressBar, textTerminal);
}
}
还有
@Data
//@Component
public class LoadExportTemplate {
private VerticalLayout subjectCounterExportButtonUploaders;
public LoadExportTemplate() {
// Create layout for the uploads
VerticalLayout uploadsLayout = new VerticalLayout();
// Create subject counter for how many uploaders we should have
NumberField subjectCounter = createSubjectCounter(uploadsLayout);
// Create layout for holding subject counter, export button and uploaders
subjectCounterExportButtonUploaders = createLayoutForSubjectCounterExportButtonUploaders(subjectCounter, uploadsLayout);
}
private VerticalLayout createLayoutForSubjectCounterExportButtonUploaders(NumberField subjectCounter, VerticalLayout uploadsLayout) {
// Create SubjectCounter and ExportButton on a row
Button exportButton = new Button("Export to MATLAB code");
exportButton.addClickListener(e -> {
System.out.println("Exported to MATLAB code.");
});
HorizontalLayout layoutHorizon = new HorizontalLayout(subjectCounter, exportButton);
// Add the uploaders under the horizontal layout
return new VerticalLayout(layoutHorizon, uploadsLayout);
}
private NumberField createSubjectCounter(VerticalLayout uploadsLayout) {
NumberField subjectCounter = new NumberField();
subjectCounter.setValue(1d);
subjectCounter.setHasControls(true);
subjectCounter.setMin(1);
subjectCounter.addValueChangeListener(e-> {
// First clear, then fill with new uploaders
uploadsLayout.removeAll();
for(Double i = 0.0; i < e.getValue(); i++) {
PictureUpload pictureUpload = new PictureUpload();
uploadsLayout.add(pictureUpload.getUpload());
}
});
// Add one to begin with
//PictureUpload pictureUpload = new PictureUpload();
//uploadsLayout.add(pictureUpload.getUpload());
return subjectCounter;
}
}
我相信这是 Vaadin 中的一个错误,至少这不是我所期望的。
我在这里创建了一个问题 https://github.com/vaadin/flow/issues/8286
编辑:
作为解决方法,您可以改为切换可见性。但这需要您将所有组件添加到例如a Div
,并将其设置为内容
例如setContent(new Div(component1, component2));
那么当点击一个选项卡时,您将不得不隐藏除被点击的组件之外的所有组件,例如
getContent().getChildren().forEach(component -> {
boolean visible = component.equals(theComponentIWantToShow);
component.setVisible(visible);
});