Programming Basics SQL HTML CSS JavaScript Python C++ Java JavaFX Swing Problem Solving English English Conversations Computer Fundamentals Learn Typing

JavaFXطريقة جعل المستخدم قادر على إضافة و حذف و تعديل بيانات الـTreeView

المثال التالي يعلمك طريقة جعل المستخدم قادر على إضافة و حذف و تعديل بيانات الـ TreeView بطريقة إحترافية.

ملاحظة: عليك إنشاء مجلد و وضع الصور فيه كما في الصورة التالية.

الصورة توضح أننا أضفنا مجلد إسمه images و وضعنا فيه أربع صور.

⇓ تحميل مجلد الصور


مثال

EditableItem.java
import javafx.event.ActionEvent;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
// متطورة TreeItem و بالتالي أصبح إنشاء كائن منه يعني إنشاء TreeCell هنا قمنا بتعريف كلاس يرث من الكلاس
public class EditableItem extends TreeCell<String> {
// يمثل قسم في الشركة TreeItem هنا قمنا بتعريف دالة ترجع الأيقونة التي سنضعها لكل كائن
public ImageView getDepartmentIcon() {
return new ImageView(new Image(getClass().getResourceAsStream("images/department-icon.png")));
}
// يمثل موظف في الشركة TreeItem هنا قمنا بتعريف دالة ترجع الأيقونة التي سنضعها لكل كائن
public ImageView getUserMaleIcon() {
return new ImageView(new Image(getClass().getResourceAsStream("images/user-male-icon.png")));
}
// يمثل موظفة في الشركة TreeItem هنا قمنا بتعريف دالة ترجع الأيقونة التي سنضعها لكل كائن
public ImageView getUserFemaleIcon() {
return new ImageView(new Image(getClass().getResourceAsStream("images/user-female-icon.png")));
}
// TreeItem في كل مرة يريد فيها المستخدم أن يقوم بتعديل نص TextField لأننا سنظهر textField هنا قمنا بتعريف كائن
private TextField textField;
// الذي يمثل الشركة Root Item هنا قمنا بتعريف القائمة التي سنظهرها عندما ينقر المستخدمم بزر الفأرة الأيمن على الـ
private final ContextMenu menuForRootItem = new ContextMenu();
// هنا قمنا بتعريف القائمة التي سنظهرها عندما ينقر المستخدمم بزر الفأرة الأيمن على أي قسم موجود في الشركة
private final ContextMenu menuForAnyDepartment = new ContextMenu();
// هنا قمنا بتعريف القائمة التي سنظهرها عندما ينقر المستخدمم بزر الفأرة الأيمن على أي مستخدم موجود بداخل قسم
private final ContextMenu menuForAnyUser = new ContextMenu();
// الكونستركتور
public EditableItem() {
// هنا قمنا بتعريف عناصر القائمة التي تظهر عند النقر بزر الفأرة الأيمن على الشركة
MenuItem addNewDepartment = new MenuItem("Add new department");
MenuItem deleteAllDepartments = new MenuItem("Delete all departments");
// هنا قمنا بتعريف عناصر القائمة التي تظهر عند النقر بزر الفأرة الأيمن على أي قسم
MenuItem addNewMale = new MenuItem("Add a male employee");
MenuItem addNewFemale = new MenuItem("Add a female employee");
MenuItem deleteAllEmployees = new MenuItem("Delete all employees");
MenuItem deleteDepartment = new MenuItem("Delete department");
// هنا قمنا بتعريف عنصر القائمة الذي يظهر عند النقر بزر الفأرة الأيمن على أي موظف أو موظفة
MenuItem deleteUser = new MenuItem("Delete User");
// فيها menuForRootItem هنا قمنا بإضافة عناصر على القائمة
menuForRootItem.getItems().addAll(addNewDepartment, deleteAllDepartments);
// فيها menuForRootDepartment هنا قمنا بإضافة العناصر عناصر القائمة
menuForAnyDepartment.getItems().addAll(addNewMale, addNewFemale, deleteAllEmployees, deleteDepartment);
// فيها menuForRootItem هنا قمنا بإضافة عنصر على القائمة
menuForAnyUser.getItems().addAll(deleteUser);
// addNewDepartment هنا قمنا بتحديد ما سيحدث عند النقر على العنصر
addNewDepartment.setOnAction((ActionEvent t) -> {
TreeItem newDepartment = new TreeItem<>("New Department", getDepartmentIcon());
getTreeItem().getChildren().add(newDepartment);
newDepartment.setExpanded(true);
});
// deleteAllDepartments هنا قمنا بتحديد ما سيحدث عند النقر على العنصر
deleteAllDepartments.setOnAction((ActionEvent t) -> {
getTreeItem().getChildren().remove(0, getTreeItem().getChildren().size());
});
// addNewMale هنا قمنا بتحديد ما سيحدث عند النقر على العنصر
addNewMale.setOnAction((ActionEvent t) -> {
TreeItem newDepartment = new TreeItem<>("New Employee", getUserMaleIcon());
getTreeItem().getChildren().add(newDepartment);
});
// addNewFemale هنا قمنا بتحديد ما سيحدث عند النقر على العنصر
addNewFemale.setOnAction((ActionEvent t) -> {
TreeItem newDepartment = new TreeItem<>("New Employee", getUserFemaleIcon());
getTreeItem().getChildren().add(newDepartment);
});
// deleteAllEmployees هنا قمنا بتحديد ما سيحدث عند النقر على العنصر
deleteAllEmployees.setOnAction((ActionEvent t) -> {
getTreeItem().getChildren().remove(0, getTreeItem().getChildren().size());
});
// deleteDepartment هنا قمنا بتحديد ما سيحدث عند النقر على العنصر
deleteDepartment.setOnAction((ActionEvent t) -> {
getTreeItem().getParent().getChildren().remove(getTreeItem());
});
// deleteUser هنا قمنا بتحديد ما سيحدث عند النقر على العنصر
deleteUser.setOnAction((ActionEvent t) -> {
getTreeItem().getParent().getChildren().remove(getTreeItem());
});
}
// بداخله بعد TreeItem أو ترجع نص فارغ في حال كان لا يحتوي على EditableItem هنا قمنا بتعريف دالة ترجع نص الـ
// و هذا يعني أنه في حال كان قد تم إنشاؤه فإننا لن نفقد القيمة الموجودة فيه
private String getString() {
return getItem() == null ? "" : getItem();
}
// EditableItem عند النقر على الـ TextField هنا قمنا بتعريف الدالة التي تنشئ
private void createTextField() {
// getString() فيه و الذي ترجعه الدالة EditableItem و تمرير النص الذي كان ظاهراً على الـ TextField هنا سيتم إنشاء الـ
textField = new TextField(getString());
// EditableItem هنا قمنا بفحص كل حرف يدخله المستخدم عند تعديل نص الـ
textField.setOnKeyReleased((KeyEvent t) -> {
// سيتم حفظ التعديلات Enter إذا قام المستخدم بالنقر على الزر
if (t.getCode() == KeyCode.ENTER) {
commitEdit(textField.getText());
}
// سيتم إلغاء التعديلات Esc إذا قام المستخدم بالنقر على الزر
else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
});
}
// TextField التي تنشئ createTextField() سيتم إستدعاء الدالة EditableItem هنا قلنا أنه عند تعديل نص الـ
@Override
public void startEdit() {
super.startEdit();
if (textField == null) {
createTextField();
}
setText(null);
setGraphic(textField);
textField.selectAll();
}
// سيتم إعادة النص الذي كان موجوداً من قبل EditableItem هنا قلنا أنه عند إلغاء تعديل نص الـ
@Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(getTreeItem().getGraphic());
}
// بأي شكلٍ كان EditableItem هنا قمنا بتحديد ما سيحدث عند محاولة تعديل الـ
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
// TreeView في حال تم إلغاؤه قلنا أنه سيتم مسحه من الـ
if (empty) {
setText(null);
setGraphic(null);
}
// في حال تم التفاعل معه بأي طريقة
else {
// مكانه ثم تحديث النافذة لإظهار النص الجديد TextField في حال كان يتم تعديل نصه سيتم وضع النص الذي تم إدخاله في الـ
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
}
// في حال تم النقر عليه بواسطة زر الفأرة الأيمن
else {
// سيتم تحديث النافذة لضمان أن يتم إظهاره بشكل صحيح
setText(getString());
setGraphic(getTreeItem().getGraphic());
// TreeView ثم سيتم إظهار القائمة الخاصة بالشركة إذا تم النقر على أول شيء في الـ
if (getTreeItem().getParent() == null) {
setContextMenu(menuForRootItem);
}
// TreeView أو سيتم إظهار القائمة الخاصة بالأقسام إذا تم النقر على أي شيء موضوع تحت الشركة في الـ
else if( getTreeItem().getParent().getParent() == null) {
setContextMenu(menuForAnyDepartment);
}
// TreeView أو سيتم إظهار القائمة الخاصة بالموظفين و المظفات إذا تم النقر على أي شيء موضوع تحت أي قسم في الـ
else if( getTreeItem().getParent().getParent().getParent() == null) {
setContextMenu(menuForAnyUser);
}
}
}
}
}
import javafx.event.ActionEvent; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.control.TextField; import javafx.scene.control.TreeCell; import javafx.scene.control.TreeItem; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; // متطورة TreeItem و بالتالي أصبح إنشاء كائن منه يعني إنشاء TreeCell هنا قمنا بتعريف كلاس يرث من الكلاس public class EditableItem extends TreeCell<String> { // يمثل قسم في الشركة TreeItem هنا قمنا بتعريف دالة ترجع الأيقونة التي سنضعها لكل كائن public ImageView getDepartmentIcon() { return new ImageView(new Image(getClass().getResourceAsStream("images/department-icon.png"))); } // يمثل موظف في الشركة TreeItem هنا قمنا بتعريف دالة ترجع الأيقونة التي سنضعها لكل كائن public ImageView getUserMaleIcon() { return new ImageView(new Image(getClass().getResourceAsStream("images/user-male-icon.png"))); } // يمثل موظفة في الشركة TreeItem هنا قمنا بتعريف دالة ترجع الأيقونة التي سنضعها لكل كائن public ImageView getUserFemaleIcon() { return new ImageView(new Image(getClass().getResourceAsStream("images/user-female-icon.png"))); } // TreeItem في كل مرة يريد فيها المستخدم أن يقوم بتعديل نص TextField لأننا سنظهر textField هنا قمنا بتعريف كائن private TextField textField; // الذي يمثل الشركة Root Item هنا قمنا بتعريف القائمة التي سنظهرها عندما ينقر المستخدمم بزر الفأرة الأيمن على الـ private final ContextMenu menuForRootItem = new ContextMenu(); // هنا قمنا بتعريف القائمة التي سنظهرها عندما ينقر المستخدمم بزر الفأرة الأيمن على أي قسم موجود في الشركة private final ContextMenu menuForAnyDepartment = new ContextMenu(); // هنا قمنا بتعريف القائمة التي سنظهرها عندما ينقر المستخدمم بزر الفأرة الأيمن على أي مستخدم موجود بداخل قسم private final ContextMenu menuForAnyUser = new ContextMenu(); // الكونستركتور public EditableItem() { // هنا قمنا بتعريف عناصر القائمة التي تظهر عند النقر بزر الفأرة الأيمن على الشركة MenuItem addNewDepartment = new MenuItem("Add new department"); MenuItem deleteAllDepartments = new MenuItem("Delete all departments"); // هنا قمنا بتعريف عناصر القائمة التي تظهر عند النقر بزر الفأرة الأيمن على أي قسم MenuItem addNewMale = new MenuItem("Add a male employee"); MenuItem addNewFemale = new MenuItem("Add a female employee"); MenuItem deleteAllEmployees = new MenuItem("Delete all employees"); MenuItem deleteDepartment = new MenuItem("Delete department"); // هنا قمنا بتعريف عنصر القائمة الذي يظهر عند النقر بزر الفأرة الأيمن على أي موظف أو موظفة MenuItem deleteUser = new MenuItem("Delete User"); // فيها menuForRootItem هنا قمنا بإضافة عناصر على القائمة menuForRootItem.getItems().addAll(addNewDepartment, deleteAllDepartments); // فيها menuForRootDepartment هنا قمنا بإضافة العناصر عناصر القائمة menuForAnyDepartment.getItems().addAll(addNewMale, addNewFemale, deleteAllEmployees, deleteDepartment); // فيها menuForRootItem هنا قمنا بإضافة عنصر على القائمة menuForAnyUser.getItems().addAll(deleteUser); // addNewDepartment هنا قمنا بتحديد ما سيحدث عند النقر على العنصر addNewDepartment.setOnAction((ActionEvent t) -> { TreeItem newDepartment = new TreeItem<>("New Department", getDepartmentIcon()); getTreeItem().getChildren().add(newDepartment); newDepartment.setExpanded(true); }); // deleteAllDepartments هنا قمنا بتحديد ما سيحدث عند النقر على العنصر deleteAllDepartments.setOnAction((ActionEvent t) -> { getTreeItem().getChildren().remove(0, getTreeItem().getChildren().size()); }); // addNewMale هنا قمنا بتحديد ما سيحدث عند النقر على العنصر addNewMale.setOnAction((ActionEvent t) -> { TreeItem newDepartment = new TreeItem<>("New Employee", getUserMaleIcon()); getTreeItem().getChildren().add(newDepartment); }); // addNewFemale هنا قمنا بتحديد ما سيحدث عند النقر على العنصر addNewFemale.setOnAction((ActionEvent t) -> { TreeItem newDepartment = new TreeItem<>("New Employee", getUserFemaleIcon()); getTreeItem().getChildren().add(newDepartment); }); // deleteAllEmployees هنا قمنا بتحديد ما سيحدث عند النقر على العنصر deleteAllEmployees.setOnAction((ActionEvent t) -> { getTreeItem().getChildren().remove(0, getTreeItem().getChildren().size()); }); // deleteDepartment هنا قمنا بتحديد ما سيحدث عند النقر على العنصر deleteDepartment.setOnAction((ActionEvent t) -> { getTreeItem().getParent().getChildren().remove(getTreeItem()); }); // deleteUser هنا قمنا بتحديد ما سيحدث عند النقر على العنصر deleteUser.setOnAction((ActionEvent t) -> { getTreeItem().getParent().getChildren().remove(getTreeItem()); }); } // بداخله بعد TreeItem أو ترجع نص فارغ في حال كان لا يحتوي على EditableItem هنا قمنا بتعريف دالة ترجع نص الـ // و هذا يعني أنه في حال كان قد تم إنشاؤه فإننا لن نفقد القيمة الموجودة فيه private String getString() { return getItem() == null ? "" : getItem(); } // EditableItem عند النقر على الـ TextField هنا قمنا بتعريف الدالة التي تنشئ private void createTextField() { // getString() فيه و الذي ترجعه الدالة EditableItem و تمرير النص الذي كان ظاهراً على الـ TextField هنا سيتم إنشاء الـ textField = new TextField(getString()); // EditableItem هنا قمنا بفحص كل حرف يدخله المستخدم عند تعديل نص الـ textField.setOnKeyReleased((KeyEvent t) -> { // سيتم حفظ التعديلات Enter إذا قام المستخدم بالنقر على الزر if (t.getCode() == KeyCode.ENTER) { commitEdit(textField.getText()); } // سيتم إلغاء التعديلات Esc إذا قام المستخدم بالنقر على الزر else if (t.getCode() == KeyCode.ESCAPE) { cancelEdit(); } }); } // TextField التي تنشئ createTextField() سيتم إستدعاء الدالة EditableItem هنا قلنا أنه عند تعديل نص الـ @Override public void startEdit() { super.startEdit(); if (textField == null) { createTextField(); } setText(null); setGraphic(textField); textField.selectAll(); } // سيتم إعادة النص الذي كان موجوداً من قبل EditableItem هنا قلنا أنه عند إلغاء تعديل نص الـ @Override public void cancelEdit() { super.cancelEdit(); setText((String) getItem()); setGraphic(getTreeItem().getGraphic()); } // بأي شكلٍ كان EditableItem هنا قمنا بتحديد ما سيحدث عند محاولة تعديل الـ @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); // TreeView في حال تم إلغاؤه قلنا أنه سيتم مسحه من الـ if (empty) { setText(null); setGraphic(null); } // في حال تم التفاعل معه بأي طريقة else { // مكانه ثم تحديث النافذة لإظهار النص الجديد TextField في حال كان يتم تعديل نصه سيتم وضع النص الذي تم إدخاله في الـ if (isEditing()) { if (textField != null) { textField.setText(getString()); } setText(null); setGraphic(textField); } // في حال تم النقر عليه بواسطة زر الفأرة الأيمن else { // سيتم تحديث النافذة لضمان أن يتم إظهاره بشكل صحيح setText(getString()); setGraphic(getTreeItem().getGraphic()); // TreeView ثم سيتم إظهار القائمة الخاصة بالشركة إذا تم النقر على أول شيء في الـ if (getTreeItem().getParent() == null) { setContextMenu(menuForRootItem); } // TreeView أو سيتم إظهار القائمة الخاصة بالأقسام إذا تم النقر على أي شيء موضوع تحت الشركة في الـ else if( getTreeItem().getParent().getParent() == null) { setContextMenu(menuForAnyDepartment); } // TreeView أو سيتم إظهار القائمة الخاصة بالموظفين و المظفات إذا تم النقر على أي شيء موضوع تحت أي قسم في الـ else if( getTreeItem().getParent().getParent().getParent() == null) { setContextMenu(menuForAnyUser); } } } } }

