سؤال

لقد استخدمت النهج التالي لإنشاء مكونات وإرجاع القيم من التأرجح إلى / من خارج EDT. على سبيل المثال، يمكن أن تكون الطريقة التالية تمديدا JFrame, ، لخلق JPanel وأضفه إلى الوالد JFrame:

public JPanel threadSafeAddPanel() {

    final JPanel[] jPanel = new JPanel[1];

    try {
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                jPanel[0] = new JPanel();
                add(jPanel[0]);
            }
        });
    } catch (InterruptedException ex) {
    } catch (InvocationTargetException ex) {
    }

    return jPanel[0];
}

يتم استخدام صفيف الطول المحلي 1-الطول لنقل "النتيجة" من داخل Runnable, ، والتي يتم الاحتجاج بها في EDT. حسنا، يبدو "بعض الشيء"، واكيكن أسئلتي:

  1. هل لهذا معنى؟ هل أي شخص آخر يفعل شيئا مثل هذا؟
  2. هو مجموعة طول 1 طريقة جيدة لنقل النتيجة؟
  3. هل هناك طريقة أسهل لعمل هذا الشيء؟
هل كانت مفيدة؟

المحلول

  • استثناءات البلع دون تسجيلها سيئة!! - سوف تكره نفسك عندما تأتي بشيء من هذا القبيل بعد عملية البحث عن علة 2 ساعة
  • لا، المجموعة ليست طريقة جيدة؛ لسبب واحد، لا يقدم أي طريقة سهلة لرمز الاتصال لانتظار موضوع EDT لتنفيذ Runnable قبل جلب النتيجة
  • هناك فئة مصممة صراحة لهذا النوع من الأشياء: SwingWorker

نصائح أخرى

على الرغم من أن هذه الطريقة قد تكون منطقية في بعض المواقف، إلا أنه سيكون من الفائدة معظم الوقت.

السبب هو أن إنشاء معظم (لم يكن كل شيء) من مكوناتك سيحدث دائما من EDT، نتيجة لعملية المستخدم (عنصر القائمة أو الزر النقر فوق) الذي يتم تنفيذه دائما من EDT.

في الحالات التي يكون لديك عمل كبير لأداءها قبل إنشاء لوحةك ولا ترغب في حظر EDT، فيجب عليك، كما اقترح من قبل شخص آخر، استخدم SwingWorker أو إطار التأرجح الذي يوفر دعما للمهام الطويلة (بناء على ذلك بشكل عام Swingworker داخليا على أي حال، ولكن ليس بالضرورة).

فيما يتعلق بسؤالك 2، لسوء الحظ، ليس لديك العديد من الطرق للقيام بذلك:

  • استخدم مجموعة من العناصر التي قمت بها، وهذا هو الأسهل ولكن أيضا حلا الحل
  • قم بإنشاء فئة Iondholder (انظر أدناه) التي تتطلب تقريبا نفسها، ويتطلب المزيد من العمل وغير نظافة، في رأيي
  • أخيرا، استخدم مرافق Java.util.concurrent (المستقبل وقابل للاستدعاء)؛ سيكون ذلك أنظف أفكر، لكنه يتطلب أيضا أكثر جهد

هنا، مبسطة، فئة Itemholder:

public class ItemHolder<T> {
    public void set(T item) {...}
    public T get() {...}
    private T item;
}
  1. أ) من المنطقي. ب) ليس هذا أعرف.
  2. جيدة مثل أي.
  3. إنشاء JPanel خارج invokeAndWait يتصل

// هذا الخط المضافة إلى استرضاء

public JPanel threadSafeAddPanel() {
    final JPanel jPanel = new JPanel();
    try {
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                add(jPanel);
            }
        });
    } catch (InterruptedException ex) {
    } catch (InvocationTargetException ex) {
    }
    return jPanel;
}

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

public JPanel threadSafeAddPanel() throws InterruptedException, 
        InvocationTargetException {
    if (EventQueue.isDispatchThread()) {
        JPanel panel = new JPanel();
        add(panel);

        return panel; 
    } else {
        final JPanel[] jPanel = new JPanel[1];
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                jPanel[0] = new JPanel();
                add(jPanel[0]);
            }
        });

        return jPanel[0];
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top