JAVA - как изменить интерфейс SWT во время цикла в потоке - PullRequest
0 голосов
/ 01 июля 2018

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

Но я либо получаю

org.eclipse.swt.SWTException: Invalid thread access

когда я не использую дисплей

или пользовательский интерфейс действительно вялый, когда я делаю

display.asyncExec(new Runnable() {

Мой код выглядит так:

public void open() {
    Display display = Display.getDefault();
    shell = new Shell();
    shell.setSize(486, 322);
    shell.setText("SWT Application");

    Button btnStartLoop = new Button(shell, SWT.NONE);
    btnStartLoop.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseDown(MouseEvent e) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() // updates displayArea
                {
                    while (true) {
                        try {
                            text.setText("Text has been set");
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    });
    btnStartLoop.setBounds(35, 30, 75, 25);
    btnStartLoop.setText("Start Loop");

    text = new Text(shell, SWT.BORDER);
    text.setText("0");
    text.setBounds(116, 32, 177, 21);
    shell.open();
    shell.layout();
    while (!shell.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }
}

Есть ли способ, которым это можно преодолеть?

1 Ответ

0 голосов
/ 01 июля 2018

Вы никогда не должны спать в потоке пользовательского интерфейса. Вы должны использовать новый Thread для фоновой активности. Вы вызываете Display.asyncExec из потока, чтобы запустить код обновления пользовательского интерфейса в потоке пользовательского интерфейса.

btnStartLoop.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseDown(final MouseEvent e) {
        final Thread background = new Thread(new Runnable() {
            public void run()
            {
                while (true) {
                    try {
                        Display.getDefault().asyncExec(() -> text.setText("Text has been set"));
                        Thread.sleep(1000);
                    } catch (final InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        });
        background.start();
    }
});

Примечание: SwingUtilities для приложений Swing, не используйте его в приложениях SWT.

Вы также можете использовать timerExec метод Display для запуска кода после определенной задержки, что устраняет необходимость в фоновом потоке.

btnStartLoop.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseDown(final MouseEvent e) {
        final Runnable update = new Runnable() {
          public void run()
          {
            text.setText("Text has been set");

            Display.getDefault().timerExec(1000, this);
          }
        };
        Display.getDefault().timerExec(0, update);
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...