观察者和线程的问题

时间:2016-06-14 19:44:36

标签: javafx threadpool fxml observer-pattern

我是Java和JavaFX的新手我的代码遇到了一个非常大的问题。我使用JavaFX和Scene Builder。

我的目标是计算房间的热量方程,现在我试图在标签上显示我的结果。

我在循环中计算方程式,标签应该每次都更新以显示最后的结果。我在youtube上发现了一个视频,我尝试这样做,但它不起作用。 =(也许你可以帮助我: - /

这不是完整的代码,我删除了不必要的东西。

我没有错误,但它不起作用。

youtube video

这是我计算热量的第一堂课:

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.concurrent.*;

public class Raum {
    int zeit;
    int startTemperatur;

    // length, width, height
    int x;
    int y;
    int z;

    double sensorwert;
    String sensorwertString;
    private final List<TemperaturSensorListener> listeners = new ArrayList();
    //and so on

    public Raum() {    
        ExecutorService service = Executors.newCachedThreadPool();
        service.submit(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

            }
            temperaturverlauf(); // is this correct?
            for (TemperaturSensorListener listener : listeners) {
                listener.onReadingChanged();
            }
        });    
    }

    // Calculate Heat equation
    public void temperaturverlauf() {
        double[][][] raumTemp = new double[x][y][z];
        double[][][] raumTempneu = new double[x][y][z];
        zeit = 0;

        //Start temperature for every position
        for (int posX = 0; posX < x; posX++) {
            for (int posY = 0; posY < y; posY++) {
                for (int posZ = 0; posZ < z; posZ++) {
                    raumTemp[posX][posY][posZ] = startTemperatur;    
                }
            }
        }

        /*Heater*/
        raumTemp[0][0][0] = startHeizung;

        while (zeit < 100) {
            for (int posX = 0; posX < x; posX++) {
                for (int posY = 0; posY < y; posY++) {
                    for (int posZ = 0; posZ < z; posZ++) {
                        // Compute the heat of every quadrant in the room
                        // upper left corner
                        if (posX == 0 && posY == Array.getLength(raumTemp[0]) - 1 && posZ == 0) {
                            raumTempneu[posX][posY][posZ] = raumTemp[posX][posY][posZ] - temperaturleitfähigkeit * (4 * raumTemp[posX][posY][posZ] - raumTemp[posX + 1][posY][posZ] - raumTemp[posX][posY - 1][posZ] - raumTemp[posX][posY][posZ + 1] - mauertemp);
                        }    
                        // Upper right corner , walls and so on
                    }    
                }
            }

            raumTemp = raumTempneu;

            // print out the heat of the sensor position and convert it to a string. this String has to be displayed in a label
            System.out.println("raum1:" + raumTemp[Array.getLength(raumTemp) - 1][Array.getLength(raumTemp[0]) - 1][1]);
            sensorwert = raumTemp[Array.getLength(raumTemp) - 1][Array.getLength(raumTemp[0]) - 1][1];
            sensorwertString = Double.toString(sensorwert);
        }
    }

    public void addListener(TemperaturSensorListener listener) {
        listeners.add(listener);
    }

    public String getSensorwertString() {
        return sensorwertString;
    }
}

这是我的第二个课程,里面有标签:

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;

import java.net.URL;
import java.util.ResourceBundle;

public class FXMLDocumentController implements Initializable {
    private Raum r = new Raum();

    // Slider for heater temperature
    @FXML
    private Slider slider1;

    // Label with the String from the other class
    @FXML
    private final Label anzeigetempaktuell1 = new Label(r.getSensorwertString());

    // Textfields so user can type in the size of the room
    @FXML
    private TextField laenge;

    @FXML
    private TextField breite;

    @FXML
    private TextField hoehe;

    // starttemperature
    @FXML
    private TextField tempAktuell;

    // target temperature
    @FXML
    private TextField tempGewuenscht;

    //this button should start the application after the user typed in the required values
    @FXML
    private Button button;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        r.temperaturverlauf();// i think this is wrong
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        slider1.setMin(17);
        slider1.setMax(85);
        slider1.setValue(45);

        slider1.valueProperty().addListener((ov, old_val, new_val) -> {
            r.maxHeizung = (double) new_val;
            System.out.println(r.maxHeizung);
        });

        // this is a relevant part i think but i think its the same like in the video
        r.addListener(new TemperaturSensorListener() {
            @Override
            public void onReadingChanged() {
                updateTemperatureLabel();
            }

            private void updateTemperatureLabel() {
                Platform.runLater(() -> anzeigetempaktuell1.setText(r.getSensorwertString()));
            }
        });
    }
}

这是最后一堂课:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.*;
import javafx.stage.Stage;

public class SmartHome 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();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

问题是我使用这个FXMLDocumentController课,而视频中的人没有。我不知道将所有内容写入initialize方法是否正确。我不知道该怎么做。

1 个答案:

答案 0 :(得分:0)

您的sleep来电不在temperaturverlauf的来电之内。您发送给执行程序的任务在1000ms内休眠一次,然后运行所有计算,将输出转储到System.out。然后,最后,它会调用你的观察者。

听起来这不是你想要的。如果您想在计算过程中暂停一下,那么您需要进行sleep调用。同样,如果您希望每次更改值时通知观察者,那么在值更改时您需要调用onReadingChanged

我建议使用体系结构修订版来简化重新设计:编写计算方法,以便计算出一个更改。这样可以更容易地分离您的问题,以便其他代理可以遵循以下顺序:

  1. 调用方法计算一次温度变化。
  2. 使用新值更新标签。
  3. 睡一秒钟。
相关问题