代码之家  ›  专栏  ›  技术社区  ›  SDS

Vaadin 8.5.1-行更新后刷新网格

  •  1
  • SDS  · 技术社区  · 6 年前

    当一行的it属性发生更改时,我使用 grid.getDataProvider().refreshItem(selectedRow) grid.getDataProvider().refreshAll()

    我得说清楚 grid.setItems()

    我正在使用下面的代码片段创建网格

        msgGrid = new ABSMsgGrid();
    
        List<ConsoleEntry> messageEntryList = new ArrayList<>();
        if (inputConsole != null) {
            messageEntryList.addAll(inputConsole.getMessageEntryList());
        }
    
        msgGridDataProvider = new ListDataProvider<ConsoleEntry>(messageEntryList) {
    
            @Override
            public Object getId(ConsoleEntry item) {
                return item.getId();
            }
        };
    
        msgGrid.setDataProvider(msgGridDataProvider);
    
    
    
    //on changing property of the grid row, i use the below snippet
    private void handleHideRowMenuItem(GridContextMenu<ConsoleEntry> contextMenu, ConsoleEntry selectedConsoleItem) {
            if (!selectedConsoleItem.isHidden()) {
                hideRowMenuItem = contextMenu.addItem("Hide Row", VaadinIcons.EYE_SLASH, selectedMenuItem -> {
                        selectedConsoleItem.hide();
                        **msgGridDataProvider.refreshItem(selectedConsoleItem);**
                    }
                });
            }
    }
    
    public class ConsoleEntry {
    
            @Override
            public boolean equals(Object obj) {
                // TODO Auto-generated method stub
                if (obj instanceof ConsoleEntry) {
                    ConsoleEntry temp = (ConsoleEntry) obj;
                    String msgRef2 = temp.getMsgRef();
                    return this.getMsgRef().equalsIgnoreCase(msgRef2);
                }
                return false;
            }
    
            @Override
            public int hashCode() {
                // TODO Auto-generated method stub
                return super.hashCode();
            }
    
            public String getId(){
                return this.getMsgRef();
            }
    }       
    

    我也看到过类似的问题,但没有一个解决方案奏效。

    How to refresh the vaadin Grid after you change something?

    Vaadin - Refresh grid after row modification

    如果有人能分享如何解决这个问题的建议,我将不胜感激

    短暂性脑缺血发作

    2 回复  |  直到 6 年前
        1
  •  4
  •   André Schild    6 年前

    要使一个项被视为同一个项(以及刷新工作),您需要正确地实现 equals() hashCode() 对象上的方法。

    从文件中

    公共无效刷新项(T项)

    从接口复制的说明:数据提供程序

    DataProviderListeners,该项已被更新或替换为 新实例。

    equals(Object)和#hashCode()将新旧项实例视为相等,或者

    应该实现DataProvider.getId(对象)以返回 适当的标识符。

    除此之外,您还应该创建 ListDataProvider 列表数据提供程序

        2
  •  1
  •   Basil Bourque    6 年前

    作为 correct Answer by Schild 说,你必须 override your equals and hashCode

    对于数据驱动的业务对象,这通常意味着只需查看对象上的标识符,该标识符是您在数据库中的主键(如果您使用数据库,则会是主键)。

    如下例所示,我们的 Status 类有一个 UUID universally unique identifier (UUID) (128位值,规范地显示为36个字符的十六进制字符串,带有连字符)。我们的 等于 哈希码 只考虑对象的一个成员。

    @Override
    public boolean equals ( Object obj ) {  // Compare the UUID member named `uuid`.
        if ( obj == this ) { return true; }
        if ( obj instanceof Status ) { return this.getUuid().equals( ( ( Status ) obj ).getUuid() ); }
        return false;
    }
    
    @Override
    public int hashCode () {
        return Objects.hashCode( this.uuid );
    }  // Compare the UUID member named `uuid`.
    

    示例应用程序

    enter image description here

    在本例中,我们跟踪三个设备。一个 地位 对象表示每个对象。

    NativeSelect 在Vaadin中),并单击某个按钮。在这里选择行是不相关的。

    为了您的启发,我在 Grid . 这两种方法在Vaadin业务应用程序中都很常见:

    • 修改现有 对象支持 网格
    • 替换目标 对象,但在其id字段中使用相同的标识符值。

    例如,在某些情况下,可以编写数据存储库服务代码以始终返回新实例。在其他情况下,我们可能有意地用改变来更新现有对象。

        private void updateByModifying ( Status s , Integer integer ) {
            s.setCurrentStatus( integer );
            grid.getDataProvider().refreshItem( s );
        }
    
        private void updateByInstantiating ( Status s , Integer integer ) {
            boolean removed = statuses.remove( s );
            Status replacement = new Status( s.getUuid() , s.getName() , integer );
            boolean added = statuses.add( replacement );
            grid.getDataProvider().refreshItem( replacement );
        }
    

    在本演示中,使用 Update row by 弹出式菜单(也称为下拉列表)。这两种方法都是通过调用 DataProvider::refreshItem . 注意,这两种方法都依赖于 等于 哈希码 正在正确实施。

    Refresh all 显示使用的按钮 DataProvider::refreshAll 方法。

    源代码

    • MyUI.java (进入瓦丁)
    • Status.java (我们的业务对象,POJO)
    • StatusLayout

    MyUI.java

    package com.basilbourque.example;
    
    import javax.servlet.annotation.WebServlet;
    
    import com.vaadin.annotations.Theme;
    import com.vaadin.annotations.VaadinServletConfiguration;
    import com.vaadin.server.VaadinRequest;
    import com.vaadin.server.VaadinServlet;
    import com.vaadin.ui.*;
    
    import java.util.List;
    import java.util.UUID;
    
    /**
     * This UI is the application entry point. A UI may either represent a browser window
     * (or tab) or some part of an HTML page where a Vaadin application is embedded.
     * <p>
     * The UI is initialized using {@link #init(VaadinRequest)}. This method is intended to be
     * overridden to add component to the user interface and initialize non-component functionality.
     */
    @Theme ( "mytheme" )
    public class MyUI extends UI {
    
        @Override
        protected void init ( VaadinRequest vaadinRequest ) {
            Layout layout = new StatusLayout();
            this.setContent( layout );
        }
    
        @WebServlet ( urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true )
        @VaadinServletConfiguration ( ui = MyUI.class, productionMode = false )
        public static class MyUIServlet extends VaadinServlet {
        }
    }
    

    Status.java状态

    package com.basilbourque.example;
    
    import java.util.Objects;
    import java.util.UUID;
    
    public class Status {
        // Members.
        private UUID uuid;
        private String name;
        private Integer currentStatus;  // 1 = Good, 0 = okay, -1 = Bad.
    
        // Constructor.
        public Status ( UUID uuid , String name , Integer currentStatus ) {
            this.uuid = uuid;
            this.name = name;
            this.currentStatus = currentStatus;
        }
    
        // -----------|  Object  |-------------------------
    
        @Override
        public boolean equals ( Object obj ) {  // Compare the UUID member named `uuid`.
            if ( obj == this ) { return true; }
            if ( obj instanceof Status ) { return this.getUuid().equals( ( ( Status ) obj ).getUuid() ); }
            return false;
        }
    
        @Override
        public int hashCode () {
            return Objects.hashCode( this.uuid );
        }  // Compare the UUID member named `uuid`.
    
        @Override
        public String toString () {
            return "Status{ " +
            "uuid=" + uuid +
            " | name='" + name + '\'' +
            " | currentStatus=" + currentStatus +
            " }";
        }
    
        // -----------|  Accessors  |-----------------------------
    
        public UUID getUuid () {
            return uuid;
        }
    
        public void setUuid ( UUID uuid ) {
            this.uuid = uuid;
        }
    
        public String getName () {
            return name;
        }
    
        public void setName ( String name ) { this.name = name; }
    
        public Integer getCurrentStatus () {
            return currentStatus;
        }
    
        public void setCurrentStatus ( Integer currentStatus ) {
            this.currentStatus = currentStatus;
        }
    }
    

    StatusLayout.java状态布局

    package com.basilbourque.example;
    
    import com.vaadin.data.provider.ListDataProvider;
    import com.vaadin.ui.*;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;
    import java.util.UUID;
    
    public class StatusLayout extends VerticalLayout {
        // Members
        List< Status > statuses;
        Grid< Status > grid;
    
        final List< Integer > numbers = List.of( 1 , 0 , - 1 );
        NativeSelect< Integer > numberPopup;
        NativeSelect< Boolean > updatyByModifyingOrInstantiating;
        Button setPump, setCamera, setSensor, refreshAllButton;
    
        // Constructor
        public StatusLayout () {
    
            statuses = new ArrayList<>( 3 );
            statuses.add( new Status( UUID.fromString( "1c0d183e-c2ba-11e8-a355-529269fb1459" ) , "Pump" , numbers.get( 0 ) ) );
            statuses.add( new Status( UUID.fromString( "2490c74e-1aac-4d71-9a2c-880628dcfc28" ) , "Camera" , numbers.get( 1 ) ) );
            statuses.add( new Status( UUID.fromString( "6ae07414-f557-4a1e-a552-cb5ec5f48476" ) , "Sensor" , numbers.get( 2 ) ) );
    
            // Create a grid bound to the list
            grid = new Grid<>( Status.class );
            grid.setCaption( "Equipment Status" );
            grid.setItems( statuses );
    //        grid.addColumn( Status :: getName ).setCaption( "Name" );
    //        grid.addColumn( Status :: getCurrentStatus ).setCaption( "Status" );
    
            updatyByModifyingOrInstantiating = new NativeSelect<>( "Update row by: " , List.of( Boolean.TRUE , Boolean.FALSE ) );
            updatyByModifyingOrInstantiating.setValue( Boolean.TRUE );
            updatyByModifyingOrInstantiating.setItemCaptionGenerator( ( ItemCaptionGenerator< Boolean > ) item -> item ? "modifying" : "instantiating" );
    
            Label valueSetterLabel = new Label( "Set status:" );
            numberPopup = new NativeSelect<>();
            numberPopup.setItems( numbers );
            numberPopup.setValue( numbers.get( 1 ) );
    //        numberPopup.setItemCaptionGenerator( item -> List.of( "Good" , "Okay" , "Bad" ).get( numbers.indexOf( item ) ) );  // Display words rather than the underlying number.
    
            // The `buttonClick` method below has logic depending on match between button name and `name` property on `Status` objects in grid.
            setPump = new Button( statuses.get( 0 ).getName() );  // Pump
            setPump.addClickListener( this :: buttonClick );
            setCamera = new Button( statuses.get( 1 ).getName() ); // Camera
            setCamera.addClickListener( this :: buttonClick );
            setSensor = new Button( statuses.get( 2 ).getName() );   // Sensor
            setSensor.addClickListener( this :: buttonClick );
    
            refreshAllButton = new Button( "Refresh all" );
            refreshAllButton.addClickListener( clickEvent -> grid.getDataProvider().refreshAll() );
    
            // Arrange
            grid.setWidth( 100 , Unit.PERCENTAGE );
    
            HorizontalLayout valueSetterBar = new HorizontalLayout();
            valueSetterBar.addComponents( valueSetterLabel , numberPopup , setPump , setCamera , setSensor );
            valueSetterBar.setComponentAlignment( valueSetterLabel , Alignment.MIDDLE_CENTER );
            valueSetterBar.setComponentAlignment( numberPopup , Alignment.MIDDLE_CENTER );
            valueSetterBar.setComponentAlignment( setPump , Alignment.MIDDLE_CENTER );
            valueSetterBar.setComponentAlignment( setCamera , Alignment.MIDDLE_CENTER );
            valueSetterBar.setComponentAlignment( setSensor , Alignment.MIDDLE_CENTER );
    
            addComponents( grid , updatyByModifyingOrInstantiating , valueSetterBar , refreshAllButton );
        }
    
        private void buttonClick ( Button.ClickEvent clickEvent ) {
            System.out.println( "TRACE - Setting " + clickEvent.getButton().getCaption() + " to " + this.numberPopup.getValue().toString() );
            // Find the `Status` object in the `List` whose name matches the name of the button clicked by user.
            Optional< Status > optionalStatus = statuses.stream().filter( status -> status.getName().equals( clickEvent.getButton().getCaption() ) ).findFirst();
            // We expect the matching `Status` to always be found. If not, throw exception.
            Status s = optionalStatus.orElseThrow( () -> new IllegalStateException( "Failed to find expected item in list of statuses: " + clickEvent.getButton().getCaption() ) );
            Integer valueToSet = this.numberPopup.getValue();
            // Set the `currentStatus` property on the `Status` object to the value of the selected popup menu item.
            // Try either updating by modifying existing row or by instantiating a new one.
            // Comment-out either of the next two lines.
            if(updatyByModifyingOrInstantiating.getValue().equals( Boolean.TRUE )) {
                this.updateByModifying( s , valueToSet );
            } else {
                this.updateByInstantiating( s , valueToSet );
            }
        }
    
        private void updateByModifying ( Status s , Integer integer ) {
            s.setCurrentStatus( integer );
            grid.getDataProvider().refreshItem( s );
        }
    
        private void updateByInstantiating ( Status s , Integer integer ) {
            boolean removed = statuses.remove( s );
            Status replacement = new Status( s.getUuid() , s.getName() , integer );
            boolean added = statuses.add( replacement );
            grid.getDataProvider().refreshItem( replacement );
        }
    }