1

我尝试了很多,现在我需要你的帮助。我想做的是:当黑莓应用程序启动时,会弹出一个是/否对话框。如果用户选择“是”,请执行某些操作,然后继续启动。如果用户选择“否”退出应用程序。

我写了一个 SSCCE,如果你选择“是”,它应该会振动,之后你应该会听到声音。当然我知道,代码在调用 Alert.vibrate() 之后继续,它不会等待振动完成。无论如何,这只是一个例子。对 vibrate() 的调用应该首先出现,并且 dialogClosed() 应该在播放声音之前完全处理。

SSCCE 是我目前所获得的。我尝试了很多其他的东西。我敢肯定这不会那么难。我只是不明白。

这里是:

package TestDialog;

import net.rim.device.api.system.Alert;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.DialogClosedListener;

public class TestDialog extends UiApplication
{

public static short[] SOUND_ALERT = { 523, 200, //C for 200ms
                0, 200, //Pause 200ms
                554, 200, //C# 200ms
                0, 200, //Pause 200ms
                587, 200, //D 200ms
                0, 200, //Pause 200ms
                622, 200         //D# 200ms         
                                  };

/**
 * @param args
 */
public static void main(final String[] args)
{

    final TestDialog test = new TestDialog();
    test.enterEventDispatcher();

}

public TestDialog()
{

    //the dialog
    final Dialog d = new Dialog(Dialog.D_YES_NO, "vibrate?", Dialog.OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), Dialog.FIELD_TOP);
    d.setDialogClosedListener(new DialogClosedListener()
    {

        public void dialogClosed(final Dialog dialog, final int choice)
        {
            if (d.getSelectedValue() == Dialog.YES)
            {
                Alert.startVibrate(2000);
                //do something which takes some time
            }
            else
            {
                System.exit(0);
            }

        }
    });

    //show the dialog
    showDialog(d);

    //now wait for the dialog to call notify
    try
    {
        synchronized (this)
        {
            this.wait();
        }
    }
    catch (final Exception e)
    {
        System.out.println(e.getMessage());
    }

    //finally AFTER the dialog has been closed and everything in dialogClosed() has been done, play a sound
    Alert.startAudio(SOUND_ALERT, 100);

}

private void showDialog(final Dialog d)
{

    UiApplication.getUiApplication().invokeLater(new Runnable()
    {
        public void run()
        {
            d.doModal();
            this.notify();
        }
    });

}
}

好的,其他一些 SSCCE。这会启动并显示一个对话框,但随后会引发 IllegalMonitorExcpetion:

package TestDialog;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;

public class TestDialog extends UiApplication
{

public static short[] SOUND_ALERT = { 523, 200, //C for 200ms
                0, 200, //Pause 200ms
                554, 200, //C# 200ms
                0, 200, //Pause 200ms
                587, 200, //D 200ms
                0, 200, //Pause 200ms
                622, 200         //D# 200ms         
                                  };

/**
 * @param args
 */
public static void main(final String[] args)
{

    final TestDialog test = new TestDialog();
    test.enterEventDispatcher();

}

public TestDialog()
{

    UiApplication.getUiApplication().invokeLater(new Runnable()
    {
        public void run()
        {
            //the dialog
            final Dialog d = new Dialog(Dialog.D_YES_NO, "vibrate?", Dialog.OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), Dialog.FIELD_TOP);

            if (d.doModal() == Dialog.YES)
            {
                System.out.println("selection made yes");
                this.notify();
            }
            else
            {
                System.out.println("selection made no");
                System.exit(0);
            }

        }
    });


        try
        {
            this.wait();
        }
        catch (final Exception e)
        {
            e.printStackTrace();
        }


    //finally AFTER the dialog has been closed and everything in dialogClosed() has been done, play a sound
    System.out.println("done");
}

}

因此,我在 wait() 调用周围放置了一个同步块,因为我读过,在调用 wait() 时对象必须是同步的。但现在该应用程序什么也没显示。它运行主要方法,但在某处停止。在模拟器中发生了非常奇怪的事情:当模拟器仍在启动中并且显示器上写着“调试器附加”时,应用程序的主方法被调用。好吧,这里是带同步块的 SSCCE。还是不行。

package TestDialog;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;

