2016-12-14 242 views
1

我遇到了Java FX的麻烦我正在尝试序列化一个对象,为此我创建了一个将对象从javaFX转换为可序列化对象的类。 但是当我试图加载后方对象,我得到java.lang.UnsupportedOperationException JavaFX ArrayList <String> to ObservableList <StringProperty>

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException 
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774) 
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.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
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.control.MenuItem.fire(MenuItem.java:462) 
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405) 
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358) 
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.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:380) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294) 
at java.security.AccessController.doPrivileged(Native Method) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416) 
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415) 
at com.sun.glass.ui.View.handleMouseEvent(View.java:555) 
at com.sun.glass.ui.View.notifyMouse(View.java:937) 
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) 
at java.lang.Thread.run(Unknown Source) 
Caused by: java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at sun.reflect.misc.Trampoline.invoke(Unknown Source) 
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at sun.reflect.misc.MethodUtil.invoke(Unknown Source) 
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771) 
    ... 43 more 


Caused by: java.lang.UnsupportedOperationException 
    at java.util.AbstractList.add(Unknown Source) 
    at java.util.AbstractList.add(Unknown Source) 
    at view.OverviewInterroController.handleLoad(OverviewInterroController.java:172) 
    ... 53 more 

导致它的代码:

package model; 

import java.io.Serializable; 
import java.util.ArrayList; 

import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.collections.FXCollections; 

public class QuestionSerializable implements Serializable { 

    private final String question; 
    private final String typeReponse; 
    private final int nbLignesReponse; 
    private final ArrayList<String> reponseData = new ArrayList<String>(); 


    public QuestionSerializable(QuestionModel model) 
    { 
     this.question = model.getQuestion().getValue(); 
     this.typeReponse = model.getTypeReponse().getValue(); 
     this.nbLignesReponse = model.getNbLignesReponse().getValue(); 
     for(StringProperty val : model.getReponseData().getValue()) 
     { 
      reponseData.add(val.getValue()); 
     } 
    } 

    public QuestionModel convert() 
    { 
     QuestionModel qm = new QuestionModel(question); 
     qm.getNbLignesReponse().setValue(this.nbLignesReponse); 
     qm.getTypeReponse().setValue(typeReponse); 
     ObjectProperty<ObservableList<StringProperty>> reponseData2 =qm.getReponseData(); 
     for(String val : reponseData) 
     { 
      reponseData2.getValue().add(new SimpleStringProperty(val)); 
     } 
     return qm; 
    } 
} 

以及专门:

ObjectProperty<ObservableList<StringProperty>> reponseData2 =qm.getReponseData(); 
for(String val : reponseData) 
{ 
    reponseData2.getValue().add(new SimpleStringProperty(val)); 
} 

而且OverviewController

package view; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.util.ArrayList; 

import com.itextpdf.text.xml.simpleparser.handler.NeverNewLineHandler; 

import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.fxml.FXML; 
import javafx.scene.control.Alert; 
import javafx.scene.control.Alert.AlertType; 
import javafx.scene.control.Label; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.stage.FileChooser; 
import model.QuestionModel; 
import model.QuestionSerializable; 
import principale.Main; 

public class OverviewInterroController { 

    @FXML 
    private TableView<QuestionModel> questionTable; 
    @FXML 
    private TableColumn<QuestionModel,String> questionColumn; 
    @FXML 
    private Label questionLabel; 
    @FXML 
    private Label typeLabel; 
    @FXML 
    private Label nbLigneLabel; 
    @FXML 
    private TableView<StringProperty> reponseTable; 
    @FXML 
    private TableColumn<ObservableList<StringProperty>,String> reponseColumn; 

    // Reference to the main application. 
    private Main mainApp; 

    @FXML 
    private void initialize() 
    { 
     questionColumn.setCellValueFactory(cellData -> cellData.getValue().getQuestion()); 
     showQuestionDetails(null); 

     questionTable.getSelectionModel().selectedItemProperty().addListener(
       (observable,oldvalue,newValue)-> showQuestionDetails(newValue)); 
    } 

