Java/Vaadin-FormLayout自定义隐藏组件实现

Java/Vaadin-FormLayout自定义隐藏组件实现,java,vaadin,vaadin-grid,vaadin8,Java,Vaadin,Vaadin Grid,Vaadin8,我正在vaadin开发一个web应用程序,目前正在尝试实现一个地址簿。我查看了github的官方实现,并试图以此为基础进行构建 我遇到的问题是联系方式。我希望能够单击网格中的一行并打开一个包含信息的表单。类似于他们的例子 但是,该组件没有按预期反应。如果我将组件直接添加到主布局,并尝试切换可见性,则会弄乱视图。我让它工作的唯一方法是根据需要添加和删除组件,尽管我不喜欢这个解决方案,也不美观 下面是当前的实现 package com.example.ecenter.view; import co

我正在vaadin开发一个web应用程序,目前正在尝试实现一个地址簿。我查看了github的官方实现,并试图以此为基础进行构建

我遇到的问题是联系方式。我希望能够单击网格中的一行并打开一个包含信息的表单。类似于他们的例子

但是,该组件没有按预期反应。如果我将组件直接添加到主布局,并尝试切换可见性,则会弄乱视图。我让它工作的唯一方法是根据需要添加和删除组件,尽管我不喜欢这个解决方案,也不美观

下面是当前的实现

package com.example.ecenter.view;

import com.vaadin.data.Binder;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.ui.Button;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Grid;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;

import io.valhala.ecenter.temp.Client;

import java.util.Arrays;
import java.util.List;

@SpringView(name = AddressBookView.VIEW_NAME)
@SpringComponent
public class AddressBookView extends HorizontalLayout implements View
{
    public static final String VIEW_NAME = "Address Book";
    Grid<Client> contactList = new Grid<>(Client.class);
    private List<Client> clients = Arrays.asList(
        new Client("Sernie", "A", "123 Test St.", "test@gmail.gov", "555-555-5554"),
        new Client("Ernie", "B", "123 Test St.", "test@gmail.com", "555-555-5555"),
        new Client("Bernie", "C", "123 Test St.", "test@gmail.net", "555-555-5556"),
        new Client("Ayy", "Lmao", "123 Test St.", "test@gmail.org", "555-555-5557"),
        new Client("Dax", "E", "123 Test St.", "test@gmail.net", "555-555-5558"),
        new Client("Avorion", "F", "123 Test St.", "test@gmail.net", "555-555-5559"),
        new Client("Xanion", "G", "123 Test St.", "test@gmail.net", "555-555-5560"),
        new Client("Trinium", "H", "123 Test St.", "test@gmail.net", "555-555-5561"),
        new Client("Naonite", "I", "123 Test St.", "test@gmail.net", "555-555-5562"),
        new Client("Squillium", "J", "123 Test St.", "test@gmail.net", "555-555-5563"),
        new Client("Picard", "K", "123 Test St.", "test@gmail.net", "555-555-5564"),
        new Client("Richard", "L", "123 Test St.", "test@gmail.net", "555-555-5565"),
        new Client("Rickard", "M", "123 Test St.", "test@gmail.net", "555-555-5566"),
        new Client("Bobby", "N", "123 Test St.", "test@gmail.net", "555-555-5567"),
        new Client("Bob", "O", "123 Test St.", "test@gmail.net", "555-555-5568"),
        new Client("Ron", "P", "123 Test St.", "test@gmail.net", "555-555-5569"),
        new Client("Bill", "Q", "123 Test St.", "test@gmail.net", "555-555-5570"),
        new Client("Greg", "R", "123 Test St.", "test@gmail.net", "555-555-5571"),
        new Client("Juan", "S", "123 Test St.", "test@gmail.net", "555-555-5572"),
        new Client("Squidward", "T", "123 Test St.", "test@gmail.net", "555-555-5573"));

private ContactForm contactForm = new ContactForm();
private TextField filter = new TextField();
private Button addContact = new Button("New Client");

public AddressBookView()
{
    initConfig();
    buildLayout();
}

private void buildLayout() 
{
    HorizontalLayout actionBar = new HorizontalLayout(filter, addContact);
    actionBar.setWidth("100%");
    filter.setWidth("100%");
    actionBar.setExpandRatio(filter, 1);

    VerticalLayout left = new VerticalLayout(actionBar, contactList);
    left.setSizeFull();
    contactList.setSizeFull();
    left.setExpandRatio(contactList, 1);

    HorizontalLayout mainLayout = new HorizontalLayout(left);
    mainLayout.setSizeFull();
    mainLayout.setExpandRatio(left, 1);

    //HorizontalLayout test = new HorizontalLayout(contactForm);
    addComponent(mainLayout);

    //addComponent(test);
    /*
     * even using a different layout still messes it up
     */

    //contactForm.setVisible(false);
}

private void initConfig() 
{
    addContact.addClickListener(event -> 
    {
        addComponent(contactForm);
        contactForm.setClient(new Client());
    });

    filter.setPlaceholder("Search clients...");
    addContact.addStyleName(ValoTheme.BUTTON_PRIMARY);
    //filter.addValueChangeListener(e -> refreshContacts(e.getText()));

    contactList.setSelectionMode(Grid.SelectionMode.SINGLE);
    contactList.setColumns("firstName", "lastName");
    contactList.setItems(clients);

    contactList.asSingleSelect().addValueChangeListener(event -> 
    {
        if(event.getValue() == null)
        {
            removeComponent(contactForm); //quick and dirty workaround
        }
        else
        {
            addComponent(contactForm); //quick and dirty workaround
            /* contactForm.setVisible(true); messes up the entire view */
            contactForm.setClient(event.getValue());
        }
    });
}

@Override
public void enter(ViewChangeEvent event) {
}

private class ContactForm extends FormLayout
{
    private Client client;
    private Button save, delete, cancel;
    private TextField firstName, lastName, email, address, phoneNumber;
    private Binder<Client> binder = new Binder<>(Client.class);
    public ContactForm()
    {
        initConf();
        initLayout();
        setSizeUndefined();
        binder.bindInstanceFields(this);
    }

