Не удается сбросить StringBuffer в приложении JavaFX - PullRequest
0 голосов
/ 06 января 2019

Я работаю над проектом курса для колледжа, приложением JavaFX, имитирующим гараж с движущимися транспортными средствами. Следуя этому ответу , я создал механизм для постоянного обновления графического интерфейса без переполнения потока JavaFX.

Весь код можно найти здесь .

Observer - это поток демона, задачей которого является вычисление значения String для вывода и отправка его в TextArea, который постоянно обновляется.

Метод запуска наблюдателя:

    @Override
    public void run() {
        while (true) {
            synchronized (Garage.getLock()) {
                try {
//                  buffer = new StringBuffer("");

                    buffer.append('\n');
                    garage.print(buffer);
                    buffer.append('\n');
                    garage.outputText.set(buffer.toString());
                    System.out.println(buffer.toString());
                    Garage.getLock().wait(3000);
                } catch (InterruptedException exception) {
                    exception.printStackTrace();
                } finally {
                    Garage.getLock().notifyAll();
                }
            }
        }
    }

Observer объект имеет ссылку на класс модели - garage. print() метод класса Garage в основном добавляет вещи в буфер.

Полный вывод выводится на консоль, которая работает нормально. Выход также используется для установки outputText, SimpleStringProperty, к которому подключен прослушиватель в MainControllerClass.

элемент outputText:

public class Garage implements Externalizable {
    ...
    public SimpleStringProperty outputText = new SimpleStringProperty();
    ...
}

Обновление GUI запускается нажатием кнопки.

Класс MainController:

package garage.controller;

import java.util.concurrent.atomic.AtomicInteger;

import garage.model.*;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;

public class MainController {

    @FXML
    private TextArea output;

    @FXML
    private Button startButton;

    private Garage model;

    public MainController() {

    }

    private AtomicInteger control = new AtomicInteger(-1);

    @FXML
    public void initialize() {

    }

    @FXML
    private void handleStartButton() {
        model.outputText.addListener(new ChangeListener<String>() {
            @Override
            public void changed(final ObservableValue<? extends String> observable, final String oldValue,
                    final String newValue) {
                if (control.getAndSet(1) == -1) {
                    javafx.application.Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            control.set(-1);
                            output.setText(newValue);
                        }
                    });
                }

            }
        });

    }

    public void setModel(Garage model) {
        this.model = model;
    }

}

Когда я запускаю приложение и нажимаю кнопку, все идет хорошо. TextArea обновляется в режиме реального времени. Поскольку вывод постоянно добавляется к StringBuffer, я хотел обновлять его в каждом цикле и получать что-то вроде симуляции.

Здесь начинаются проблемы.

Когда я раскомментирую строку в методе Observer run

//                  buffer = new StringBuffer("");

ничего не печатается на TextArea. Консольный вывод работает хорошо.

Я также пытался с другими StringBuffer методами, такими как delete и setLenght, но ничего не работает. Однако я пытаюсь очистить буфер, TextArea больше не обновляется.

Не получается сбросить StringBuffer.

Что мне здесь не хватает?

РЕДАКТИРОВАТЬ: print() методы

Метод печати в гараже

public void print(StringBuffer buffer) {
        synchronized (Garage.lock) {
            synchronized (lock) {
                for (int i = 0; i < platformCount; i++)
                    platforms.get(i).print(buffer);
            }
        }
    }

Метод печати GarageItem

package garage.model;

import java.io.*;

public interface GarageItem extends Serializable {
    public void print(StringBuffer buffer);

}

Метод печати на полосе

package garage.model;

public class Lane implements GarageItem {
    private static final long serialVersionUID = 5L;

    @Override
    public void print(StringBuffer buffer) {
        synchronized (Garage.getLock()) {
            buffer.append('.');
        }
    }
}

Метод печати ParkingSpot

package garage.model;

public class ParkingSpot implements GarageItem {
    private static final long serialVersionUID = 4L;

    @Override
    public void print(StringBuffer buffer) {
        synchronized (Garage.getLock()) {
            buffer.append('*');
        }

    }

}

Способ печати автомобиля

@Override
    public void print(StringBuffer buffer) {
        synchronized (Garage.getLock()) {
            buffer.append(symbol);
        }
    }

, где symbol - это V.

1 Ответ

0 голосов
/ 08 января 2019

Нашел ответ сегодня. Мой текстовый пример был тривиальным, и к тому времени, когда я нажал handleStartButton, все машины закончили движение и припарковались в гараже.

Поскольку я сбрасывал буфер на каждой итерации цикла, это означало, что состояние гаража больше не менялось, и его представление String было таким же. Из-за этого прослушиватель изменений не был запущен, и в TextArea ничего не печаталось.

...