    public void showReponseTable(QuestionModel question) 
    { 
     if(question.getTypeReponse().getValue().equals("Cocher")) 
     { 
      reponseTable.setItems(question.getReponseData().getValue()); 
      reponseColumn.setCellValueFactory(new PropertyValueFactory<>("value")); 
      reponseTable.setVisible(true); 
     }else 
     { 
      this.reponseTable.setVisible(false); 
     } 
    } 

    public void setMainApp(Main mainApp) { 
     this.mainApp = mainApp; 
     questionTable.setItems(mainApp.getQuestionData()); 
    } 


    public void handleImprimer() 
    { 
     mainApp.showImprimerDialog(); 
    } 

    public void handleClose() 
    { 
     System.exit(0); 
    } 


    public void showQuestionDetails(QuestionModel question) 
    { 
     if(question != null) 
     { 
      questionLabel.setText(question.getQuestion().getValue()); 
      typeLabel.setText(question.getTypeReponse().getValue()); 
      nbLigneLabel.setText(Integer.toString(question.getNbLignesReponse().getValue())); 
      reponseTable.setItems(FXCollections.emptyObservableList()); 
      showReponseTable(question); 
     }else 
     { 
      questionLabel.setText(""); 
      typeLabel.setText(""); 
      nbLigneLabel.setText("0"); 
      reponseTable.setVisible(false); 
     } 
    } 



    public void handleDelete() 
    { 
     int selectedIndex = questionTable.getSelectionModel().getSelectedIndex(); 
     if(selectedIndex>=0) 
     { 
     questionTable.getItems().remove(selectedIndex); 
     }else 
     { 
      Alert alert = new Alert(AlertType.ERROR); 
      alert.initOwner(mainApp.getPrimaryStage()); 
      alert.setTitle("Aucune question séléctionnée !"); 
      alert.setContentText("Veuillez séléctionner une question valide !"); 

      alert.showAndWait(); 
     } 
    } 

    public void handleSave() throws IOException 
    { 
     FileChooser fileChooser = new FileChooser(); 

     //Set extension filter 
     FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("CTRL Files (*.ctrl)", "*.ctrl"); 
     fileChooser.getExtensionFilters().add(extFilter); 

     //Show save file dialog 
     File file = fileChooser.showSaveDialog(this.mainApp.getPrimaryStage()); 

     if(file != null){ 
      FileOutputStream fout = new FileOutputStream(file); 
      ObjectOutputStream oos = new ObjectOutputStream(fout); 
      ArrayList<QuestionSerializable> qs = new ArrayList<QuestionSerializable>(); 
      for(QuestionModel qm : this.mainApp.getQuestionData()) 
      { 
       qs.add(new QuestionSerializable(qm)); 
      } 

      oos.writeObject(new ArrayList<QuestionModel>(this.mainApp.getQuestionData())); 
      oos.close(); 
      fout.close(); 
     } 
    } 

    @SuppressWarnings("unchecked") 
    public void handleLoad() throws Exception 
    { 
     FileChooser fileChooser = new FileChooser(); 

     //Set extension filter 
     FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("CTRL Files (*.ctrl)", "*.ctrl"); 
     fileChooser.getExtensionFilters().add(extFilter); 

     //Show save file dialog 
     File file = fileChooser.showSaveDialog(this.mainApp.getPrimaryStage()); 

     if(file != null){ 
      FileInputStream fout = new FileInputStream(file); 
      ObjectInputStream oos = new ObjectInputStream(fout); 
      ArrayList<QuestionSerializable> qm = (ArrayList<QuestionSerializable>) oos.readObject(); 
      ObservableList<QuestionModel> qo = FXCollections.emptyObservableList(); 
      for(QuestionSerializable q : qm) 
      { 
       qo.add(q.convert()); 
      } 
      this.mainApp.setQuestionData(qo); 
      this.questionTable.refresh(); 
      this.showQuestionDetails(null); 
      oos.close(); 
      fout.close(); 
     } 
    } 

    public void handleNew() 
    { 
     QuestionModel tempQuestion = new QuestionModel(""); 
     tempQuestion.getReponseData().getValue().add(new SimpleStringProperty("")); 
     boolean okClicked = mainApp.showPersonEditDialog(tempQuestion); 
     if (okClicked) { 
      mainApp.getQuestionData().add(tempQuestion); 
     } 

    } 

