我正在尝试制作一个可以记录和绘制Android手机数据的记录程序。为了显示数据,我使用javafx在主窗口中创建子窗口,每个子窗口都有一个折线图。该程序连接到手机就好了,但是当它试图创建一个新的子窗口来记录传入的数据时,程序停止,但没有给出错误的指示。这是我的主窗口类的代码。
public class Window implements OnReceiveData, OnConnectionUpdate {
private static final int GRAPH_OFFSET = 20;
@FXML
public Button adbButton;
@FXML
private Label adbStatus, connectionStatus;
@FXML
private MenuButton devices;
@FXML
private VBox variables;
@FXML
private AnchorPane contentPane;
@FXML
private DataStreamer streamer;
private JadbConnection connection;
private Map<String, InternalWindow> windows;
private int devicesHashCode;
private double xGraphOffset, yGraphOffset;
@FXML
protected void initialize() {
this.xGraphOffset = 0;
this.yGraphOffset = 0;
this.devicesHashCode = -1;
this.windows = new HashMap<>();
DataLogger.getService().scheduleAtFixedRate(() -> {
boolean connected = true;
try {
if (connection == null)
connection = new JadbConnection();
List<JadbDevice> devices = connection.getDevices();
if (devicesHashCode != devices.hashCode()) {
devicesHashCode = devices.hashCode();
updateDeviceList(devices.stream().collect(Collectors.toMap(x -> x, DeviceUtils::getTitle)));
}
} catch (Exception e) {
if (!(e instanceof ConnectException))
e.printStackTrace();
devices.setDisable(true);
connection = null;
connected = false;
}
setADBStatus(connected);
}, 0, 100, TimeUnit.MILLISECONDS);
}
@FXML
protected void onHardRest(ActionEvent event) {
}
@FXML
public void onRefreshADB(ActionEvent event) {
DataLogger.getService().execute(() -> {
if (connection == null) {
ADBUtils.start();
} else {
ADBUtils.stop();
ADBUtils.start();
}
});
}
private void connect(JadbDevice device) {
Optional<String> optionalAddress = DeviceUtils.getIPAddress(device);
devices.setDisable(true);
if (optionalAddress.isPresent()) {
streamer = new DataStreamer(optionalAddress.get())
.addConnectionListener(this)
.addDataListener(this)
.start();
} else {
devices.setDisable(false);
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Invalid IP!");
alert.setHeaderText("App Not sSarted!");
alert.setContentText("We were unable to parse a valid IP address from the device. Please check the console for more info!");
alert.show();
}
}
protected InternalWindow createGraph(String title) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/internal-window.fxml"));
try {
Pane load = loader.load();
//stalls here
load.setLayoutX(xGraphOffset);
load.setLayoutY(yGraphOffset);
contentPane.getChildren().add(load);
xGraphOffset += GRAPH_OFFSET;
yGraphOffset += GRAPH_OFFSET;
if (yGraphOffset + load.getPrefHeight() > contentPane.getHeight()) {
xGraphOffset += GRAPH_OFFSET;
yGraphOffset = 0;
}
if (xGraphOffset + load.getPrefWidth() > contentPane.getWidth()) {
xGraphOffset = 0;
yGraphOffset = 0;
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
InternalWindow controller = loader.getController();
controller.setTitle(title);
controller.addWindowExitListener((listener, pane) -> contentPane.getChildren().remove(pane));
return controller;
}
private void updateDeviceList(Map<JadbDevice, String> devices) {
Platform.runLater(() -> {
ObservableList<MenuItem> menuItems = this.devices.getItems();
menuItems.clear();
for (JadbDevice device : devices.keySet()) {
MenuItem item = new MenuItem(devices.get(device));
item.setOnAction(e -> connect(device));
menuItems.add(item);
}
this.devices.setDisable(devices.size() <= 0);
});
}
private void setADBStatus(boolean running) {
Platform.runLater(() -> {
adbButton.setText((running ? "Refresh" : "Start") + " ADB");
adbButton.setDisable(false);
updateStatus(running, adbStatus);
});
}
private void updateStatus(boolean status, Label label) {
label.setText(status ? "Yes" : "No");
label.setTextFill(status ? Color.GREEN : Color.RED);
}
@Override
public void onConnectionUpdate(boolean connected, Exception exception) {
Platform.runLater(() -> {
if (exception != null) {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Device Connection Error!");
alert.setHeaderText("We are unable to connect to the device!");
alert.setContentText(exception.getMessage());
alert.show();
exception.printStackTrace();
}
devices.setDisable(connected);
updateStatus(connected, connectionStatus);
});
System.out.println("We are connected: " + connected);
}
@Override
public void onReceiveData(String graph, double[] values) {
System.out.println("Received: " + Arrays.toString(values));
if(windows.containsKey(graph)){
windows.get(graph).update(values, graph);
}
else windows.put(graph, createGraph(graph));
}
}
这是内部窗口类的代码
public class InternalWindow {
private static final int RESIZE_MARGIN = 10;
@FXML
public BorderPane node;
@FXML
private LineChart<Number, Number> lineGraph;
@FXML
private Label titleLabel;
@FXML
private SplitMenuButton mergeDropdown;
private HashMap<String, XYChart.Series> series;
private double xDragDelta, yDragDelta, mouseX, mouseY;
private List<OnInternalWindowExit> exitListeners;
private boolean resizing, resizingX, resizingY;
@FXML
void initialize() {
xDragDelta = 0;
yDragDelta = 0;
mouseX = 0;
mouseY = 0;
exitListeners = new ArrayList<>();
resizing = false;
resizingY = false;
resizingX = false;
node.setMinWidth(node.getPrefWidth());
node.setMinHeight(node.getPrefHeight());
series = new HashMap<>();
}
public void setTitle(String title) {
this.titleLabel.setText(title);
}
public void addWindowExitListener(OnInternalWindowExit listener) {
exitListeners.add(listener);
}
@FXML
protected void onExit(ActionEvent event) {
for (OnInternalWindowExit listener : exitListeners) {
listener.onInternalWindowExit(this, node);
}
}
@FXML
protected void onClearGraph(ActionEvent event) {
}
@FXML
protected void onExportGraph(ActionEvent event) {
}
/******************************************
*
* Dragging
*
******************************************/
@FXML
protected void onBarDragged(MouseEvent event) {
double offsetX = event.getSceneX() - mouseX;
double offsetY = event.getSceneY() - mouseY;
xDragDelta += offsetX;
yDragDelta += offsetY;
Pane pane = (Pane) node.getParent();
node.setLayoutX(constrain(xDragDelta, 0, pane.getWidth() - node.getWidth()));
node.setLayoutY(constrain(yDragDelta, 0, pane.getHeight() - node.getHeight()));
// again set current Mouse x AND y position
mouseX = event.getSceneX();
mouseY = event.getSceneY();
}
@FXML
protected void onBarPressed(MouseEvent event) {
mouseX = event.getSceneX();
mouseY = event.getSceneY();
xDragDelta = node.getLayoutX();
yDragDelta = node.getLayoutY();
node.toFront();
}
/******************************************
*
* Resizing
*
******************************************/
@FXML
protected void onResizeReleased(MouseEvent event) {
resizing = false;
node.setCursor(Cursor.DEFAULT);
}
@FXML
protected void onResizeOver(MouseEvent event) {
Cursor cursor = Cursor.DEFAULT;
if (updateResizeState(event) || resizing) {
if (resizingX && resizingY) {
cursor = Cursor.NW_RESIZE;
} else if (resizingX) {
cursor = Cursor.E_RESIZE;
} else if (resizingY) {
cursor = Cursor.S_RESIZE;
}
}
node.setCursor(cursor);
}
@FXML
protected void onResizeDragged(MouseEvent event) {
if (!resizing) {
return;
}
Pane pane = (Pane) node.getParent();
if (resizingX) {
double width = node.getMinWidth() + (event.getX() - mouseX);
node.setMinWidth(constrain(width, node.getPrefWidth(), pane.getWidth() - node.getLayoutX()));
mouseX = event.getX();
}
if (resizingY) {
double height = node.getMinHeight() + (event.getY() - mouseY);
node.setMinHeight(constrain(height, node.getPrefHeight(), pane.getHeight() - node.getLayoutY()));
mouseY = event.getY();
}
}
@FXML
protected void onResizePressed(MouseEvent event) {
if (!updateResizeState(event)) {
return;
}
resizing = true;
mouseY = event.getY();
mouseX = event.getX();
}
protected boolean updateResizeState(MouseEvent event) {
resizingX = event.getX() > node.getWidth() - RESIZE_MARGIN;
resizingY = event.getY() > node.getHeight() - RESIZE_MARGIN;
return resizingX || resizingY;
}
private double constrain(double value, double min, double max) {
if (value < min) {
return min;
}
if (value > max) {
return max;
}
return value;
}
public void update(double[] values, String tag) {
if(!series.containsKey(tag)){
XYChart.Series series = new XYChart.Series();
series.setName(tag);
lineGraph.getData().add(series);
this.series.put(tag, series);
}
series.get(tag).getData().addAll(values);
}
}
谢谢。