«pushModalScreen, вызываемый потоком, не являющимся событием», генерируется в потоке события - PullRequest
3 голосов
/ 26 марта 2010

Я пытаюсь заставить мое приложение Blackberry отображать пользовательское модальное диалоговое окно, и заставляет начальную ветку ждать, пока пользователь не закроет диалоговое окно.

final Screen dialog = new FullScreen();

...// Fields are added to dialog

Application.getApplication().invokeAndWait(new Runnable()
{

    public void run()
    {
        Application.getUiApplication().pushModalScreen(dialog);             
    }
});

Это вызывает исключение, в котором говорится, что pushModalScreen вызывается потоком, не являющимся событием, несмотря на то, что я использую invokeAndWait для вызова pushModalScreen из потока события.

Есть идеи о том, в чем реальная проблема?

Вот код для дублирования этой проблемы:

package com.test;

import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;

public class Application extends UiApplication {
    public static void main(String[] args)
    {
        new Application();
    }

    private Application()
    {
        new Thread()
        {
            public void run()
            {
                Application.this.enterEventDispatcher();
            }
        }.start();

        final Screen dialog = new FullScreen();
        final ButtonField closeButton = new ButtonField("Close Dialog");
        closeButton.setChangeListener(new FieldChangeListener()
        {

            public void fieldChanged(Field field, int context)
            {
                Application.getUiApplication().popScreen(dialog);
            }
        });
        dialog.add(closeButton); 
        Application.getApplication().invokeAndWait(new Runnable()
        {

            public void run()
            {
                try
                {
                    Application.getUiApplication().pushModalScreen(dialog);
                }
                catch (Exception e)
                {
                    // To see the Exception in the debugger
                    throw new RuntimeException(e.getMessage());
                }
            }
        });

        System.exit(0);
    }
}

Я использую Компонент Пакет версии 4.5.0.

Ответы [ 3 ]

2 голосов
/ 08 мая 2010

Кажется, что там есть куча кода, который не нужен.

public class Application extends UiApplication {
    public static void main(String[] args)
    {
        new Application().enterEventDispatcher();
    }

private Application()
{
    final Screen dialog = new FullScreen();
    final ButtonField closeButton = new ButtonField("Close Dialog");
    closeButton.setChangeListener(new FieldChangeListener()
    {
        public void fieldChanged(Field field, int context)
        {
            Application.getUiApplication().popScreen(dialog);
        }
    });
    dialog.add(closeButton); 

    // this call will block the current event thread
    pushModalScreen(dialog);

    System.exit(0);
   }
}
2 голосов
/ 26 марта 2010

Опираясь на замечание Макса Гонтара о том, что исключение не выдается при использовании invokeLater вместо invokeAndWait, полное решение состоит в том, чтобы правильно реализовать invokeAndWait из invokeLater и методов синхронизации Java:

public static void invokeAndWait(final Application application,
    final Runnable runnable)
{
    final Object syncEvent = new Object();
    synchronized(syncEvent)
    {
        application.invokeLater(new Runnable()
        {

            public void run()
            {   
                runnable.run();
                synchronized(syncEvent)
                {
                    syncEvent.notify();
                }
            }
        });
        try
        {
            syncEvent.wait();
        }
        catch (InterruptedException e)
        {
            // This should not happen
            throw new RuntimeException(e.getMessage());
        }
    }
}

К сожалению, метод invokeAndWait не может быть переопределен, поэтому следует осторожно вызывать эту статическую версию.

0 голосов
/ 06 сентября 2013

Используйте это:

UiApplication.getUiApplication().invokeAndWait(new Runnable() {
    public void run() {
        pushScreen(new MyScreen());
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...