java شرح - استخدام JFrames متعددة:ممارسة جيدة أو سيئة؟




example in (9)

أنا طور تطبيقًا يعرض الصور ، ويلعب الأصوات من قاعدة بيانات. أحاول تحديد ما إذا كنت تريد استخدام JFrame منفصل لإضافة صور إلى قاعدة البيانات من واجهة المستخدم الرسومية.

أنا فقط أتساءل عما إذا كانت ممارسة جيدة لاستخدام نوافذ JFrame متعددة؟


Answers

أنا فقط أتساءل عما إذا كان من الجيد استخدام عدة JFrames؟

سيئة (سيئة ، سيئة) الممارسة.

  • مستخدم غير ودي: يرى المستخدم رموزًا متعددة في شريط المهام عند توقع رؤية واحدة فقط. بالإضافة إلى الآثار الجانبية لمشكلات الترميز ..
  • كابوس للرمز والصيانة:
    • يوفر الحوار المشروط فرصة سهلة لتركيز الانتباه على محتوى مربع الحوار هذا - اختيار / إصلاح / إلغاء هذا ، ثم المتابعة. إطارات متعددة لا.
    • سيظهر مربع حوار (أو شريط أدوات عائم) مع أحد الوالدين عند النقر على الوالد - سيكون عليك تنفيذ ذلك في الإطارات إذا كان هذا هو السلوك المرغوب.

هناك أي عدد من الطرق لعرض العديد من العناصر في واجهة مستخدم رسومية واحدة ، على سبيل المثال:

  • CardLayout ( demo. قصير demo. ). جيدة ل:
    1. عرض المعالج مثل الحوارات.
    2. عرض تحديدات قائمة أو شجرة إلخ للعناصر التي لها مكون مرتبط.
    3. التقليب بين أي مكون والمكون المرئي.
  • JInternalFrame/JDesktopPane المستخدم عادةً JInternalFrame/JDesktopPane MDI .
  • JTabbedPane لمجموعات من المكونات.
  • JSplitPane طريقة لعرض مكونين JSplitPane بين واحد أو آخر (الحجم) وفقًا لما يقوم به المستخدم.
  • JLayeredPane الكثير من المكونات جيدا ..layered.
  • يحتوي JToolBar عادةً على مجموعات من الإجراءات أو عناصر التحكم. يمكن سحبها حول واجهة المستخدم الرسومية أو إيقافها تمامًا وفقًا لاحتياجات المستخدم. كما ذكر أعلاه ، سوف يقلل / استعادة وفقا للوالدين القيام بذلك.
  • JList في JList (مثال بسيط أدناه).
  • كما العقد في JTree .
  • تخطيطات متداخلة .

ولكن إذا لم تنجح هذه الاستراتيجيات في حالة استخدام معينة ، فجرّب ما يلي. إنشاء JFrame رئيسي واحد ، ثم JDialog أو JOptionPane مثيلات لبقية العناصر الحرة العائمة ، وذلك باستخدام الإطار JDialog JOptionPane الحوار.

العديد من الصور

في هذه الحالة حيث تكون العناصر المتعددة عبارة عن صور ، سيكون من الأفضل استخدام أي مما يلي بدلاً من ذلك:

  1. JLabel واحد (يتم توسيطه في جزء التمرير) لعرض أي صورة يهتم بها المستخدم في تلك اللحظة. كما رأينا في ImageViewer .
  2. صف واحد JList . كما رأينا في هذا الجواب . لا يعمل جزء "الصف المفرد" من ذلك إلا إذا كانت جميعها ذات نفس الأبعاد. بالتناوب ، إذا كنت على استعداد لتغيير حجم الصور على الطاير ، وكلها بنفس نسبة العرض إلى الارتفاع (على سبيل المثال 4: 3 أو 16: 9).


إذا كانت الإطارات ستكون بنفس الحجم ، فلماذا لا تقوم بإنشاء الإطار وتمرير الإطار ثم كمرجع إليه بدلاً من ذلك.

عند تمرير الإطار ، يمكنك بعد ذلك تحديد كيفية ملؤه. سيكون مثل وجود طريقة لحساب متوسط ​​مجموعة من الأرقام. هل ستقوم بإنشاء الطريقة مرارا وتكرارا؟


