Я создаю графический интерфейс с помощью Scene Builder в JavaFX и Spring Boot. У некоторых моих сцен есть один общий элемент - простой индикатор KPI, называемый PerformanceBeacon. В зависимости от конфигурации, выполненной классом контроллера, маяк может использоваться, например. для параметров проекта, таких как бюджет, время и так далее. В идеале даже одна сцена может иметь несколько таких элементов.
Проблема в том, что наличие нескольких маяков KPI в одной сцене не работает, поскольку все встроенные контроллеры указывают на одну и ту же память, и, следовательно, я могу манипулировать только одним - последним - маяком KPI.
Фрагмент из файла fxml выглядит следующим образом:
...
<VBox layoutX="301.0" layoutY="325.0" spacing="6.0" AnchorPane.leftAnchor="2.0" AnchorPane.topAnchor="24.0">
<children>
<fx:include source="PerformanceBeacon.fxml" fx:id="embeddedTimeKPI" />
<fx:include source="PerformanceBeacon.fxml" fx:id="embeddedBudgetKPI"/>
<fx:include source="PerformanceBeacon.fxml" fx:id="embeddedResourcesKPI"/>
<fx:include source="PerformanceBeacon.fxml" fx:id="embeddedScopeKPI"/>
<fx:include source="PerformanceBeacon.fxml" fx:id="embeddedEffortKPI"/>
<fx:include source="PerformanceBeacon.fxml" fx:id="embeddedQualityKPI"/>
</children>
</VBox>
...
Встроенные контроллеры определены в классе контроллеров окружающего пользовательского интерфейса, и код должен «только» устанавливать метку каждой из гиперссылок в каждом PerformanceBeacon.
@Controller
public class ProductManagerCtrl implements Initializable {
...
@FXML protected PerformanceBeaconCtrl embeddedTimeKPIController;
@FXML protected PerformanceBeaconCtrl embeddedBudgetKPIController;
@FXML protected PerformanceBeaconCtrl embeddedResourcesKPIController;
@FXML protected PerformanceBeaconCtrl embeddedScopeKPIController;
@FXML protected PerformanceBeaconCtrl embeddedEffortKPIController;
@FXML protected PerformanceBeaconCtrl embeddedQualityKPIController;
...
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
...
initializePerformanceIndicator();
...
}
protected void initializePerformanceIndicator() {
embeddedBudgetKPIController.setHyperlink("Budget", null);
embeddedScopeKPIController.setHyperlink("Scope", null);
embeddedTimeKPIController.setHyperlink("Time", null);
embeddedQualityKPIController.setHyperlink("Quality", null);
embeddedResourcesKPIController.setHyperlink("Resources", null);
embeddedEffortKPIController.setHyperlink("Effort estimates", null);
}
Когда я отлаживаю код, каждый из этих встроенных контроллеров указывает на одну и ту же память. Таким образом, у меня есть один контроллер, и я могу манипулировать только последним элементом. В конце последний маяк имеет метку «Оценки усилий», а все остальные остаются без изменений.
PerformanceBeacon.fxml довольно прост. Я копирую его, если вы хотите попробовать себя
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.Double?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.shape.Circle?>
<?import javafx.scene.shape.Polygon?>
<GridPane styleClass="pane" stylesheets="@../stylesheets/PerformanceBeacon.css" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.agiletunes.productmanager.controllers.PerformanceBeaconCtrl">
<children>
<Circle fx:id="beacon" fill="#1fff4d" radius="10.0" stroke="BLACK" strokeType="INSIDE" GridPane.columnIndex="1" GridPane.valignment="CENTER">
<GridPane.margin>
<Insets bottom="12.0" left="12.0" right="6.0" top="12.0" />
</GridPane.margin>
</Circle>
<Polygon fx:id="trendArrow" fill="#11ff1c" rotate="45.0" stroke="#2e229a" strokeType="INSIDE" GridPane.columnIndex="2" GridPane.valignment="CENTER">
<points>
<Double fx:value="-10.0" />
<Double fx:value="10.0" />
<Double fx:value="-5.0" />
<Double fx:value="10.0" />
<Double fx:value="-5.0" />
<Double fx:value="15.0" />
<Double fx:value="5.0" />
<Double fx:value="15.0" />
<Double fx:value="5.0" />
<Double fx:value="10.0" />
<Double fx:value="10.0" />
<Double fx:value="10.0" />
<Double fx:value="0.0" />
<Double fx:value="-10.0" />
</points>
<GridPane.margin>
<Insets bottom="12.0" left="12.0" right="12.0" top="12.0" />
</GridPane.margin>
</Polygon>
<Hyperlink fx:id="hyperlink" onAction="#showDetails" text="Subject">
<GridPane.margin>
<Insets left="24.0" />
</GridPane.margin>
</Hyperlink>
</children>
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" maxWidth="1.7976931348623157E308" minWidth="170.0" />
<ColumnConstraints minWidth="10.0" />
<ColumnConstraints minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints />
</rowConstraints>
</GridPane>
И последний, но не менее важный, контроллер PerformanceBeacon
@Controller
public class PerformanceBeaconCtrl {
@FXML protected Circle beacon;
@FXML private Polygon trendArrow;
@FXML private Hyperlink hyperlink;
@FXML
public void showDetails(ActionEvent event) {
// TODO
}
public void setHyperlink(String label, URL url) {
Platform.runLater(() -> {
hyperlink.setText(label);
});
}
public void setBeaconColor(Color color) {
Platform.runLater(() -> {
beacon.setFill(color);
});
}
public void setTrend(Double angle) {
Platform.runLater(() -> {
trendArrow.rotateProperty().set(angle);
});
}
}
Я успешно использую встроенные элементы / контроллер пользовательского интерфейса и в других местах моего кода. Но никогда не один и тот же элемент несколько раз.
Я не уверен, является ли это побочным эффектом Spring?
Что я делаю не так? Заранее спасибо.