    public void handleEdit() 
    { 
     QuestionModel selectedQuestion = questionTable.getSelectionModel().getSelectedItem(); 
     if(selectedQuestion!=null) 
     { 
      boolean okClicked = mainApp.showPersonEditDialog(selectedQuestion); 
      if (okClicked) { 
       showQuestionDetails(selectedQuestion); 
       this.reponseTable.refresh(); 
      } 
     }else 
     { 
      Alert alert = new Alert(AlertType.ERROR); 
      alert.initOwner(mainApp.getPrimaryStage()); 
      alert.setTitle("Aucune question séléctionnée !"); 
      alert.setContentText("Veuillez séléctionner une question valide !"); 

      alert.showAndWait(); 
     } 
    } 

} 

和线172是:

ObservableList<QuestionModel> qo = FXCollections.emptyObservableList(); 
for(QuestionSerializable q : qm) 
{ 
    qo.add(q.convert()); 
} 

QuestionModelClass:

package model; 

import java.io.Serializable; 

import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.ObjectProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.property.SimpleObjectProperty; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 

public class QuestionModel{ 

    private final StringProperty question; 
    private final StringProperty typeReponse = new SimpleStringProperty("Remplir Ligne"); 
    private final IntegerProperty nbLignesReponse = new SimpleIntegerProperty(1); 
    private ObjectProperty<ObservableList<StringProperty>> reponseData = new SimpleObjectProperty<ObservableList<StringProperty>>(FXCollections.observableArrayList()); 



    /** 
    * @return the reponseData 
    */ 
    public ObjectProperty<ObservableList<StringProperty>> getReponseData() { 
     return reponseData; 
    } 

    public void setReponseData(ObjectProperty<ObservableList<StringProperty>> reponseData) 
    { 
     this.reponseData = reponseData; 
    } 

    public QuestionModel(String question) 
    { 
     this.question = new SimpleStringProperty(question); 
    } 

    /** 
    * @return the nbLignesReponse 
    */ 
    public IntegerProperty getNbLignesReponse() { 
     return nbLignesReponse; 
    } 

    /** 
    * @return the question 
    */ 
    public StringProperty getQuestion() { 
     return question; 
    } 

    /** 
    * @return the typeReponse 
    */ 
    public StringProperty getTypeReponse() { 
     return typeReponse; 
    } 
} 
+0

尝试'responseData2.add(new SimpleStringProperty(val));'我很难判断错误发生在哪一行。 –

+0

'ObjectProperty >' - 这是一个奇怪的类型。它可以更改为'ListProperty '? –

+0

这不起作用我麝香获取ObservableList这是一个ObjectProperty与getValue() –

回答

5

FXCollections.emptyObservableList()返回一个不可修改的空ObservableList,这就是为什么当您拨打add时得到UnsupportedOperationException

使用FXCollections.observableArrayList()创建列表,而不是:

ObservableList<QuestionModel> qo = FXCollections.observableArrayList(); 

这将创建一个可修改的列表。该列表最初是空的。

+0

在发布源代码后很好的发现了这一点。 +1 :-) – PNS

+0

不幸的是,这是行不通的:/我的问题仍然是相同的 –

+0

谢谢我忘记了一行:)它的工作谢谢你 –

1

显然,reponseDataqm.getReponseData().getValue()应该有一个类型的ObjectProperty<List<StringProperty>>

FXCollections documentation指定方法

FXCollections.emptyObservableList() 

会返回一个 “空不可修改可观察名单”。

因此,环

for(QuestionSerializable q : qm) 
{ 
    qo.add(q.convert()); 
} 

将抛出UnsupportedOperationException,由于qo对象通过调用上述方法创建。

为了得到修改空单,方法

FXCollections.observableArrayList() 

应该叫,按照上述文件和Fabian的较早前的答复。

+0

StrinProperty不能序列所以我把它们转换成字符串 –

+0

请张贴的QuestionModel类方法的签名,并阐明你什么序列。不可序列化的类是QuestionModel,可序列化是QuestionSerializable?在说明问题时不应该有任何猜测。 :-) – PNS

+0

我刚加了:) –

相关问题