使用Platform.RunLater的JavaFX更新UI不起作用

时间:2017-08-17 09:51:21

标签: java javafx tableview

我知道这个话题已经彻底讨论过了 但是仍然有些东西不适合我。

我有以下型号(DicomModel)

public class DicomModel {
    private final IntegerProperty studyId;
    private final IntegerProperty seriesId;
    private final StringProperty scanTime;
    private StringProperty dicomStatus;
    private StringProperty lastMessage;
    private final List<String> messages;

    private final DicomImageType dicomImageType;
    private final File dicomFile;

    public DicomModel(DicomImageType imageType, File dicomFile, int studyId, int seriesId, String scanTime) {
        messages = new ArrayList<>();

        this.dicomImageType = imageType;
        this.dicomFile = dicomFile;
        this.studyId = new SimpleIntegerProperty(studyId);
        this.seriesId = new SimpleIntegerProperty(seriesId);
        this.scanTime = new SimpleStringProperty(scanTime);

        this.lastMessage = new SimpleStringProperty();
        this.dicomStatus = new SimpleStringProperty(ExecutionStatus.Pending.getDisplayName());
    }

    /**
     * @return the studyId
     */
    public int getStudyId() {
        return studyId.get();
    }

    /**
     * @return the seriesId
     */
    public int getSeriesId() {
        return seriesId.get();
    }

    /**
     * @return the scanTime
     */
    public String getScanTime() {
        return scanTime.get();
    }

    /**
     * @return the dicomStatus
     */
    public String getDicomStatus() {
        return dicomStatus.get();
    }

    /**
     * @param dicomStatus the dicomStatus to set
     */
    public void setDicomStatus(ExecutionStatus dicomStatus) {
        this.dicomStatus.set(dicomStatus.getDisplayName());
    }

    /**
     * @return the lastMessage
     */
    public String getLastMessage() {
        return lastMessage.get();
    }

    /**
     * @return the messages
     */
    public List<String> getMessages() {
        return messages;
    }

    /**
     * Add a new message to the DICOM model.
     * The new message will be inserted to the list of {@link DicomModel} messages,
     * and be visible as latest message received. 
     * @param newDicomSendResponse The retrieved DICOM message from DICOM send module. 
     */
    public void addMessage(String newDicomSendResponse){
        messages.add(newDicomSendResponse);
        this.lastMessage.set(newDicomSendResponse);
    }

    /**
     * @return the dicomImageType
     */
    public DicomImageType getDicomImageType() {
        return dicomImageType;
    }

    /**
     * @return the dicomFile
     */
    public File getDicomFile() {
        return dicomFile;
    }
}

这是我的fxml TableView列定义:

<TableView fx:id="_tvDicomSend" prefWidth="${_queueBox.width}">
    <columns>
        <TableColumn text="Study" prefWidth="120">
            <cellValueFactory>
                <PropertyValueFactory property="studyId" />
            </cellValueFactory>
        </TableColumn>
        <TableColumn text="Series" prefWidth="120">
            <cellValueFactory>
                <PropertyValueFactory property="seriesId" />
            </cellValueFactory>
        </TableColumn>
        <TableColumn text="Scan time" prefWidth="120">
            <cellValueFactory>
                <PropertyValueFactory property="scanTime" />
            </cellValueFactory>
        </TableColumn>
        <TableColumn text="Status" prefWidth="70">
            <cellValueFactory>
                <PropertyValueFactory property="dicomStatus" />
            </cellValueFactory>
        </TableColumn>
        <TableColumn text="Last message" prefWidth="400">
            <cellValueFactory>
                <PropertyValueFactory property="lastMessage" />
            </cellValueFactory>
        </TableColumn>
    </columns>
</TableView>

以下是我填充数据的方式 这是在ExecutorService(在handleResponse方法中)

中使用的Callable
class executorThread implements Callable<Boolean>, DicomResponseListener{
    private final DicomModel dicom;

    public executorThread(DicomModel dicom) {
        dicomComm.addListener(this);
        this.dicom = dicom;
    }

    @Override
    public Boolean call() throws Exception {
        dicom.setDicomStatus(ExecutionStatus.Running);
        sendDicom(dicom.getDicomImageType(), dicom.getDicomFile());

        return true;
    }

    @Override
    public void handleResponse(DicomResponseType responseType, String responseMessage) {
        Platform.runLater(() -> dicom.addMessage(responseMessage));
        //dicomSendController.refreshUI();
    }

    @Override
    public void handleDicomCompletion(DicomReturnCode returnCode) {
        dicom.setDicomStatus(ExecutionStatus.Completed);
        //dicomSendController.refreshUI();
        dicomComm.removeListener(this);
    }
}

现在一个小概述:
此执行程序驻留在DicomSendManager中,该DIComSendManager包含DicomModel对象的队列 当我将新对象插入队列时,我将其插入到DicomSendController中的ObservableList中。
以下是此方法的代码段:

/**
 * Add a new DICOM image to the DICOMs list, the controller, and the execution queue
 * @param newDicom {@link DicomModel} to add
 */
private void addNewDicom(DicomModel newDicom){
    // Add the new DICOM to the execution list
    dicomImages.add(newDicom);
    // Add the new DICOM to the UI Controller
    dicomSendController.addDicomImage(newDicom);
    // Submit the DICOM to execution queue
    executor.submit(new executorThread(newDicom));
}

他们的辩护:

  • List<DicomModel> dicomImages = new ArrayList<DicomModel>();
  • ExecutorService executor = Executors.newSingleThreadExecutor();
  • ObservableList<DicomModel> dicomSendQueue = FXCollections.observableArrayList(); - 在UI控制器

现在出现问题。
即使Platform.RunLater()将新消息插入DicomModel,它也不会更新UI 旁注:我知道这种方法有效,因为当我输入一个小的控制台打印消息时,它会打印出来。

我得到的唯一UI更新是:

  • 如果将新的DicomModel插入ObservableList,则它会更新旧DicomModel对象的值
  • 如果我手动调用_tvDicomSend.Refresh()(强制刷新TableView)。

我在这里想念的是什么? 我的概念有什么问题吗?

谢谢!

0 个答案:

没有答案