شرح الكلاس ContextMenu
الكلاس ContextMenu
يستخدم للحصول على قائمة منبثقة ( Popup Menu ) تظهر عند النقر على زر الفأرة الأيمن ( Right Click ).
ملاحظة: ليس بالضرورة أن تظهر القائمة فقط عند النقر على زر الفأرة الأيمن, لكنك على الأغلب لن تحتاج إظهارها إلا عند النقر على زر الفأرة الأيمن.
في الـ ContextMenu
يمكنك وضع أي نوع من العناصر ( Menu Items ) التالية بداخلها:
Menu
: أي قائمة داخلية, حيث يمكنك أن تضع قائمة بداخل قائمة.MenuItem
: عنصر عادي خاص للقوائم.RadioMenuItem
: يمثلRadioButton
خاص للقوائم.CheckMenuItem
: يمثلCheckBox
خاص للقوائم.SeparatorMenuItem
: يمثل خط فاصل (Separator
) خاص للقوائم.CustomMenuItem
: عبارة عن كلاس خاص يجب أن يرث منه أي كلاس تنشئه أنت بهدف وضعه كعنصر في القائمة.
مثال
الصورة التالية عبارة عن ContextMenu
تحتوي على إثنين ContextMenu
, إثنين RadioMenuItem
, إثنين CheckMenuItem
و إثنين SeparatorMenuItem
.
لعلك تتسائل ما الفرق بين الـ RadioMenuItem
و الـ CheckMenuItem
لأنهما يعطيانك نفس الشكل!
الفرق بينهما أنك تستطيع وضع الـ RadioMenuItem
ضمن مجموعة مثل الـ RadioButton
تماماً لجعل المستخدم قادر على إختيار عنصر واحد فقط كما سبق أن شرحنا في درس الـ radiobutton.
بناء الكلاس ContextMenu
@IDProperty(value="id") public class ContextMenu extends PopupControl
كونستركتورات الكلاس ContextMenu
الجدول التالي يحتوي على كونستركتورات الكلاس ContextMenu
.
الكونستركتور مع تعريفه | |
---|---|
public ContextMenu()
ينشئ كائن من الكلاس ContextMenu يمثل قائمة فارغة, أي لا تحتوي أي عنصر.لإضافة خيارات فيها نستدعي الدالة getItems() التي تسمح للوصول لعناصرها و من ثم نستدعي الدالة add() أو addAll() لإضافة عناصر فيها كالتالي.
|
|
public ContextMenu(MenuItem... items)
ينشئ كائن من الكلاس ContextMenu يمثل قائمة تحتوي على عناصر.مكان الباراميتر items يمكنك أن تمرر العدد الذي تريده من الكائنات التي ترث من الكلاس MenuItem مع وضع فاصلة بين كل إثنين. هذه العناصر ستظهر كعناصر في القائمة. |
دوال الكلاس ContextMenu
الجدول التالي يحتوي على دوال الكلاس ContextMenu
الأكثر إستخداماً.
الدالة مع تعريفها | |
---|---|
public void show(Node anchor, double screenX, double screenY)
تستخدم لإظهار القائمة التي يمثلها كائن الـ ContextMenu الذي قام باستدعائها في الموقع الذي تم تحديده.
|
|
public final void setStyle(String value)
تستخدم لتعديل تصميم كائن الـ ContextMenu الذي قام بإستدعائها.مكان الباراميتر value يمكنك تمرير إسم و قيمة أي خاصية تريد تعديلها في كائن الـ ContextMenu بأسلوب لغة CSS لإظهاره بالشكل الذي تريده. |
مثال طريقة إظهار قائمة ContextMenu عند النقر على زر الفأرة الأيمن في javafx
المثال التالي يعلمك طريقة إنشاء كائن من الكلاس ContextMenu
يمثل قائمة تظهر عند النقر على زر الفأرة الأيمن ( Right Click ).
هذه القائمة تسمح للمستخدم بقلب الصورة يميناً و يساراً, إظهار خط حولها, تحديد لون الخط, إخفاء الخط.
ملاحظة: عليك إنشاء مجلد و وضع الصورة فيه كما في الصورة التالية.
الصورة توضح أننا أضفنا مجلد إسمه images
و وضعنا فيه صورة واحدة إسمها javafx-icon.png
.
مثال طريقة إنشاء كائن من الكلاس ContextMenu
يمثل قائمة تظهر عند النقر على زر الفأرة الأيمن ( Right Click ).
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); } }
•ستظهر لك النافذة التالية عند التشغيل.