2016-12-14 235 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

我剛加了:) –

相關問題