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

JavaFXطريقة إظهار قائمة ContextMenu عند النقر على زر الفأرة الأيمن

معلومة تقنية

في JavaFX لا يمكنك وضع حدود (Borders) لصورة تعرضها بالأساس بواسطة ImageView. إن أردت وضع حدود للصورة, يمكنك أنت تضع الـ ImageView الذي يمثل الصورة بداخل Pane ثم تقوم بوضع حدود لهذا الـ Pane. عندها سيظهر حول الصورة لأن الصورة موضوعة بداخله.

و طبعاً, يمكنك إستخدام أي حاوية أخرى متوفرة في JavaFX غير الـ Pane مثل StackPane, BorderPane الخ..


المثال التالي يعلمك طريقة إنشاء كائن من الكلاس ContextMenu يمثل قائمة تظهر عند النقر على زر الفأرة الأيمن ( Right Click ).
هذه القائمة تسمح للمستخدم بقلب الصورة يميناً و يساراً, إظهار خط حولها, تحديد لون الخط, إخفاء الخط.

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

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

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


مثال

Main.java
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioMenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Main extends Application {
// لأننا ننوي وضع الصورة بداخله pane هنا قمنا بإنشاء كائن من الكلاس
Pane pane = new Pane();
// يمثل الصورة التي تظهر في النافذة Image هنا قمنا بإنشاء كائن من الكلاس
Image image = new Image(getClass().getResourceAsStream("/images/javafx-icon.png"));
// في النافذة image لعرض الصورة التي يشير لها الكائن ImageView هنا قمنا بإنشاء كائن من الكلاس
ImageView imageView = new ImageView(image);
// يمثل القائمة التي تظهر عن النقر بزر الفأرة الأيمن فوق الصورة ContextMenu هنا قمنا بإنشاء كائن من الكلاس
ContextMenu contextMenu = new ContextMenu();
// هنا قمنا بإنشاء جميع الكائنات التي سنستخدمها كعناصر بداخل القائمة
MenuItem menuItem1 = new MenuItem("Rotate Right");
MenuItem menuItem2 = new MenuItem("Rotate Left");
CheckMenuItem checkMenuItem = new CheckMenuItem("Show Border");
RadioMenuItem radioMenuItem1 = new RadioMenuItem("Black Border");
RadioMenuItem radioMenuItem2 = new RadioMenuItem("Blue Border");
// radioMenuItem2 و radioMenuItem1 لأننا ننوي وضع الكائنين toggleGroup هنا قمنا بإنشاء كائن من الكلاس
// لاحقاً في مجموعة واحدة لجعل المستخدم قادر على إختيار إحداهما في كل مرة و ليس كلاهما
ToggleGroup toggleGroup = new ToggleGroup();
// الذي يحتوي على الصورة pane هنا قمنا بتعريف دالة خاصة لرسم أو إخفاء حدود الكائن
public void drawBorderOnDemande()
{
// checkMenuItem إذا كان يوجد على صح على الكائن
if (checkMenuItem.isSelected())
{
// pane سيتم إظهار حدود لونها أزرق للكائن radioMenuItem1 إذا كان يوجد علامة صح على الكائن
if (radioMenuItem1.isSelected())
{
pane.setStyle("-fx-border-style: solid; -fx-border-color: black;");
}
// pane سيتم إظهار حدود لونها أسود للكائن radioMenuItem2 إذا كان يوجد علامة صح على الكائن
else
{
pane.setStyle("-fx-border-style: solid; -fx-border-color: blue;");
}
}
// pane سيتم إزالة الحدود عن الكائن checkMenuItem إذا لم يكن هناك علامة صح على الكائن
else
{
pane.setStyle("-fx-border:none;");
}
}
// قابلين للنقر أم لا radioMenuItem2 و radioMenuItem1 هنا قمنا بتعريف دالة خاصة لتحديد ما إذا كان يجب جعل الكائنين
public void autoEnableOrDisableMenuOptions()
{
// قابلين للنقر radioMenuItem2 و radioMenuItem1 سيتم جعل الكائنين checkMenuItem إذا قام المستخدم بوضع علامة صح على الكائن
if (checkMenuItem.isSelected())
{
radioMenuItem1.setDisable(false);
radioMenuItem2.setDisable(false);
}
// غير قابلين للنقر radioMenuItem2 و radioMenuItem1 سيتم جعل الكائنين checkMenuItem إذا قام المستخدم بإزالة علامة الصح عن الكائن
else
{
radioMenuItem1.setDisable(true);
radioMenuItem2.setDisable(true);
}
}
@Override
public void start(Stage stage) {
// في النافذة pane هنا قمنا بتحديد حجم و مكان الكائن
pane.setPrefSize(202, 202);
pane.setTranslateX(99);
pane.setTranslateY(24);
// pane في الكائن imageView هنا قمنا بوضع الكائن
pane.getChildren().add(imageView);
// للأننا وضعناه بداخله pane بالنسبة للكائن imageView هنا قمنا بتحديد حجم و مكان الكائن
imageView.setFitWidth(200);
imageView.setFitHeight(200);
imageView.setTranslateX(1);
imageView.setTranslateY(1);
// و هكذا أصبح يمكن إختيار واحد منهم فقط في كل مرة radioMenuItem2 و radioMenuItem1 و ربطنا فيه الكائنين ToggleGroup هنا قمنا بإنشاء كائن من الكلاس
radioMenuItem1.setToggleGroup(toggleGroup);
radioMenuItem2.setToggleGroup(toggleGroup);
// هنا قمنا بوضع كل جميع الكائنات التي أنشأناها خصيصاً لوضعها كعناصر في القائمة بداخلها
contextMenu.getItems().add(menuItem1);
contextMenu.getItems().add(menuItem2);
contextMenu.getItems().add(new SeparatorMenuItem());
contextMenu.getItems().add(checkMenuItem);
contextMenu.getItems().add(new SeparatorMenuItem());
contextMenu.getItems().add(radioMenuItem1);
contextMenu.getItems().add(radioMenuItem2);
// في النافذة Root Node لأننا ننوي جعله الـ Group هنا قمنا بإنشاء كائن من الكلاس
Group root = new Group();
// root في الكائن datePicker هنا قمنا بإضافة الكائن
root.getChildren().add(pane);
// فيها و تحديد حجمها Node كأول root هنا قمنا بإنشاء محتوى النافذة مع تعيين الكائن
Scene scene = new Scene(root, 400, 250);
// هنا وضعنا عنوان للنافذة
stage.setTitle("JavaFX ContextMenu");
// أي وضعنا محتوى النافذة الذي قمنا بإنشائه للنافذة .stage في كائن الـ scene هنا وضعنا كائن الـ
stage.setScene(scene);
// هنا قمنا بإظهار النافذة
stage.show();
// الذي يمثل الصورة imageView هنا قمنا بتحديد ماذا سيحدث عند النقر بواسطة الفأرة على الكائن
imageView.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
// في المكان الذي تم النقر عليه (contextMenu) إذا تم النقر على الصورة من الفأرة بواسطة الزر الأيمن, سيتم إظهار القائمة
if (e.getButton() == MouseButton.SECONDARY) {
contextMenu.show(imageView, e.getScreenX(), e.getScreenY());
}
});
// menuItem1 هنا قمنا بتحديد ماذا سيحدث عند النقر على الخيار الذي يمثل الكائن
menuItem1.setOnAction((ActionEvent) -> {
// سيتم جعل الصورة تدور 90 درجة باتجاه اليمين
imageView.setRotate(imageView.getRotate() + 90);
});
// menuItem2 هنا قمنا بتحديد ماذا سيحدث عند النقر على الخيار الذي يمثل الكائن
menuItem2.setOnAction((ActionEvent) -> {
// سيتم جعل الصورة تدور 90 درجة باتجاه اليسار
imageView.setRotate(imageView.getRotate() - 90);
});
// checkMenuItem هنا قمنا بتحديد ماذا سيحدث عند النقر على الخيار الذي يمثل الكائن
checkMenuItem.setOnAction((ActionEvent) -> {
// لتحديد ما إذا كان يجب رسم حدود حول الصورة أم لا autoEnableOrDisableMenuOptions() و drawBorderOnDemande() سيتم إستدعاء الدالتين
// أم لا radioMenuItem2 و radioMenuItem1 و كيف يجب أن يتم تلوين هذه الحدود و لتحديد ما إذا كان يمكن النقر على الكائنين
drawBorderOnDemande();
autoEnableOrDisableMenuOptions();
});
// group تابع للمجموعة RadioButton هنا قمنا بتحديد ماذا سيحدث عند النقر على أي
toggleGroup.selectedToggleProperty().addListener((ObservableValue<? extends Toggle> ov, Toggle toggle, Toggle new_toggle) -> {
drawBorderOnDemande();
});
// غير مختار عند تشغيل التطبيق, أي لا يوجد عليه علامة صح checkMenuItem هنا قمنا بجعل الكائن
checkMenuItem.setSelected(false);
// مختاراً بشكل إفتراضي عند تشغيل التطبيق, أي يوجد عليه علامة صح radioMenuItem1 هنا قمنا بجعل الكائن
radioMenuItem1.setSelected(true);
// أم لا radioMenuItem2 و radioMenuItem1 لتحديد ما إذا كان يمكن النقر على الكائنين autoEnableOrDisableMenuOptions() هنا قمنا باستدعاء الدالة
autoEnableOrDisableMenuOptions();
}
// هنا قمنا بتشغيل التطبيق
public static void main(String[] args) {
launch(args);
}
}
import javafx.application.Application; import javafx.beans.value.ObservableValue; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.CheckMenuItem; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.control.RadioMenuItem; import javafx.scene.control.SeparatorMenuItem; import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; import javafx.stage.Stage; public class Main extends Application { // لأننا ننوي وضع الصورة بداخله pane هنا قمنا بإنشاء كائن من الكلاس Pane pane = new Pane(); // يمثل الصورة التي تظهر في النافذة Image هنا قمنا بإنشاء كائن من الكلاس Image image = new Image(getClass().getResourceAsStream("/images/javafx-icon.png")); // في النافذة image لعرض الصورة التي يشير لها الكائن ImageView هنا قمنا بإنشاء كائن من الكلاس ImageView imageView = new ImageView(image); // يمثل القائمة التي تظهر عن النقر بزر الفأرة الأيمن فوق الصورة ContextMenu هنا قمنا بإنشاء كائن من الكلاس ContextMenu contextMenu = new ContextMenu(); // هنا قمنا بإنشاء جميع الكائنات التي سنستخدمها كعناصر بداخل القائمة MenuItem menuItem1 = new MenuItem("Rotate Right"); MenuItem menuItem2 = new MenuItem("Rotate Left"); CheckMenuItem checkMenuItem = new CheckMenuItem("Show Border"); RadioMenuItem radioMenuItem1 = new RadioMenuItem("Black Border"); RadioMenuItem radioMenuItem2 = new RadioMenuItem("Blue Border"); // radioMenuItem2 و radioMenuItem1 لأننا ننوي وضع الكائنين toggleGroup هنا قمنا بإنشاء كائن من الكلاس // لاحقاً في مجموعة واحدة لجعل المستخدم قادر على إختيار إحداهما في كل مرة و ليس كلاهما ToggleGroup toggleGroup = new ToggleGroup(); // الذي يحتوي على الصورة pane هنا قمنا بتعريف دالة خاصة لرسم أو إخفاء حدود الكائن public void drawBorderOnDemande() { // checkMenuItem إذا كان يوجد على صح على الكائن if (checkMenuItem.isSelected()) { // pane سيتم إظهار حدود لونها أزرق للكائن radioMenuItem1 إذا كان يوجد علامة صح على الكائن if (radioMenuItem1.isSelected()) { pane.setStyle("-fx-border-style: solid; -fx-border-color: black;"); } // pane سيتم إظهار حدود لونها أسود للكائن radioMenuItem2 إذا كان يوجد علامة صح على الكائن else { pane.setStyle("-fx-border-style: solid; -fx-border-color: blue;"); } } // pane سيتم إزالة الحدود عن الكائن checkMenuItem إذا لم يكن هناك علامة صح على الكائن else { pane.setStyle("-fx-border:none;"); } } // قابلين للنقر أم لا radioMenuItem2 و radioMenuItem1 هنا قمنا بتعريف دالة خاصة لتحديد ما إذا كان يجب جعل الكائنين public void autoEnableOrDisableMenuOptions() { // قابلين للنقر radioMenuItem2 و radioMenuItem1 سيتم جعل الكائنين checkMenuItem إذا قام المستخدم بوضع علامة صح على الكائن if (checkMenuItem.isSelected()) { radioMenuItem1.setDisable(false); radioMenuItem2.setDisable(false); } // غير قابلين للنقر radioMenuItem2 و radioMenuItem1 سيتم جعل الكائنين checkMenuItem إذا قام المستخدم بإزالة علامة الصح عن الكائن else { radioMenuItem1.setDisable(true); radioMenuItem2.setDisable(true); } } @Override public void start(Stage stage) { // في النافذة pane هنا قمنا بتحديد حجم و مكان الكائن pane.setPrefSize(202, 202); pane.setTranslateX(99); pane.setTranslateY(24); // pane في الكائن imageView هنا قمنا بوضع الكائن pane.getChildren().add(imageView); // للأننا وضعناه بداخله pane بالنسبة للكائن imageView هنا قمنا بتحديد حجم و مكان الكائن imageView.setFitWidth(200); imageView.setFitHeight(200); imageView.setTranslateX(1); imageView.setTranslateY(1); // و هكذا أصبح يمكن إختيار واحد منهم فقط في كل مرة radioMenuItem2 و radioMenuItem1 و ربطنا فيه الكائنين ToggleGroup هنا قمنا بإنشاء كائن من الكلاس radioMenuItem1.setToggleGroup(toggleGroup); radioMenuItem2.setToggleGroup(toggleGroup); // هنا قمنا بوضع كل جميع الكائنات التي أنشأناها خصيصاً لوضعها كعناصر في القائمة بداخلها contextMenu.getItems().add(menuItem1); contextMenu.getItems().add(menuItem2); contextMenu.getItems().add(new SeparatorMenuItem()); contextMenu.getItems().add(checkMenuItem); contextMenu.getItems().add(new SeparatorMenuItem()); contextMenu.getItems().add(radioMenuItem1); contextMenu.getItems().add(radioMenuItem2); // في النافذة Root Node لأننا ننوي جعله الـ Group هنا قمنا بإنشاء كائن من الكلاس Group root = new Group(); // root في الكائن datePicker هنا قمنا بإضافة الكائن root.getChildren().add(pane); // فيها و تحديد حجمها Node كأول root هنا قمنا بإنشاء محتوى النافذة مع تعيين الكائن Scene scene = new Scene(root, 400, 250); // هنا وضعنا عنوان للنافذة stage.setTitle("JavaFX ContextMenu"); // أي وضعنا محتوى النافذة الذي قمنا بإنشائه للنافذة .stage في كائن الـ scene هنا وضعنا كائن الـ stage.setScene(scene); // هنا قمنا بإظهار النافذة stage.show(); // الذي يمثل الصورة imageView هنا قمنا بتحديد ماذا سيحدث عند النقر بواسطة الفأرة على الكائن imageView.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> { // في المكان الذي تم النقر عليه (contextMenu) إذا تم النقر على الصورة من الفأرة بواسطة الزر الأيمن, سيتم إظهار القائمة if (e.getButton() == MouseButton.SECONDARY) { contextMenu.show(imageView, e.getScreenX(), e.getScreenY()); } }); // menuItem1 هنا قمنا بتحديد ماذا سيحدث عند النقر على الخيار الذي يمثل الكائن menuItem1.setOnAction((ActionEvent) -> { // سيتم جعل الصورة تدور 90 درجة باتجاه اليمين imageView.setRotate(imageView.getRotate() + 90); }); // menuItem2 هنا قمنا بتحديد ماذا سيحدث عند النقر على الخيار الذي يمثل الكائن menuItem2.setOnAction((ActionEvent) -> { // سيتم جعل الصورة تدور 90 درجة باتجاه اليسار imageView.setRotate(imageView.getRotate() - 90); }); // checkMenuItem هنا قمنا بتحديد ماذا سيحدث عند النقر على الخيار الذي يمثل الكائن checkMenuItem.setOnAction((ActionEvent) -> { // لتحديد ما إذا كان يجب رسم حدود حول الصورة أم لا autoEnableOrDisableMenuOptions() و drawBorderOnDemande() سيتم إستدعاء الدالتين // أم لا radioMenuItem2 و radioMenuItem1 و كيف يجب أن يتم تلوين هذه الحدود و لتحديد ما إذا كان يمكن النقر على الكائنين drawBorderOnDemande(); autoEnableOrDisableMenuOptions(); }); // group تابع للمجموعة RadioButton هنا قمنا بتحديد ماذا سيحدث عند النقر على أي toggleGroup.selectedToggleProperty().addListener((ObservableValue<? extends Toggle> ov, Toggle toggle, Toggle new_toggle) -> { drawBorderOnDemande(); }); // غير مختار عند تشغيل التطبيق, أي لا يوجد عليه علامة صح checkMenuItem هنا قمنا بجعل الكائن checkMenuItem.setSelected(false); // مختاراً بشكل إفتراضي عند تشغيل التطبيق, أي يوجد عليه علامة صح radioMenuItem1 هنا قمنا بجعل الكائن radioMenuItem1.setSelected(true); // أم لا radioMenuItem2 و radioMenuItem1 لتحديد ما إذا كان يمكن النقر على الكائنين autoEnableOrDisableMenuOptions() هنا قمنا باستدعاء الدالة autoEnableOrDisableMenuOptions(); } // هنا قمنا بتشغيل التطبيق public static void main(String[] args) { launch(args); } }

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

طريقة إظهار قائمة ContextMenu عند النقر على زر الفأرة الأيمن في javafx