    public void initConf() 
    {
        save = new Button("Save");
        cancel = new Button("Cancel");

        firstName = new TextField();
        firstName.setPlaceholder("First Name");

        lastName = new TextField();
        lastName.setPlaceholder("Last Name");

        email = new TextField();
        email.setPlaceholder("Email Address");

        address = new TextField();
        address.setPlaceholder("Address");

        phoneNumber = new TextField();
        phoneNumber.setPlaceholder("Phone Number");

    }
    public void initLayout() 
    {
        HorizontalLayout actions = new HorizontalLayout(save, cancel);
        actions.setSpacing(true);

        addComponents(actions, firstName, lastName, email, address, phoneNumber);
    }

    public void setClient(Client client)
    {
        //setVisible(true);
        this.client = client;
        binder.setBean(client);
    }
  }
}
第一幅图显示了将表单添加到布局并将其设置为“隐藏”时视图的反应

第二个和第三个图像显示视图应该如何反应。虽然为了达到预期的效果,我不得不做草率的编码

最后一个问题是:

如何解决此问题?我已经尝试为表单使用一个内部类,并将其创建为自己的类。我唯一的猜测是,在github实现中,他们将UI传递给此表单,其中通讯簿扩展了UI而不是组件


所发生的情况是,您将离开视图的组合是一个未定义大小的水平布局,并将大小设置为完全,再加上隐藏表单,这会产生奇怪的结果。因此,如果使用一些开发人员工具检查生成的元素,您将看到视图水平布局的高度为147px,网格表包装的高度为24px:

如果要将“视图高度”设置为100%,则它将展开以占用所有可用空间,这可能不是您想要的:

因此,只需保留未定义的左侧大小,并丢失主布局您的视图已扩展水平布局,因此只需使用该布局,然后返回使用contactForm.setVisibletrue/false。这样,左侧布局将展开以适应为操作栏+网格计算的任何大小:

private void buildLayout() {
    HorizontalLayout actionBar = new HorizontalLayout(filter, addContact);
    actionBar.setWidth("100%");
    filter.setWidth("100%");
    actionBar.setExpandRatio(filter, 1);

    VerticalLayout left = new VerticalLayout(actionBar, contactList);
    left.setSizeFull();
    left.setExpandRatio(contactList, 1);

    addComponents(left, contactForm);
    contactForm.setVisible(false);
}

另外,如果有人可以通过提供更多关于这种情况下如何计算尺寸的见解来改进此答案,请编辑此答案

发生的情况是,您将离开视图的组合是一个未定义大小的水平布局,并将大小设置为完全加上隐藏表单会产生奇怪的结果。因此,如果使用一些开发人员工具检查生成的元素,您将看到视图水平布局的高度为147px,网格表包装的高度为24px:

如果要将“视图高度”设置为100%,则它将展开以占用所有可用空间,这可能不是您想要的:

因此,只需保留未定义的左侧大小,并丢失主布局您的视图已扩展水平布局,因此只需使用该布局,然后返回使用contactForm.setVisibletrue/false。这样,左侧布局将展开以适应为操作栏+网格计算的任何大小:

private void buildLayout() {
    HorizontalLayout actionBar = new HorizontalLayout(filter, addContact);
    actionBar.setWidth("100%");
    filter.setWidth("100%");
    actionBar.setExpandRatio(filter, 1);

    VerticalLayout left = new VerticalLayout(actionBar, contactList);
    left.setSizeFull();
    left.setExpandRatio(contactList, 1);

    addComponents(left, contactForm);
    contactForm.setVisible(false);
}

另外,如果有人可以通过提供更多关于这种情况下如何计算尺寸的见解来改进此答案,请编辑此答案

什么条件使其无法隐藏?contactList.AssingeSelect.addValueChangeListenerevent->如果事件数据为null,它调用setClientClient客户端,然后该客户端将具有setVisibletrue,但如果我这样做,该表单将永远不会出现。仅当我将组件添加到布局中时才会出现,但这会弄乱网格。因此,行为是:显示网格,然后选择一行,然后在右侧显示包含数据的表单?隐藏表单时,使用所有这些SetSizell和expandRatios勾选大小计算。尝试更改为left.setSizeUndefined&mainLayout.setSizeUndefined并切换回隐藏/显示表单。另外,我认为你不需要主布局,因为你的视图本身就是一个水平布局;只需添加ComponentsLeft,ContactForm您是否尝试过在运行时只添加右侧的小部件?前面的评论是:这似乎是一个复杂的设置。什么条件使它无法隐藏?contactList.asSingleSelect.addValueChangeListenerevent->如果事件数据在那里!=null,它调用setClientClient客户端,然后该客户端将具有setVisibletrue,但如果我这样做,该表单将永远不会出现。仅当我将组件添加到布局中时才会出现,但这会弄乱网格。因此,行为是:显示网格,然后选择一行,然后在右侧显示包含数据的表单?隐藏表单时,使用所有这些SetSizell和expandRatios勾选大小计算。尝试更改为left.setSizeUndefined&mainLayout.setSizeUndefined并切换回隐藏/显示表单。另外,我认为你不需要主布局,因为你的视图本身就是一个水平布局;只需添加组件就可以了,con
TactForm您是否尝试过在运行时在右侧添加小部件?而之前的评论是针对这一点的:这似乎是一个复杂的设置。