#javafx #combobox #treeview
#javafx #выпадающий список #древовидный вид
Вопрос:
Я пытаюсь создать древовидный просмотр, который будет иметь на каждой ветке и лист со списком, кнопку «добавить дочерний элемент» и кнопку «удалить дочерний элемент». Вот мой код
package example;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* @author me
*/
public class Example extends Application {
String[] companyNames = new String[10];
@Override
public void start(Stage primaryStage) {
companyNames[0]="FORD";
companyNames[1]="MG";
companyNames[2]="LADA";
companyNames[3]="BMW";
companyNames[4]="KIA";
companyNames[5]="HYUNDAI";
companyNames[6]="AUDI";
companyNames[7]="MERCEDES";
companyNames[8]="DACIA";
companyNames[9]="TOYOTA";
final TreeItem<String> treeRootItem = new TreeItem<>("Root");
final TreeView<String> treeView = new TreeView<>(treeRootItem);
treeRootItem.setExpanded(true);
treeView.setCellFactory(e -> new CustomCell());
VBox mainVBox = new VBox();
mainVBox.getChildren().add(treeView);
Scene scene1 = new Scene(mainVBox,1600,600);
primaryStage.setScene(scene1);
primaryStage.show();
primaryStage.centerOnScreen();
}
//function custom TreeCell CustomCell
class CustomCell extends TreeCell<String> {
@Override
protected void updateItem(String item, boolean empty)
{
ComboBox companiesComboBox = new ComboBox();
Button addChildButton = new Button("Add Child");
Button removeButton = new Button("Remove Child");
super.updateItem(item, empty);
if (isEmpty()) {
setGraphic(null);
setText(null);
}
else {
HBox cellBox = new HBox(10);
if (item.equals("Root"))
{
cellBox.getChildren().addAll(companiesComboBox,addChildButton);
}
else cellBox.getChildren().addAll(companiesComboBox,addChildButton,removeButton);
setGraphic(cellBox);
setText(null);
}
companiesComboBox.getItems().addAll((Object[]) companyNames);
addChildButton.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent e) {
String selection=companiesComboBox.getSelectionModel().getSelectedItem().toString();
TreeItem<String> childNode1 = new TreeItem<>("Child Node");
getTreeItem().getChildren().add(childNode1);
}});
removeButton.setOnAction(value -> {
//somehow i will remove the leaf/branch
});
}
}
public static void main(String[] args) {
launch(args);
}
}
(Как указала Александра, в моем предыдущем посте у меня было много неправильных соглашений об именах Java, надеюсь, я исправил это сейчас.
Прошу прощения, что я удалил свой предыдущий пост, но он был не по теме со многими ошибками, поэтому я решил провести небольшое исследование, как сделать сообщение с лучшим кодом и более конкретным без ошибок, и вернуться через несколько дней.Я надеюсь, что теперь это презентабельно.)
Проблема, с которой я сталкиваюсь, заключается в том, что когда я добавляю нового дочернего элемента, дерево отверстий теряет выбор со списком.
Вот изображение запущенного проекта https://ibb.co/8MVDqhX
Любая помощь / предложение будут оценены
ОБНОВЛЕНИЕ: после ответа Slaw я попытался создать класс модели с именем SelectedCompanyClass
package example;
import javafx.beans.property.StringProperty;
/**
*
* @author me
*/
public class SelectedCompanyClass {
public String companyNameString;
public SelectedCompanyClass(String companyNameString) {
this.companyNameString = companyNameString;
}
}
И я изменил свой основной класс следующим образом
package example;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* @author me
*/
public class Example extends Application {
String[] companyNames = new String[10];
int x=0;
SelectedCompanyClass SelectedCompanyClass1;
@Override
public void start(Stage primaryStage) {
this.SelectedCompanyClass1 = new SelectedCompanyClass("root");
companyNames[0]="FORD";
companyNames[1]="MG";
companyNames[2]="LADA";
companyNames[3]="BMW";
companyNames[4]="KIA";
companyNames[5]="HYUNDAI";
companyNames[6]="AUDI";
companyNames[7]="MERCEDES";
companyNames[8]="DACIA";
companyNames[9]="TOYOTA";
final TreeItem<SelectedCompanyClass> treeRootItem = new TreeItem<>(SelectedCompanyClass1);
final TreeView<SelectedCompanyClass> treeView = new TreeView<>(treeRootItem);
treeRootItem.setExpanded(true);
treeView.setCellFactory(e -> new CustomCell());
VBox mainVBox = new VBox();
mainVBox.getChildren().add(treeView);
Scene scene1 = new Scene(mainVBox,1600,600);
primaryStage.setScene(scene1);
primaryStage.show();
primaryStage.centerOnScreen();
System.out.println("Start runs");
}
class CustomCell extends TreeCell<SelectedCompanyClass> {
protected void updateItem(SelectedCompanyClass SelectedCompanyClass1, boolean empty)
{
ComboBox companiesComboBox = new ComboBox();
Button addChildButton = new Button("Add Child");
Button removeButton = new Button("Remove Child");
super.updateItem(SelectedCompanyClass1,empty);
if (isEmpty()) {
setGraphic(null);
setText(null);
}
else {
HBox cellHBox = new HBox();
if (SelectedCompanyClass1!=null)
{
if (SelectedCompanyClass1.companyNameString.equals("Root"))
{
cellHBox.getChildren().addAll(companiesComboBox,addChildButton);
}
else cellHBox.getChildren().addAll(companiesComboBox,addChildButton,removeButton);
companiesComboBox.getSelectionModel().select(SelectedCompanyClass1.companyNameString);
}
setGraphic(cellHBox);
setText(null);
}
companiesComboBox.getItems().addAll((Object[]) companyNames);
addChildButton.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent e) {
String selection="none";
SelectedCompanyClass SelectedCompanyClass2 = new SelectedCompanyClass(selection);
if (companiesComboBox.getSelectionModel().getSelectedItem().toString()!=null) {
selection=companiesComboBox.getSelectionModel().getSelectedItem().toString();
SelectedCompanyClass2.companyNameString=selection;
}
TreeItem<SelectedCompanyClass> childNode2 = new TreeItem<>(SelectedCompanyClass2);
getTreeItem().getChildren().add(childNode2);
childNode2.setExpanded(true);
}});
removeButton.setOnAction(value -> {
//somehow i will remove the leaf/branch
});
}
}
public static void main(String[] args) {
launch(args);
}
}
Теперь, благодаря Slaw, я добился прогресса и создаю новые объекты TreeItem как дочерние, но родительский узел теряет свой выбор в списке
ОБНОВЛЕНИЕ 2: после полезных предложений я, наконец, сделал это, вот код
Код класса модели
package example;
import javafx.beans.property.StringProperty;
public class SelectedCompanyClass {
String companyNameString = new String();
public SelectedCompanyClass() {
companyNameString="Choose";
}
}
и основной код
package example;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* @author me
*/
public class Example extends Application {
String[] companyNames = new String[10];
int x=0;
@Override
public void start(Stage primaryStage) {
SelectedCompanyClass SelectedCompanyClass1 = new SelectedCompanyClass();
companyNames[0]="FORD";
companyNames[1]="MG";
companyNames[2]="LADA";
companyNames[3]="BMW";
companyNames[4]="KIA";
companyNames[5]="HYUNDAI";
companyNames[6]="AUDI";
companyNames[7]="MERCEDES";
companyNames[8]="DACIA";
companyNames[9]="TOYOTA";
final TreeItem<SelectedCompanyClass> treeRootItem = new TreeItem<>(SelectedCompanyClass1);
final TreeView<SelectedCompanyClass> treeView = new TreeView<>(treeRootItem);
treeRootItem.setExpanded(true);
treeView.setCellFactory(e -> new CustomCell());
VBox mainVBox = new VBox();
mainVBox.getChildren().add(treeView);
Scene scene1 = new Scene(mainVBox,1600,600);
primaryStage.setScene(scene1);
primaryStage.show();
primaryStage.centerOnScreen();
System.out.println("Start runs");
}
class CustomCell extends TreeCell<SelectedCompanyClass> {
protected void updateItem(SelectedCompanyClass SelectedCompanyClass1, boolean empty)
{
ComboBox companiesComboBox = new ComboBox();
Button addChildButton = new Button("Add Child");
Button removeButton = new Button("Remove");
Label objectLabel = new Label();
companiesComboBox.valueProperty().addListener((obs, oldValue, newValue) -> {
SelectedCompanyClass1.companyNameString=newValue.toString();
});
super.updateItem(SelectedCompanyClass1,empty);
if (isEmpty()) {
setGraphic(null);
setText(null);
}
else {
HBox cellHBox = new HBox();
if (SelectedCompanyClass1!=null)
{
cellHBox.getChildren().addAll(companiesComboBox,addChildButton,removeButton,objectLabel);
companiesComboBox.getSelectionModel().select(SelectedCompanyClass1.companyNameString);
}
setGraphic(cellHBox);
setText(null);
}
companiesComboBox.getItems().addAll((Object[]) companyNames);
addChildButton.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent e) {
String selection="none";
SelectedCompanyClass SelectedCompanyClass2 = new SelectedCompanyClass();
TreeItem<SelectedCompanyClass> childNode2 = new TreeItem<>(SelectedCompanyClass2);
getTreeItem().getChildren().add(childNode2);
childNode2.setExpanded(true);
companiesComboBox.valueProperty().addListener((obs, oldValue, newValue) -> {
SelectedCompanyClass2.companyNameString=newValue.toString();
});
}});
removeButton.setOnAction(value -> {
//somehow i will remove the leaf/branch
});
}
}
public static void main(String[] args) {
launch(args);
}
}
С наилучшими пожеланиями всем
Комментарии:
1. Я не анализировал ваш код подробно, но моя интуиция подсказывает мне, что проблема в том, что у вас нет модели . Поскольку у вас нет модели, вы используете представление для поддержания состояния, а это бесполезно. Создайте модель и просто
TreeView<YourModel>
отобразите состояние указанной модели. Затем взаимодействие с деревом обновляет модель , и дерево отслеживает модель на предмет изменений, чтобы быть в курсе последних событий.2. Спасибо за ваш любезный ответ, Slaw, я рассмотрю его
3. Не создавайте новое поле со списком в
updateItem()
; создайте один раз для каждого экземпляра ячейки (например, в конструкторе) и установите его выбранное значениеupdateItem()
. Но это не имеет для меня абсолютно никакого смысла: в каком смысле одна компания является дочерней компанией другой компании? Кроме того, пожалуйста, не удаляйте и, по сути, не публикуйте один и тот же вопрос; вы должны отредактировать свой старый вопрос.4. Да, спасибо, James_D я пытался добавить конструктор, но у меня не получилось заставить его работать
5. Спасибо, Клеопатра, я допустил ошибку в именовании; я прочитал несколько статей и попытался быть корректным в своем коде