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

筛选的视图列表上的Outbounds异常

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

    我正在开发一个小应用程序,它从数据库中获取信息并将其显示在列表视图中,然后选择列表中的元素并将其移动到第二个列表中,我必须能够在列表之间添加和删除元素。我还为搜索功能实现了两个带有过滤列表的列表。我的代码可以工作,我可以在列表之间切换元素,但是当我尝试将元素从第二个列表返回到第一个列表时,或者当我将第一个列表的最后一个元素移动到第二个列表时,我会得到一个越界异常。 有人能帮我弄明白吗?

    事先谢谢。

    例外

    Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
    at java.util.ArrayList.rangeCheck(ArrayList.java:657)
    at java.util.ArrayList.get(ArrayList.java:433)
    at com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
    at javafx.collections.transformation.FilteredList.get(FilteredList.java:172)
    at javafx.scene.control.ListCell.updateItem(ListCell.java:459)
    at javafx.scene.control.ListCell.lambda$new$160(ListCell.java:167)
    at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
    at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
    at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
    at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
    at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
    at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
    at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
    at javafx.collections.transformation.FilteredList.sourceChanged(FilteredList.java:147)
    at javafx.collections.transformation.TransformationList.lambda$getListener$23(TransformationList.java:106)
    at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
    at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
    at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
    at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
    at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
    at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
    at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
    at com.sun.javafx.collections.ObservableListWrapper.removeAll(ObservableListWrapper.java:185)
    at com.kalypso.WCExporter.MainController.removeItemFromList(MainController.java:351)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8411)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:432)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    

    列表声明

    @FXML
    private JFXListView leftList;
    
    @FXML
    private JFXTextField leftFilter;
    
    @FXML
    private JFXListView rightList;
    
    @FXML
    private JFXTextField rightFilter;
    private ObservableList<String> leftData = FXCollections.observableArrayList();
    private ObservableList<String> rightData = FXCollections.observableArrayList();
    private FilteredList<String> leftFilteredData;
    private FilteredList<String> rightFilteredData;
    

    此方法填充第一个列表

    此列表包含将要使用的所有值

    private void loadResultList(){
            if( session != null && session.isOpen()) {
                //Clear list View
                leftList.getItems().clear();
    
                //Get entity node
                HibernateUtil hibernateUtil = new HibernateUtil();
                //Get query results
                List resultSet = hibernateUtil.executeSQLQuery(session, selectedEntity.getValue().get("query").asText());
    
                //Wrap resultset into Observable list
                resultSet.forEach(result -> leftData.add(((Map)result).get("NAME").toString()));
    
                // 1. Wrap the ObservableList in a FilteredList (initially display all data).
                leftFilteredData = new FilteredList<>(leftData, p -> true);
    
                // 2. Set the filter Predicate whenever the filter changes.
                wrapListAndAddFiltering(leftFilter, leftFilteredData);
    
                leftList.setItems(leftFilteredData);
                leftList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    
            } else{
                Alert noDBCon = new Alert(Alert.AlertType.ERROR);
                noDBCon.setTitle("No Database connection");
                noDBCon.setHeaderText("No Database Connection");
                noDBCon.setContentText("Select and connect to a DB before doing any transaction.");
                noDBCon.showAndWait();
            }
        }
    
    private void wrapListAndAddFiltering(JFXTextField filterField,FilteredList<String> filteredData) {
        filterField.textProperty().addListener((observable, oldValue, newValue) -> {
            filteredData.setPredicate(item -> {
                String filter = filterField.getText().toLowerCase();
                if (newValue == null || newValue.isEmpty()) {
                    return true;
                }
                if (item.toLowerCase().contains(filter)) {
                    return true;
                }
                return false;
            });
        });
    }
    

    添加和删除元素的方法

    @FXML
    private void addItemToList(){
        //1.- Add elements to right list
        //Wrap left elements into Observable list
        leftList.getSelectionModel().getSelectedItems().forEach(item -> rightData.add(item.toString()));
    
        //Wrap the ObservableList in a FilteredList (initially display all data).
        rightFilteredData = new FilteredList<>(rightData, p -> true);
        wrapListAndAddFiltering(rightFilter, rightFilteredData);
        rightList.setItems(rightFilteredData);
    
        //2.- Remove elements from left list
        leftData.removeAll(leftList.getSelectionModel().getSelectedItems());
        leftFilteredData = new FilteredList<>(leftData, p -> true);
        wrapListAndAddFiltering( leftFilter, leftFilteredData );
        leftList.setItems(leftFilteredData);
    }
    
    @FXML
    private void removeItemFromList(){
        //1.-add elements to left list
        rightList.getSelectionModel().getSelectedItems().forEach(item -> leftData.add(item.toString()));
        leftFilteredData = new FilteredList<>(leftData, p -> true);
        wrapListAndAddFiltering(leftFilter, leftFilteredData);
        leftList.setItems(leftFilteredData);
    
        //1.-Remove items from right list
        ObservableList<String> temp = FXCollections.observableArrayList();
        rightList.getSelectionModel().getSelectedItems().forEach(el -> temp.add(el.toString()));
        //rightList.getSelectionModel().getSelectedItems().forEach(rightData::remove);
        rightData.removeAll(temp);
        //rightData.removeAll();
        rightFilteredData = new FilteredList<>(rightData, p -> true);
        wrapListAndAddFiltering( rightFilter, rightFilteredData );
        rightList.setItems(rightFilteredData);
    }
    

    图形用户界面

    enter image description here

    1 回复  |  直到 6 年前
        1
  •  1
  •   SedJ601    6 年前

    我创造了一个 MCVE . 代码中的注释。它显示了如何设置 FilteredList 以及如何将数据从一个 ListView 给另一个。

    主要的

    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    /**
     *
     * @author blj0011
     */
    public class JavaFXApplication239 extends Application
    {
    
        @Override
        public void start(Stage stage) throws Exception
        {
            Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
    
            Scene scene = new Scene(root);
    
            stage.setScene(scene);
            stage.show();
        }
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args)
        {
            launch(args);
        }
    
    }
    

    控制器

    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.ResourceBundle;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.collections.transformation.FilteredList;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.ListView;
    import javafx.scene.control.SelectionMode;
    import javafx.scene.control.TextField;
    
    /**
     *
     * @author blj0011
     */
    public class FXMLDocumentController implements Initializable
    {
    
        @FXML
        private ListView lvLeft, lvRight;
    
        @FXML
        private TextField tfLeft, tfRight;
    
        ObservableList<String> leftData = FXCollections.observableArrayList();
        ObservableList<String> rightData = FXCollections.observableArrayList();
    
        FilteredList<String> filteredLeftData, filteredRightData;
    
        @Override
        public void initialize(URL url, ResourceBundle rb)
        {
            leftData.addAll(getFakeDataFromDB());//get data from DB
            //rightData.addAll(getFakeDataFromDB());//Used for testing
            filteredLeftData = new FilteredList(leftData, s -> true);
            filteredRightData = new FilteredList(rightData, s -> true);
    
            //Set filtered Lists
            tfLeft.textProperty().addListener((observable, oldValue, newValue) -> {
                if (newValue == null || newValue.length() == 0) {
                    filteredLeftData.setPredicate(null);
                }
                else {
                    filteredLeftData.setPredicate(t -> {
                        return t.toUpperCase().startsWith(newValue.toUpperCase());
                    });
                }
            });
    
            tfRight.textProperty().addListener((observable, oldValue, newValue) -> {
                if (newValue == null || newValue.length() == 0) {
                    filteredRightData.setPredicate(null);
                }
                else {
                    filteredRightData.setPredicate(t -> {
                        return t.toUpperCase().startsWith(newValue.toUpperCase());
                    });
                }
            });
    
            //Set listview items
            lvLeft.setItems(filteredLeftData);
            lvRight.setItems(filteredRightData);
    
            //Set selecton model selection mode
            lvLeft.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
            lvRight.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        }
    
        @FXML
        private void handleBtnActionMoveToLeft(ActionEvent actionEvent)
        {        
            List<String> itemsToMove = new ArrayList(lvRight.getSelectionModel().getSelectedItems());//If you don't do this "new ArrayList(..):", then  you need to first addAll then removeAll
            System.out.println("list size: " + itemsToMove.size());
            rightData.removeAll(itemsToMove);
            leftData.addAll(itemsToMove);
        }
    
        @FXML
        private void handleBtnActionMoveToRight(ActionEvent actionEvent)
        {
            List<String> itemsToMove = new ArrayList(lvLeft.getSelectionModel().getSelectedItems());//If you don't do this "new ArrayList(..):", then  you need to first addAll then removeAll
            System.out.println("list size: " + itemsToMove.size());
            leftData.removeAll(itemsToMove);
            rightData.addAll(itemsToMove);
        }
    
        List<String> getFakeDataFromDB()
        {
            List<String> tempList = new ArrayList();
            tempList.add("Hello");
            tempList.add("Hello World!");
            tempList.add("Bye");
            tempList.add("Bye World!");
            tempList.add("Been");
            tempList.add("Bad");
    
            return tempList;
        }
    
    }
    

    FXML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.geometry.Insets?>
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.control.ListView?>
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.layout.VBox?>
    
    
    <HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication239.FXMLDocumentController">
       <children>
          <ListView fx:id="lvLeft" prefHeight="200.0" prefWidth="200.0" />
          <VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" HBox.hgrow="ALWAYS">
             <children>
                <Label text="Left" />
                <TextField fx:id="tfLeft" />
                <VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" spacing="5.0">
                   <children>
                      <Button mnemonicParsing="false" onAction="#handleBtnActionMoveToRight" text="Move To Right" />
                      <Button mnemonicParsing="false" onAction="#handleBtnActionMoveToLeft" text="Move To Left" />
                   </children>
                   <opaqueInsets>
                      <Insets />
                   </opaqueInsets>
                </VBox>
                <Label text="Right" />
                <TextField fx:id="tfRight" />
             </children>
          </VBox>
          <ListView fx:id="lvRight" prefHeight="200.0" prefWidth="200.0" />
       </children>
    </HBox>