ممارسة سيئة بالتأكيد. سبب واحد هو أنه ليس "سهل الاستعمال" جدا لحقيقة أن كل JFrame يظهر أيقونة شريط مهام جديدة. سيؤدي ضبط العديد من JFrame s إلى نزع شعرك.

شخصيا ، أود أن استخدام ONE JFrame لنوع من التطبيق الخاص بك. طرق عرض أشياء متعددة متروك لكم ، هناك الكثير. JInternalFrame Canvas ، JInternalFrame ، CardLayout ، حتى JPanel s ربما.

كائنات JFrame متعددة = ألم ، مشكلة ، ومشاكل.


إنها ليست ممارسة جيدة ولكن على الرغم من أنك ترغب في استخدامها يمكنك استخدام نمط المفرد كخياره. لقد استخدمت أنماط المفرد في معظم مشروعي الجيد.


لقد كان JFrame المتعدد شيئًا ما قمت بتنفيذه منذ أن بدأت في برمجة تطبيقات Swing. بالنسبة للجزء الأكبر ، فعلت ذلك في البداية لأنني لم أكن أعرف أفضل. ومع ذلك ، ومع نضوجي في خبرتي ومعرفتنا كمطور ، وبدأت في قراءة واستيعاب آراء العديد من مشغلي جافا الأكثر خبرة على الإنترنت ، قمت بمحاولة الابتعاد عن نهج JFrame المتعدد (سواء في المشاريع الحالية أو المستقبلية مشاريع) فقط ليتم تلبيتها ... الحصول على هذا ... المقاومة من موكلي! عندما بدأت في تنفيذ حوارات JInternalFrame نوافذ "الأطفال" و JInternalFrame لمكونات منفصلة ، بدأ زبائني بالشكوى! لقد فوجئت تماما ، حيث كنت أفعل ما اعتقدت أنه أفضل الممارسات! ولكن ، كما يقولون ، "الزوجة السعيدة هي حياة سعيدة." وينطبق نفس الشيء على عملائك. بالطبع ، أنا مقاول ، لذا فإن المستخدمين النهائيين لديّ يتمتعون بإمكانية الوصول المباشر إلي ، المطور ، الذي من الواضح أنه ليس سيناريو شائعًا.

