gpt4 book ai didi

java - 带有 Activity 编辑器的 Vaadin 双击网格上的按钮会引发异常 ("java.lang.NullPointerException: Editor can' t edit null")

转载 作者:行者123 更新时间:2023-12-04 08:34:57 25 4
gpt4 key购买 nike

我有一个带有 Activity 缓冲编辑器的 vaadin 网格。默认情况下,双击一行时会打开编辑器。一切正常,除非我双击按钮时出现异常:(异常未指向我的代码中的任何位置)

java.lang.NullPointerException: Editor can't edit null
at java.base/java.util.Objects.requireNonNull(Objects.java:246)
at com.vaadin.ui.components.grid.EditorImpl.doEdit(EditorImpl.java:216)
at com.vaadin.ui.components.grid.EditorImpl$1.bind(EditorImpl.java:151)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:155)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:116)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:445)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:410)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
at com.vaadin.server.communication.PushHandler.lambda$new$1(PushHandler.java:145)
at com.vaadin.server.communication.PushHandler.callWithUi(PushHandler.java:235)
at com.vaadin.server.communication.PushHandler.onMessage(PushHandler.java:520)
at com.vaadin.server.communication.PushAtmosphereHandler.onMessage(PushAtmosphereHandler.java:87)
at com.vaadin.server.communication.PushAtmosphereHandler.onRequest(PushAtmosphereHandler.java:77)
at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:223)
at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:115)
at org.atmosphere.container.Servlet30CometSupport.service(Servlet30CometSupport.java:67)
at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:2284)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:593)
at org.atmosphere.websocket.DefaultWebSocketProcessor$3.run(DefaultWebSocketProcessor.java:345)
at org.atmosphere.util.VoidExecutorService.execute(VoidExecutorService.java:101)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:340)
at org.atmosphere.websocket.DefaultWebSocketProcessor.invokeWebSocketProtocol(DefaultWebSocketProcessor.java:447)
at org.atmosphere.container.JSR356Endpoint$3.onMessage(JSR356Endpoint.java:272)
at org.atmosphere.container.JSR356Endpoint$3.onMessage(JSR356Endpoint.java:269)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395)
at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82)
at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171)
at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148)
at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:844)

这就是我将 Button 添加到网格的方式:
// Adding the column
grid.addComponentColumn(this::buildAddButton);

这是返回每一行按钮的方法:
// Building the button
private Button buildAddButton(ProductTemplate p) {
Button button = new Button("add");
// Configurate the button
...
return button;
}