Main.java
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
public class Main extends Application {
// و التي سنقصد بها الشركة Root Item الذي يمثل الـ TreeItem هنا قمنا بتعريف دالة ترجع الأيقونة التي سنضعها لكائن الـ
public ImageView getRootIcon() {
return new ImageView(new Image(getClass().getResourceAsStream("images/building-icon.png")));
}
@Override
public void start(Stage stage) {
// getRootIcon() و مررنا له أيقونة المبنى التي سترجعها الدالة TreeView في الـ Root Item و الذي سنضعه كـ TreeItem هنا قمنا بإنشاء كائن من الكلاس
TreeItem<String> rootItem = new TreeItem<>("Root Item", getRootIcon());
// يمثل القائمة الشجرية التي نريد إضافتها في النافذة TreeView هنا قمنا بإنشاء كائن من الكلاس
TreeView<String> treeView = new TreeView<>(rootItem);
// يظهر عند تشغيل البرنامج rootItem موضوع مباشرةً تحت الـ TreeItem هنا جعلنا كل كائن
rootItem.setExpanded(true);
// في النافذةView هنا قمنا بتحديد حجم الـ
treeView.setPrefSize(400, 250);
// في النافذةView هنا قمنا بتحديد مكان ظهور الكائن
treeView.setTranslateX(0);
treeView.setTranslateY(0);
// قابل للتعديل treeView هنا جعلنا محتوى الـ
treeView.setEditable(true);
// EditableItem سيتم تعديله سيتم معاملته على أنه كائن من الكلاس treeView هنا قلنا أن أي شيء بداخل الـ
treeView.setCellFactory(
(TreeView<String> p) -> new EditableItem()
);
// في النافذة Root Node لأننا ننوي جعله الـ Group هنا قمنا بإنشاء كائن من الكلاس
Group root = new Group();
// root في الكائنView هنا قمنا بإضافة الكائن
root.getChildren().add(treeView);
// فيها و تحديد حجمها Node كأول root هنا قمنا بإنشاء محتوى النافذة مع تعيين الكائن
Scene scene = new Scene(root, 400, 250);
// هنا وضعنا عنوان للنافذة
stage.setTitle("JavaFX TreeView");
// أي وضعنا محتوى النافذة الذي قمنا بإنشائه للنافذة .stage في كائن الـ scene هنا وضعنا كائن الـ
stage.setScene(scene);
// هنا قمنا بإظهار النافذة
stage.show();
}
// هنا قمنا بتشغيل التطبيق
public static void main(String[] args) {
launch(args);
}
}
import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.stage.Stage; public class Main extends Application { // و التي سنقصد بها الشركة Root Item الذي يمثل الـ TreeItem هنا قمنا بتعريف دالة ترجع الأيقونة التي سنضعها لكائن الـ public ImageView getRootIcon() { return new ImageView(new Image(getClass().getResourceAsStream("images/building-icon.png"))); } @Override public void start(Stage stage) { // getRootIcon() و مررنا له أيقونة المبنى التي سترجعها الدالة TreeView في الـ Root Item و الذي سنضعه كـ TreeItem هنا قمنا بإنشاء كائن من الكلاس TreeItem<String> rootItem = new TreeItem<>("Root Item", getRootIcon()); // يمثل القائمة الشجرية التي نريد إضافتها في النافذة TreeView هنا قمنا بإنشاء كائن من الكلاس TreeView<String> treeView = new TreeView<>(rootItem); // يظهر عند تشغيل البرنامج rootItem موضوع مباشرةً تحت الـ TreeItem هنا جعلنا كل كائن rootItem.setExpanded(true); // في النافذةView هنا قمنا بتحديد حجم الـ treeView.setPrefSize(400, 250); // في النافذةView هنا قمنا بتحديد مكان ظهور الكائن treeView.setTranslateX(0); treeView.setTranslateY(0); // قابل للتعديل treeView هنا جعلنا محتوى الـ treeView.setEditable(true); // EditableItem سيتم تعديله سيتم معاملته على أنه كائن من الكلاس treeView هنا قلنا أن أي شيء بداخل الـ treeView.setCellFactory( (TreeView<String> p) -> new EditableItem() ); // في النافذة Root Node لأننا ننوي جعله الـ Group هنا قمنا بإنشاء كائن من الكلاس Group root = new Group(); // root في الكائنView هنا قمنا بإضافة الكائن root.getChildren().add(treeView); // فيها و تحديد حجمها Node كأول root هنا قمنا بإنشاء محتوى النافذة مع تعيين الكائن Scene scene = new Scene(root, 400, 250); // هنا وضعنا عنوان للنافذة stage.setTitle("JavaFX TreeView"); // أي وضعنا محتوى النافذة الذي قمنا بإنشائه للنافذة .stage في كائن الـ scene هنا وضعنا كائن الـ stage.setScene(scene); // هنا قمنا بإظهار النافذة stage.show(); } // هنا قمنا بتشغيل التطبيق public static void main(String[] args) { launch(args); } }

ستظهر لك النافذة التالية عند التشغيل.

طريقة جعل المستخدم قادر على إضافة و حذف و تعديل بيانات ال TreeView في javafx