لذا ، سأشرح فوائد نهج JFrame المتعدد ، بالإضافة إلى أسطورة - تمثال نصفي بعض السلبيات التي قدمها الآخرون.

  1. مرونة فائقة في التصميم - عن طريق السماح JFrame منفصل ، فإنك تمنح المستخدم النهائي القدرة على الانتشار والتحكم في ما هو على شاشته. مفهوم يشعر "مفتوحة" وغير ضيقة. تفقد هذا عندما تذهب نحو JFrame كبيرة وحفنة من JInternalFrame s.
  2. يعمل بشكل جيد مع التطبيقات المنوذجية للغاية - في حالتي ، تحتوي معظم تطبيقاتي على 3 - 5 وحدات "كبيرة" لا علاقة لها بأي منها على الإطلاق. على سبيل المثال ، قد تكون وحدة نمطية واحدة لوحة معلومات للمبيعات ، وقد تكون وحدة تحكم واحدة لوحة بيانات محاسبية. انهم لا يتحدثون مع بعضهم البعض أو أي شيء آخر. ومع ذلك ، قد يرغب المسؤول التنفيذي في فتح كلاهما وإطارات منفصلة على شريط المهام يجعل حياته أسهل.
  3. تسهّل على المستخدمين النهائيين الرجوع إلى المواد الخارجية - في إحدى المرات ، كان لدي هذا الموقف: كان تطبيقي يحتوي على "عارض بيانات" ، يمكنك من خلاله النقر على "إضافة جديد" وسيفتح شاشة إدخال البيانات. في البداية ، كان كلاهما JFrame s. ومع ذلك ، أردت أن تكون شاشة إدخال البيانات JDialog التي كان والدها عارض البيانات. لقد قمت بالتغيير ، وعلى الفور تلقيت مكالمة من مستخدم نهائي اعتمد كثيرًا على حقيقة أنه يمكنه تقليل المشاهد أو إغلاقه وإبقاء المحرر مفتوحًا أثناء الإشارة إلى جزء آخر من البرنامج (أو موقع ويب ، دون لا أتذكر. إنه ليس على جهاز عرض متعدد ، لذا فهو بحاجة إلى أن يكون حوار الدخول هو الأول والثاني ليكون ثانيًا ، مع إخفاء عارض البيانات تمامًا. كان هذا مستحيلاً مع JDialog وبالتأكيد كان من المستحيل استخدام JInternalFrame أيضًا. لقد غيرت ذلك بشكل JFrames إلى أن أكون JFrames منفصلة عن سلامة عقله ، لكنها علمتني درسًا مهمًا.
  4. خرافة: من الصعب التوليف - هذا ليس صحيحًا في تجربتي. لا أرى السبب في أنه سيكون من الأسهل إنشاء JInternalFrame من JFrame . في الواقع ، من خلال تجربتي ، توفر JInternalFrames مرونة أقل بكثير. لقد طورت طريقة منتظمة للتعامل مع فتح وإغلاق JFrame s في تطبيقاتي التي تعمل بشكل جيد. أتحكم في الإطار بالكامل تقريبًا من داخل إطار الإطار نفسه ؛ إنشاء الإطار الجديد ، SwingWorker s الذي يتحكم في استرجاع البيانات الموجودة على خيوط الخلفية ورمز واجهة المستخدم الرسومية على EDT ، واستعادة / إحالة أمام الإطار إذا حاول المستخدم فتحه مرتين ، وما إلى ذلك. كل ما تحتاجه لفتح JFrame s استدعاء طريقة static علنية open() والطريقة المفتوحة ، جنبًا إلى جنب مع حدث windowClosing() يعالج الباقي (هل الإطار مفتوح بالفعل؟ هل هو غير مفتوح ، ولكن التحميل؟ إلخ) لقد جعلت هذا النهج نموذجًا لذلك ليس من الصعب تنفيذها لكل إطار.
  5. أسطورة / غير مثبتة: الموارد الثقيلة - أود أن أرى بعض الحقائق وراء هذا البيان المضارب. على الرغم من أنه ، ربما ، يمكنك القول أن JFrame يحتاج إلى مساحة أكبر من JInternalFrame ، حتى إذا فتحت 100 JFrame ، فكم من الموارد JInternalFrame حقاً؟ إذا كان لديك مخاوف تسرب الذاكرة بسبب الموارد: استدعاء dispose() يحرر كافة الموارد المستخدمة من قبل الإطار لجمع البيانات المهملة (و مرة أخرى أقول ، يجب استدعاء JInternalFrame بالضبط نفس القلق).

لقد كتبت الكثير وأشعر أنني أستطيع كتابة المزيد. على أي حال ، آمل ألا أصوت ببساطة لأنه رأي غير شعبي. السؤال بوضوح واحد قيّم وأتمنى أن تكون قد قدمت إجابة قيمة ، حتى لو لم يكن هذا الرأي المشترك.

مثال رائع على إطارات متعددة / مستند واحد لكل إطار ( SDI ) مقابل إطار واحد / مستندات متعددة لكل إطار ( MDI ) هو Microsoft Excel. بعض فوائد MDI:

  • من الممكن أن يكون لديك عدد قليل من النوافذ في شكل غير مستطيل - لذلك لا تخفي سطح المكتب أو نافذة أخرى من عملية أخرى (مثل متصفح الويب)
  • من الممكن فتح نافذة من عملية أخرى عبر نافذة Excel واحدة أثناء الكتابة في إطار Excel الثاني - مع MDI ، سيؤدي محاولة الكتابة في إحدى النوافذ الداخلية إلى التركيز على إطار Excel بأكمله ، وبالتالي إخفاء نافذة من عملية أخرى
  • من الممكن أن يكون لديك مستندات مختلفة على شاشات مختلفة ، وهو أمر مفيد بشكل خاص عندما لا يكون للشاشات نفس الدقة

SDI (واجهة المستند الفردي ، أي ، كل نافذة يمكن أن يكون لها مستند واحد فقط):

MDI (واجهة مستندات متعددة ، أي أن كل نافذة يمكن أن تحتوي على مستندات متعددة):


جعل jInternalFrame في الإطار الرئيسي وجعلها غير مرئية. ثم يمكنك استخدامه لمزيد من الأحداث.

jInternalFrame.setSize(300,150);
jInternalFrame.setVisible(true);

لقد مضى وقت طويل منذ آخر مرة أتطرق فيها للتأرجح ولكن بشكل عام يعد ممارسة سيئة للقيام بذلك. بعض العيوب الرئيسية التي تتبادر إلى الذهن:

  • إنها أكثر تكلفة: سيتعين عليك تخصيص موارد أكثر لرسم JFrame بحيث يكون نوع آخر من حاوية النافذة ، مثل Dialog أو JInternalFrame.

  • ليست صديقة للمستخدم: ليس من السهل التنقل في مجموعة من JFrame ملتصقة ببعضها البعض ، سيبدو التطبيق الخاص بك هو مجموعة من التطبيقات غير متناسقة والتصميم ضعيف.

  • من السهل استخدام JInternalFrame هذا هو نوع من الترجيع ، الآن أصبح الأمر أسهل وأشخاص آخرين أكثر ذكاءً (أو مع المزيد من وقت الفراغ) مما كنا نفكر فيه بالفعل من خلال نمط سطح المكتب و JInternalFrame ، لذا أوصي باستخدامه.


أعتقد أن استخدام العديد من Jframe ليس فكرة جيدة.

بدلاً من ذلك يمكننا استخدام JPanel s أكثر من JPanel أو أكثر في نفس JFrame .

أيضا يمكننا التبديل بين هذا JPanel الصورة. لذلك يعطينا الحرية لعرض أكثر من شيء في JFrame .

لكل JPanel يمكننا تصميم أشياء مختلفة ويمكن عرض كل JPanel على JFrame واحدة واحدة في كل مرة.

للتبديل بين استخدام JPanel s JMenuBar مع JMenuItems لكل JPanel أو 'JButton for each JPanel`.

أكثر من JFrame ليس ممارسة جيدة ، ولكن لا بأس إذا أردنا أكثر من JFrame .

ولكن من الأفضل تغيير JFrame واحد لاحتياجاتنا المختلفة بدلاً من وجود العديد من JFrame .


هذه ليست شاذة:. .* يمكن أن تتطابق مع أي شيء.

تطلب استبدال كل التكرارات:

  • التواجد الأول يتطابق مع السلسلة بأكملها ، وبالتالي يبدأ محرك regex من نهاية الإدخال للمباراة التالية ؛
  • ولكن .* يتطابق أيضًا مع سلسلة فارغة! وبالتالي فإنه يطابق سلسلة فارغة في نهاية الإدخال ويستبدلها بعلامة.

استخدام .+ بدلاً من ذلك لن يحمل هذه المشكلة حيث لا يتطابق هذا التعبير العادي مع سلسلة فارغة (يتطلب حرفًا واحدًا على الأقل ليتم مطابقته).

أو استخدم .replaceFirst() لاستبدال التواجد الأول فقط:

"test".replaceFirst(".*", "a")
       ^^^^^^^^^^^^

الآن ، لماذا .* يتصرف كما يفعل ولا يتطابق أكثر من مرتين (من الناحية النظرية يمكن) هو شيء مثير للاهتمام للنظر فيها. انظر أدناه:

# Before first run
regex: |.*
input: |whatever
# After first run
regex: .*|
input: whatever|
#before second run
regex: |.*
input: whatever|
#after second run: since .* can match an empty string, it it satisfied...
regex: .*|
input: whatever|
# However, this means the regex engine matched an empty input.
# All regex engines, in this situation, will shift
# one character further in the input.
# So, before third run, the situation is:
regex: |.*
input: whatever<|ExhaustionOfInput>
# Nothing can ever match here: out

لاحظ أنه ، كما يلاحظAH في التعليقات ، لا تتصرف جميع محركات regex بهذه الطريقة. غنو sed على سبيل المثال سوف يعتبر أنه استنفد المدخلات بعد المباراة الأولى.





java swing user-interface jframe