不幸的是,我对这个问题的发现很少......
由于 vaadin 按钮不会停止点击事件传播,我试过这个:
  • 通过从布局中删除单击监听器,将按钮添加到布局以“阻止”单击事件。
    // Adding the column 
    grid.addComponentColumn(this::buildAddLayout);

    构建一个布局而不仅仅是一个按钮:
    // Building the layout with the button
    private VerticalLayout buildAddLayout(ProductTemplate p) {
    Button button = new Button("add");

    // Configurate the button
    ...

    VerticalLayout layout = new VerticalLayout();
    layout.addComponent(button);
    layout.getListeners(Event.class).clear();

    return layout;
    }
  • 单击时禁用按钮,直到它的任务是
    完成(禁止双击按钮)。
    // Building the button
    private Button buildAddButton(ProductTemplate p) {
    Button button = new Button("add");
    // Configurate the button
    ...
    button.addClickListener(e -> {
    button.setEnabled(false);
    buttonClicked(p);
    button.setEnabled(true);
    });
    return button;
    }

  • 两者都没有让我能够摆脱异常。在启用编辑器的网格上双击按钮时,有什么建议,如何防止这种类型的异常?

    编辑:编辑器正在尝试编辑按钮的值,这显然是不可能的。我想阻止编辑这样做。 (“can't edit null”表示 vaadin 无法从按钮中创建有效的 bean)

    编辑 2:我之前在第一次编辑中做出的假设似乎是错误的。我的按钮点击正在刷新网格,我无法阻止编辑器尝试编辑一行,即使所有项目都被删除并重新加载。

    这里有一个类和一个pom,可以用来重现异常(快速点击按钮时出现异常):

    MyUI.java
    package com.example.sample;

    import java.util.ArrayList;
    import java.util.List;

    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.Button;
    import com.vaadin.ui.Grid;
    import com.vaadin.ui.Notification;
    import com.vaadin.ui.TextField;
    import com.vaadin.ui.UI;
    import com.vaadin.ui.VerticalLayout;

    @Theme("mytheme")
    public class MyUI extends UI {
    List<Product> items = new ArrayList<Product>();
    Grid<Product> grid;

    @Override
    protected void init(VaadinRequest vaadinRequest) {
    items.add(new Product("test", "test test"));

    final VerticalLayout layout = new VerticalLayout();

    grid = new Grid<Product>();
    layout.addComponent(grid);

    grid.getEditor().setBuffered(true);
    grid.getEditor().setEnabled(true);

    grid.removeAllColumns();

    grid.addComponentColumn(this::buildAddButton);

    TextField nameField = new TextField();
    TextField descriptionField = new TextField();

    grid.addColumn(Product::getName).setCaption("Name").setEditorComponent(nameField, Product::setName)
    .setExpandRatio(1);
    grid.addColumn(Product::getDescription).setCaption("Description")
    .setEditorComponent(descriptionField, Product::setDescription).setExpandRatio(1);

    grid.getEditor().addSaveListener(event -> {

    Notification.show((event.getBean() + "saved"));
    });

    grid.setItems(items);
    setContent(layout);
    }

    private Button buildAddButton(Product p) {

    Button button = new Button();

    button.addClickListener(event -> addButtonClicked(p));

    return button;
    }

    private void addButtonClicked(Product p) {
    refreshGrid();
    }

    private void refreshGrid() {
    grid.setItems(items);
    }

    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
    @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
    public static class MyUIServlet extends VaadinServlet {
    }

    public class Product {
    String name;
    String description;

    public Product(String name, String description) {
    super();
    this.name = name;
    this.description = description;
    }

    public Product() {
    super();

    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public String getDescription() {
    return description;
    }

    public void setDescription(String description) {
    this.description = description;
    }

    @Override
    public String toString() {
    return name + " " + description;
    }

    }
    }

    pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>sample</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>sample</name>

    <prerequisites>
    <maven>3</maven>
    </prerequisites>

    <properties>
    <vaadin.version>8.3.1</vaadin.version>
    <vaadin.plugin.version>8.3.1</vaadin.plugin.version>
    <jetty.plugin.version>9.3.9.v20160517</jetty.plugin.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <!-- If there are no local customizations, this can also be "fetch" or "cdn" -->
    <vaadin.widgetset.mode>local</vaadin.widgetset.mode>
    </properties>

    <repositories>
    <repository>
    <id>vaadin-addons</id>
    <url>http://maven.vaadin.com/vaadin-addons</url>
    </repository>
    </repositories>

    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-bom</artifactId>
    <version>${vaadin.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>

    <dependencies>
    <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
    </dependency>
    <dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-server</artifactId>
    </dependency>
    <dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-push</artifactId>
    </dependency>
    <dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-client-compiled</artifactId>
    </dependency>
    <dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-themes</artifactId>
    </dependency>
    </dependencies>

    <build>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
    <failOnMissingWebXml>false</failOnMissingWebXml>
    <!-- Exclude an unnecessary file generated by the GWT compiler. -->
    <packagingExcludes>WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**</packagingExcludes>
    </configuration>
    </plugin>
    <plugin>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-maven-plugin</artifactId>
    <version>${vaadin.plugin.version}</version>
    <executions>
    <execution>
    <goals>
    <goal>update-theme</goal>
    <goal>update-widgetset</goal>
    <goal>compile</goal>
    <!-- Comment out compile-theme goal to use on-the-fly theme compilation -->
    <goal>compile-theme</goal>
    </goals>
    </execution>
    </executions>
    </plugin>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-clean-plugin</artifactId>
    <version>3.0.0</version>
    <!-- Clean up also any pre-compiled themes -->
    <configuration>
    <filesets>
    <fileset>
    <directory>src/main/webapp/VAADIN/themes</directory>
    <includes>
    <include>**/styles.css</include>
    <include>**/styles.scss.cache</include>
    </includes>
    </fileset>
    </filesets>
    </configuration>
    </plugin>

    <!-- The Jetty plugin allows us to easily test the development build by
    running jetty:run on the command line. -->
    <plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>${jetty.plugin.version}</version>
    <configuration>
    <scanIntervalSeconds>2</scanIntervalSeconds>
    </configuration>
    </plugin>
    </plugins>
    </build>

    <profiles>
    <profile>
    <!-- Vaadin pre-release repositories -->
    <id>vaadin-prerelease</id>
    <activation>
    <activeByDefault>false</activeByDefault>
    </activation>

    <repositories>
    <repository>
    <id>vaadin-prereleases</id>
    <url>http://maven.vaadin.com/vaadin-prereleases</url>
    </repository>
    <repository>
    <id>vaadin-snapshots</id>
    <url>https://oss.sonatype.org/content/repositories/vaadin-snapshots/</url>
    <releases>
    <enabled>false</enabled>
    </releases>
    <snapshots>
    <enabled>true</enabled>
    </snapshots>
    </repository>
    </repositories>
    <pluginRepositories>
    <pluginRepository>
    <id>vaadin-prereleases</id>
    <url>http://maven.vaadin.com/vaadin-prereleases</url>
    </pluginRepository>
    <pluginRepository>
    <id>vaadin-snapshots</id>
    <url>https://oss.sonatype.org/content/repositories/vaadin-snapshots/</url>
    <releases>
    <enabled>false</enabled>
    </releases>
    <snapshots>
    <enabled>true</enabled>
    </snapshots>
    </pluginRepository>
    </pluginRepositories>
    </profile>
    </profiles>

    </project>

    最佳答案

    免责声明 : 由于缺少 setHandleWidgetEvents,此解决方案不适用于 8.3 之前的版本方法。否则,虽然复杂,但此解决方案可能适用于某些人:

  • 从按钮 ( addClickListener ) 中删除单击事件处理。无法在那里获得有关双击的信息,但是
  • 有一种方法可以使用 addItemClickListener和它的 clickedItem.getMouseEventDetails().isDoubleClick() , 但是 再次
  • 使用 grid.getEditor().setEnabled(true); 启用网格后双击检查总是返回 false ,所以
  • 您需要默认禁用编辑器 grid.getEditor().setEnabled(false);(这里有一个很好的相关答案 Couldn't capture double click event using vaadin 7)
  • 并且,一旦发生双击事件(并打开一行),重新启用它
    grid.getEditor().setEnabled(true);
    grid.getEditor().editRow(item.getRowIndex());
  • 如果,否则,单击按钮列一次,执行您的 addButtonClicked然后行动
  • 为了从 Grid 列的组件接收事件,当单击按钮时,列应该能够处理事件。这是使用 grid.addComponentColumn(this::buildAddButton).setHandleWidgetEvents(true).setId("buttonClick"); 实现的

  • 来自 init 的完整修改代码方法。所有其他保持不变(另外,请记住从按钮中删除 addClickListener):

            items.add(new Product("test", "test test"));

    grid = new Grid<Product>();

    grid.getEditor().setBuffered(true);
    grid.getEditor().setEnabled(false);

    grid.removeAllColumns();

    // Important! Propagate events from components to Grid
    grid.addComponentColumn(this::buildAddButton).setHandleWidgetEvents(true).setId("buttonClick");

    TextField nameField = new TextField();
    TextField descriptionField = new TextField();

    grid.addColumn(Product::getName).setCaption("Name").setEditorComponent(nameField, Product::setName)
    .setExpandRatio(1);
    grid.addColumn(Product::getDescription).setCaption("Description")
    .setEditorComponent(descriptionField, Product::setDescription).setExpandRatio(1);

    //Once close editor--> Disable it
    grid.getEditor().addSaveListener(event -> {
    grid.getEditor().setEnabled(false);

    });
    grid.getEditor().addCancelListener(e->{
    grid.getEditor().setEnabled(false);
    });
    //THIS IS WHERE ALL THE LOGIC IS HAPPENING
    grid.addItemClickListener(item->{
    //If the button column is clicked
    if("buttonClick".equals(item.getColumn().getId())){
    //Regual click--> update content; also fired twice before editor is opened
    if(!item.getMouseEventDetails().isDoubleClick()){
    addButtonClicked(item.getItem());
    }
    //If Double click is detected, just opened editor. The data is already updated
    else{
    grid.getEditor().setEnabled(true);
    grid.getEditor().editRow(item.getRowIndex());
    }
    }
    //In all the other cases, when double click is detected--> open editor
    else if(item.getMouseEventDetails().isDoubleClick()){
    grid.getEditor().setEnabled(true);
    grid.getEditor().editRow(item.getRowIndex());
    }
    });

    grid.setItems(items);
    addComponent(grid);

    关于java - 带有 Activity 编辑器的 Vaadin 双击网格上的按钮会引发异常 ("java.lang.NullPointerException: Editor can' t edit null"),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48825075/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com