Получение JOptionPane.showConfirmDialog() для работы в Mac OSX

У меня возникли проблемы с тем, чтобы окна сообщений и в некоторой степени диалоговые окна отображались/работали должным образом в Mac (v10.9.5).

Я только что обновил JRE и JDK до последней версии (8u31). «Java-версия» из окна терминала показывает, что я действительно использую 8u31. (Ранее я использовал 8u20, который демонстрировал такое же поведение.)

Приведенный ниже код отлично работает в Windows и нескольких различных версиях Linux, которые я тестировал, проблем нет. У меня просто проблемы на Mac. Я упростил свой код, основанный на SWT, но в этом примере используется Swing, до следующего:

package myTest;

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class EntryCode
{
    public static EntryCode oEntryCode;

    public EntryCode()
    {
        // TODO Auto-generated constructor stub
    }

    public static void main(String[] args)
    {
        oEntryCode = new EntryCode();

        oEntryCode.open();
    }

    public void open()
    {
        JPanel panel = new JPanel();
        panel.setMinimumSize(new Dimension(200,200));

        JFrame frame = new JFrame("JOptionPane showMessageDialog component example");
        System.out.println("open(): entry - With frame");
        JOptionPane.showConfirmDialog(frame, "Wow, works on the Mac!", "Inside open()", JOptionPane.YES_NO_OPTION);
        System.out.println("Point 1");

        System.exit(0);
    }
}

Я вижу первую строку системного вывода, и код зависает на запросе окна сообщения. В реальном коде я просто использую null в качестве первого аргумента. Первоначальная версия этого тестового кода тоже использовала null, просто я экспериментировал с указанием компонента. Я думал, что это может быть проблемой. Нет.

При отображении диалоговых окон SWT существует тенденция, что нажатие на кнопку приводит к зависанию интерфейса. Зависание происходит где-то между нажатием кнопки и срабатыванием обработчика событий. Обработчик событий никогда не срабатывает.

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

Я сделал поиск в Google для отображения java-приложений на Mac, но ничего не вышло.

Я думаю, что обновление JRE/JDK до последней версии решит любые проблемы, связанные с ОС.

Я компилирую код в банку и использую следующее для запуска из окна терминала. Я нажимаю Ctrl+C, чтобы закрыть зависшее приложение.

java -XstartOnFirstThread -jar myTest.jar

Мысли?

ОБНОВЛЕНИЕ:

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

