<fx:root>
обеспечивает решение проблемы определения повторно используемого компонента с помощью FXML.
В качестве примера предположим, что вы хотите определить простой пользовательский компонент, состоящий из TextField
и Button
содержащихся в HBox
. Вам нужно, чтобы это было представлено подклассом Node
, поэтому вы можете написать код, например
VBox vbox = new VBox();
vbox.getChildren().add(new MyComponent());
. Проблема в том, что вам нужен класс Java, который является подклассом Node
, а также FXML. В чистой Java (без FXML) вы можете сделать это с помощью:
public class MyComponent extends HBox {
private TextField textField ;
private Button button ;
public MyComponent() {
textField = new TextField();
button = new Button();
this.getChildren().addAll(textField, button);
}
}
Использование FXML для определения настраиваемого компонента без элемента <fx:root>
представляет проблему, потому что вам нужен FXML, чтобы быть чем-то вроде узла, а затем другой экземпляр узла для представления класса, обертывающего его:
<HBox>
<TextField fx:id="textField"/>
<Button fx:id="button" />
</HBox>
и
public class MyComponent extends HBox {
@FXML
private TextField textField ;
@FXML
private Button button ;
public MyComponent() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyComponent.fxml"));
loader.setController(this);
HBox hbox = loader.load();
this.getChildren().add(hbox);
} catch (IOException exc) {
// handle exception
}
}
}
Это приводит к тому, что MyComponent состоит из HBox, обертывающего HBox, обертывающий TextField и кнопка. Дополнительный избыточный HBox является результатом необходимости использования одного узла для корня FXML и одного узла для представления компонента.
<fx:root>
дает механизм для создания Узла в качестве компонента (класс Java) и затем проинструктировать файл FXML использовать этот узел в качестве его корня:
<fx:root type="javafx.scene.layout.HBox">
<TextField fx:id="textField" />
<Button fx:id="button" />
</fx:root>
и
public class MyComponent extends HBox {
@FXML
private TextField textField ;
@FXML
private Button button ;
public MyComponent() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyComponent.fxml"));
loader.setController(this);
loader.setRoot(this);
loader.load();
} catch (IOException exc) {
// handle exception
}
}
}
Теперь MyComponent
имеет ту же структуру, что и исходная версия all-Java , a HBox
, содержащий TextField
и Button
. Вы не можете сделать это с помощью FXML без элемента <fx:root>
.
Насколько я понимаю, на стороне сервера Вы не поддерживаете голоса по отдельности, Вы просто добавляете существующее голосование с новым голосом, полученным из внешнего интерфейса. Чтобы иметь возможность обновить отправленное сообщение, ваш сервер должен знать, какой был старый голос, предоставленный в старом Голосовании. Таким образом, чтобы реализовать обновление по выбору голосов, ваш клиент должен предоставить старый голос, а также новый голос, который будет обновлен, чтобы сервер мог вычесть старый голос и добавить новый голос.
Ниже приведен дополнительный класс на стороне клиента, который необходимо добавить в угловом формате.
public vote(id, oldNum, newNum) {
var voted = { id: id, oldVote: oldNum, newVote:newNum };
this.socket.emit('updateVote', voted);
}
Этот сервис вам нужно называть так же, как отправку нового голоса, но нужно предоставить oldVote
и newVote
.
Ниже приведен код на стороне сервера для принятия этого редактирования отправленного голосования. Здесь вам нужно добавить еще одного слушателя событий для редактирования пропущенного голоса.
socket.on('updateVote', (ballet) => {
messageList[ballet.id].rank -= ballet.oldVote;
messageList[ballet.id].rank += ballet.newVote;
io.to('main room').emit('new-message', messageList[ballet.id]);
});
Выше кода, вычитает уже проголосовал и добавляет новый голос.