public class TestDialog extends UiApplication
{

public static short[] SOUND_ALERT = { 523, 200, //C for 200ms
                0, 200, //Pause 200ms
                554, 200, //C# 200ms
                0, 200, //Pause 200ms
                587, 200, //D 200ms
                0, 200, //Pause 200ms
                622, 200         //D# 200ms         
                                  };

/**
 * @param args
 */
public static void main(final String[] args)
{

    final TestDialog test = new TestDialog();
    test.enterEventDispatcher();

}

public TestDialog()
{

    UiApplication.getUiApplication().invokeLater(new Runnable()
    {
        public void run()
        {
            //the dialog
            final Dialog d = new Dialog(Dialog.D_YES_NO, "vibrate?", Dialog.OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), Dialog.FIELD_TOP);

            if (d.doModal() == Dialog.YES)
            {
                System.out.println("selection made yes");
                this.notify();
            }
            else
            {
                System.out.println("selection made no");
                System.exit(0);
            }

        }
    });

    synchronized (this)
    {
        try
        {
            this.wait();
        }
        catch (final Exception e)
        {
            e.printStackTrace();
        }
    }

    //finally AFTER the dialog has been closed and everything in dialogClosed() has been done, play a sound
    System.out.println("done");
}

}

最后我尝试利用忙碌的等待。仍然没有成功。对话框只是没有弹出。即使在主线程的 while 循环中使用 Thread.sleep(1000),UI 线程似乎也不起作用。这是忙于等待的 SSCCE:

    package TestDialog;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;

public class TestDialog extends UiApplication
{
    /**
     * @param args
     */
    public static void main(final String[] args)
    {

        final TestDialog test = new TestDialog();
        test.enterEventDispatcher();

    }

    private volatile boolean _blocked = true;

    public TestDialog()
    {

        UiApplication.getUiApplication().invokeLater(new Runnable()
        {
            public void run()
            {
                //the dialog
                final Dialog d = new Dialog(Dialog.D_YES_NO, "vibrate?", Dialog.OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), Dialog.FIELD_TOP);

                if (d.doModal() == Dialog.YES)
                {
                    System.out.println("selection made yes");
                    _blocked = false;
                }
                else
                {
                    System.out.println("selection made no");
                    System.exit(0);
                }

            }
        });

        while (_blocked)
        {
            try
            {
                Thread.sleep(1000);
            }
            catch (final Exception e)
            {
                //safety catch
            }
        }
        finish();

    }

    private void finish()
    {
        System.out.println("done");
    }

}

谢谢你的帮助。

哈弗布鲁斯

4

2 回答 2

1

使用 invokeAndWait 代替 invokeLater。

private void showDialog(final Dialog d)
{

    UiApplication.getUiApplication().invokeAndWait(new Runnable()
    {
        public void run()
        {
            d.doModal();
            this.notify();
        }
    });

}
于 2012-05-16T14:29:24.947 回答
1

嗨,我终于在这里的黑莓论坛上得到了答案:http: //supportforums.blackberry.com/t5/Java-Development/Startup-YES-NO-Dialog-should-stop-the-launchign-process-of-the/ mp/1725085

对我有用的最终解决方案(看起来比我上面所做的一切都好)如下:

    package TestDialog;

import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.container.MainScreen;

public class TestDialog extends UiApplication implements Runnable
{
    /**
     * @param args
     */
    public static void main(final String[] args)
    {

        final TestDialog test = new TestDialog();
        test.invokeLater(test);

        test.enterEventDispatcher();

    }

    public TestDialog()
    {

    }

    public void run()
    {

        final int answer = Dialog.ask(Dialog.D_YES_NO, "continue?");
        //        pushGlobalScreen(new Dialog(Dialog.D_YES_NO, "continue?", 0, null, Dialog.GLOBAL_STATUS), 1, TestDialog.GLOBAL_QUEUE | TestDialog.GLOBAL_MODAL);

        if (answer == Dialog.YES)
        {
            System.out.println("user clicked yes");
        }
        else
        {
            System.exit(0);
        }

        pushScreen(new MyScreen("App loaded"));
    }

    class MyScreen extends MainScreen
    {

        public MyScreen(final String msg)
        {

            final LabelField title = new LabelField("First Screen", LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);
            setTitle(title);
            this.add(new RichTextField(msg));

        }

    }

}

感谢双方的大力支持。

于 2012-05-21T07:39:08.400 回答