Настоящая проблема заключается в том, как инициировать правильное SWT-приложение Mac OSX Cocoa, поддерживающее ограничения, которое использует диалоговые окна и окна сообщений. (Насколько мне известно, единственный способ отобразить окна сообщений — использовать JOptionPane.show*, который является фишкой Swing, тем самым как бы смешивая Swing и SWT.

Интересно отметить, что проблема всегда связана с кнопками, будь то диалоговое окно (чистая реализация SWT) или окна сообщений. В первом случае проблема заключается в зависании при вызове обработчика событий, а во втором — отображении окна сообщения (нулевой первый аргумент, поскольку в приложении SWT не существует фрейма Swing).


person Sarah Weinberger    schedule 17.02.2015    source источник


Ответы (2)


Не совсем уверен, что это может быть ошибка, так как я не могу проверить это на своем Mac в данный момент. Но вы никогда не устанавливаете видимость JFrame в true. Когда вы передаете кадр в качестве параметра JOptionPane, панель пытается отобразить панель в кадре.

Так что попробуйте :

 public void open()
{
    JFrame frame = new JFrame("JOptionPane showMessageDialog component example");
    System.out.println("open(): entry - With frame");
    frame.setSize(300,300);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

    JOptionPane.showConfirmDialog(frame, "Wow, works on the Mac!", "Inside open()", JOptionPane.YES_NO_OPTION);
    System.out.println("Point 1");

    System.exit(0);
}

Кроме того, почему вы создаете JPanel, панель никогда не используется, насколько я вижу?

Поскольку рамка не видна, это может вызвать проблемы. Просто предположение... Это также объясняет, почему ваше приложение "зависает". Это потому, что он ждет, пока вы сделаете выбор в своем JOptionPane, но вы не можете сделать этот выбор, потому что не видите JOptionPane.

Я знаю, что вы писали, что также пытались передать null в качестве аргумента, но я мог подумать, что это также может вызвать проблемы, когда не отображается другой JFrame. Как я уже сказал, просто предположение. Просто попробуйте и вернитесь сюда, чтобы предоставить дополнительную информацию.

ИЗМЕНИТЬ Только что протестировано и похоже, что ваш код в порядке. Ваша ошибка должна заключаться в настройке вашего Mac или Java.

EDIT 2 Думаю, я нашел ваш ответ. Похоже, проблема в startOnFirstThread. Я только что проверил через javac и java в командной строке. Посмотри на это:

Swing перестает работать, потому что -XstartOnFirstThread подразумевает, что
кто-то другой (скорее всего, SWT) придет и начнет
прокачивать цикл обработки событий в потоке 0 с помощью CFRunLoop или чего-то подобного.

Это может объяснить, почему ваш JOptionPane изо всех сил пытается появиться. (Взято из: здесь

Также немного старше, но описывает вашу проблему:

Проблемы AWT обычно сводятся к тому, в каком потоке была запущена jvm. При использовании средства запуска java (как это делает pde) на Mac java по умолчанию запускается во втором потоке (это то, что хочет AWT), если вы не укажете -XstartOnFirstThread (это то, что хочет SWT). https://bugs.eclipse.org/bugs/show_bug.cgi?id=212617

person dehlen    schedule 18.02.2015
comment
Я смогу протестировать на своем Mac примерно через 30 минут. Я вернусь к вам тогда. О, а также, пожалуйста, убедитесь, что у вас не установлены точки останова. - person dehlen; 18.02.2015
comment
Спасибо, но я не запускаю код внутри Eclipse на Mac. Я создаю код в Windows и использую Ant для создания файла jar. Затем я подключаю TeamViewer к Mac и копирую файл jar в папку. Затем я использую java -XstartOnFirstThread -jar ‹мой файл jar›, чтобы запустить приложение из окна терминала. Нет Eclipse, поэтому невозможно установить точку останова. - person Sarah Weinberger; 18.02.2015
comment
Я только что скомпилировал и запустил вашу программу на своем Mac, и все работает нормально. Похоже, что-то не так с вашей настройкой Mac/Java. - person dehlen; 18.02.2015
comment
Я попробовал код на другом Mac безрезультатно; такая же проблема. Я попробовал несколько вариантов (с/без запуска и т. д.) и получил то же самое поведение, что и на первом компьютере Mac. Я понимаю, что код работал на компьютере Делена, хотя я не тестировал его конкретный двоичный файл, а он не тестировал мой. - person Sarah Weinberger; 19.02.2015
comment
SwingUtilities.invokeLater нельзя использовать с приложениями SWT и циклом сообщений на Mac из-за ограничений Cocoa. Создать фрейм и использовать его тоже не вариант, потому что у меня уже есть видимый фрейм. Это называется моим приложением, основанным на SWT. Это оставляет меня в самом начале. - person Sarah Weinberger; 19.02.2015
comment
Используйте компоненты SWT или компоненты Swing, но не оба вместе. Это так просто - person dehlen; 19.02.2015
comment
Хорошо, но зависания Mac/OSX связаны с кнопками: 1) в окне сообщения 2) нажатия кнопок в диалогах SWT. В диалоговом окне SWT нет Swing. Насколько мне известно, нужно использовать JOptionPane для окон сообщений в SWT, вещь Swing. - person Sarah Weinberger; 19.02.2015
comment
В SWT вы используете MessageDialog компонент SWT. - person dehlen; 19.02.2015
comment
Проблема заключалась в смешивании SWT и Swing. Как только я удалил все следы Swing и нашел реализацию SWT для окон сообщений, Mac начал нормально работать. Код теста Swing работал отлично, если следовать протоколу Swing (без -XstartOnFirstThread, запуск для запуска в отдельном потоке и видимый кадр). - person Sarah Weinberger; 20.02.2015

Проблема может заключаться в том, что вы не запускаете графический интерфейс в EDT. Попробуй это:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            oEntryCode = new EntryCode();
            oEntryCode.open();
        }
    });
}

Дополнительная информация: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html

Другая проблема заключается в использовании -XstartOnFirstThread с Swing. Swing делает то же самое, что и -XstartOnFirstThread, но по-своему. Вы не должны использовать -XstartOnFirstThread с Swing, так же как не рекомендуется смешивать SWT и Swing.

Если вы добавите SwingUtilities.invokeLater() и удалите -XstartOnFirstThread, ваш пример должен работать нормально.

person martinez314    schedule 17.02.2015
comment
Голосование за кого-то было преждевременным. Тестирование, к сожалению, не дало результатов. - person Sarah Weinberger; 18.02.2015