Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / GUI + thread. Корректно ли ? / 25 сообщений из 40, страница 1 из 2
01.04.2014, 09:46
    #38601555
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Почитал, что пишут про работу с GUI и возникло желание сделать что-то свое.
Смысл такой, что при нажатии на кнопку (к примеру "Вход" после ввода логина и пароля) появляется анимация и висит до тех пор, пока новое окно не выполнит свою инициализацию.
То, что получилось - ниже, просто хотелось бы знать, такой вариант вообще имеет право на жизнь ?

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
    protected static boolean showSecondStageFlag = false;
    protected static Stage stage;

    @FXML
    private void newStageButtonAction(ActionEvent event) {
        CreateSecondStage cs = new CreateSecondStage();
        cs.start();
    }

    public class CreateSecondStage
        extends Thread {

         @Override
        public void run() {

                Platform.runLater(new Runnable() {
                    @Override
                    public void run() { createStage(); }
                });

            int x = 1;

                while(!showSecondStageFlag) {
                    final int y = x;
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() { label.setText(String.valueOf(y)); }
                        });
                        try { TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException ex) { Logger.getLogger(ThreadsFXTestFXMLController.class.getName()).log(Level.SEVERE,null,ex); }
                    x++;
                }

        }

        void createStage() {
            try {
                stage = new Stage();
                Parent root = FXMLLoader.load(getClass().getResource("SecondStage.fxml"));
                Scene scene = new Scene(root);
                stage.setScene(scene);
            } catch (IOException ex) { Logger.getLogger(ThreadsFXTestFXMLController.class.getName()).log(Level.SEVERE,null,ex); }
        }

    }



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
    @Override
    public void initialize(URL url,ResourceBundle rb) {
        SecondStageThread st = new SecondStageThread();
        st.start();
    }

    public class SecondStageThread
                extends Thread {

        @Override
        public void run() {
                for(int x=0;x<10;x++) {
                    try { TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException ex) { Logger.getLogger(ThreadsFXTestFXMLController.class.getName()).log(Level.SEVERE,null,ex); }
                }

            ThreadsFXTestFXMLController.showSecondStageFlag = true;

                Platform.runLater(new Runnable() {
                    @Override
                    public void run() { ThreadsFXTestFXMLController.stage.show(); }
                });

        }

    }
...
Рейтинг: 0 / 0
01.04.2014, 10:17
    #38601595
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
korshunСмысл такой, что при нажатии на кнопку (к примеру "Вход" после ввода логина и пароля) появляется анимация и висит до тех пор, пока новое окно не выполнит свою инициализацию.
То, что получилось - ниже, просто хотелось бы знать, такой вариант вообще имеет право на жизнь ?

В JavaFX есть встроеные средства анимации. Поэтому этот лисапед не понятен совершенно.
...
Рейтинг: 0 / 0
01.04.2014, 10:21
    #38601601
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Можно чуточку подробнее ?
По каким словам гуглить ?
...
Рейтинг: 0 / 0
01.04.2014, 10:54
    #38601635
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
korshunМожно чуточку подробнее ?
По каким словам гуглить ?
JavaFX Animation? :)
http://docs.oracle.com/javafx/2/get_started/animation.htm
http://docs.oracle.com/javafx/2/animations/jfxpub-animations.htm
...
Рейтинг: 0 / 0
01.04.2014, 11:17
    #38601660
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Судя по коду, смысл такой:
- запускается вспомогательный поток, который дает команду в потоке javafx сделать какую-то длинную работу
- примерно раз в секунду этот поток дает команду в поток javafx отобразить какую-то информацию и дальше засыпает на секунду
Таким образом, вся работа по-прежнему происходит в потоке javafx, а вспомогательный поток в основном спит.

А надо бы так:
- длинная работа делается во вспомогательном потоке
- в потоке javafx отображаем анимацию средствами javafx, либо создаем обычный таймер (еще один поток), который посылает события для отображения счетчика.
В этом случае поток javafx будет только обновлять внешний вид, а приложение остается отзывчивым все время создания нового окна
...
Рейтинг: 0 / 0
01.04.2014, 12:04
    #38601721
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Blazkowicz, спасибо, этот раздел еще не изучал :)
Но я, видимо, немного некорректно задал вопрос в 1м посте, т.к. меня интересует не "анимация" etc (все эти плюшки можно вообще убрать), а именно "разгрузка" главного потока с целью избавиться от "зависания" приложения.

ivanraСудя по коду, смысл такой:
- запускается вспомогательный поток, который дает команду в потоке javafx сделать какую-то длинную работу
- примерно раз в секунду этот поток дает команду в поток javafx отобразить какую-то информацию и дальше засыпает на секунду
Таким образом, вся работа по-прежнему происходит в потоке javafx, а вспомогательный поток в основном спит.

А надо бы так:
- длинная работа делается во вспомогательном потоке
- в потоке javafx отображаем анимацию средствами javafx, либо создаем обычный таймер (еще один поток), который посылает события для отображения счетчика.
В этом случае поток javafx будет только обновлять внешний вид, а приложение остается отзывчивым все время создания нового окна

Возможно не понял, что вы имеете в виду, но так и происходит. Приложение не "виснет" и полностью доступно.
А "длинная" работа (цикл с задержками) и делается во вспомогательном потоке. Основной поток как раз не задействован, нет разве ?
Если перенести эти циклы в @FXML private void newStageButtonAction(ActionEvent event) { } приложение как раз и будет висеть все эти 10 сек.
...
Рейтинг: 0 / 0
01.04.2014, 12:17
    #38601740
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
korshunНо я, видимо, немного некорректно задал вопрос в 1м посте

Вы видимо написали код, который ниразу не понятно что делает. Что характеризует его соответствующим образом.

korshun, т.к. меня интересует не "анимация" etc (все эти плюшки можно вообще убрать), а именно "разгрузка" главного потока с целью избавиться от "зависания" приложения.

Для этого тоже есть готовые средства.
http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
http://docs.oracle.com/javafx/2/api/javafx/concurrent/Worker.html
...
Рейтинг: 0 / 0
01.04.2014, 12:35
    #38601763
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
korshunПриложение не "виснет" и полностью доступно.
т.е. пока юзверь авторизуется, он может снять средства со счёта?
Игрушки всё это.
...
Рейтинг: 0 / 0
01.04.2014, 12:43
    #38601773
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Спасибо за "готовые средства", вопрос закрыт :)
...
Рейтинг: 0 / 0
02.04.2014, 10:47
    #38602706
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Апну тему.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
        Task t = new Task() {
            @Override
            protected Object call() throws Exception {
                    for(int x=0;x<=10;x++) {
                            if(isCancelled()) {
                                updateMessage("isCancelled");
                                break;
                            }
                        TimeUnit.MILLISECONDS.sleep(100);
                    }
                return null;
            }
        };
        new Thread(t).start();
        button.setOnMouseClicked(new EventHandler<MouseEvent>(){
            @Override
            public void handle(MouseEvent event) {
                t.cancel();
            }
        });



В документации (по ссылке выше) пишут: " First, the Task author may check the isCancelled method, inherited from FutureTask, to see whether the Task has been cancelled. ".
Я так понял, что с помощью метода isCancelled можно проверить, была ли завершена задача.

Проблема в том, что if(isCancelled()) { } вообще не срабатывает, т.е. "isCancelled" в message я не получаю :(
Объясните плз, где туплю :(
...
Рейтинг: 0 / 0
02.04.2014, 10:57
    #38602726
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
korshun,

Не успеваешь нажать кнопку? :)
...
Рейтинг: 0 / 0
02.04.2014, 11:00
    #38602732
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Ну, RTFM же.
http://docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html Second, if the Task implementation makes use of any blocking calls (such as NIO InterruptibleChannels or Thread.sleep) and the task is cancelled while in such a blocking call, an InterruptedException is thrown.
cancel() вызывается во время sleep() и выкидывает InterruptedException. А логирование исключения в новом Thread нигде не прописано. Вот вам его и не видно.
...
Рейтинг: 0 / 0
02.04.2014, 11:03
    #38602736
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Успеваю, задача останавливается.
Перед TimeUnit.MILLISECONDS.sleep(100); специально добавлял System.out.println("x: "+x); что бы видеть все своими глазами.
Мало того getState() возвращает CANCELLED
Чесслово не понимаю, где туплю :( И туплю ли вообще.
...
Рейтинг: 0 / 0
02.04.2014, 11:03
    #38602738
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Это, кстати, такая мерзкая особенность FutureTask в Java. Они нигде не требуют обработки исключнений. Поэтому Threads и Executores молча сдыхают от исключений, которые нигде не логируются, если их вручную не ловить. Либо (опять же вручную) вешать UncaughtExceptionHandler.
...
Рейтинг: 0 / 0
02.04.2014, 11:10
    #38602744
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Если правильно понял, о чем Вы, то вот так:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
try {
     TimeUnit.MILLISECONDS.sleep(800);
}catch(InterruptedException ex) {
     if(isCancelled()) {
           updateMessage("isCancelled");
           break;
     }
}


message тоже пустое :(
...
Рейтинг: 0 / 0
02.04.2014, 11:15
    #38602752
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
korshun,

выложи компилябельный код, плз.
...
Рейтинг: 0 / 0
02.04.2014, 11:31
    #38602777
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Blazkowicz, все в порядке, с try-catch действительно все работает :)
Еще раз благодарю за уделенное время!
...
Рейтинг: 0 / 0
03.04.2014, 09:48
    #38603776
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Добрый день, подскажите плз по классу ScheduledService, есть несколько непонятных моментов :(

1. При циклическом выполнении конструкция labelCount.textProperty().bind(ss.messageProperty()); строку из updateMessage не получает, label остается пустым. При этом вывод в консоль System.out.println(x + " - " + msg); идет нормально.
Если останавливать выполнение при достижении какого-нибудь условия (пример ниже), то в label выводится строка из этого условия.
Если убрать cancel(); то та же история: вывод в консоль идет, в label - нет.
Код: java
1.
2.
3.
4.
5.
                        if(x%3==0){
                            updateMessage(String.valueOf(x));
                            System.out.println(x + " " + msg);
                            cancel();
                        }



2. При остановке командой cancel(); условие if(isCancelled()) { } не выполняется.

Сам класс.
Полный компиляберный код под спойлером.
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
    private class MyScheduledService
                extends ScheduledService<Void> {

        int period,x=1;
        String msg = "working";

        MyScheduledService(int _period) {
            this.period = _period;
        }

        @Override
        protected Task<Void> createTask() {
            return new Task(){
                @Override
                protected Void call() throws Exception {
                    setPeriod(Duration.millis(period));
                    setDelay(Duration.millis(period));
                        if(isCancelled()) {
                            updateMessage("Cancel");
                            System.out.println("Cancel");
                        }
                    updateMessage(String.valueOf(x));
                    System.out.println(x + " - " + msg);
                    x++;
                    return null;
                }
            };
        }




Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
package threadsfxtest1;

import javafx.application.Application;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {
    MyScheduledService ss;

    @Override
    public void start(Stage primaryStage) {

        ss = new MyScheduledService(500);

        Label labelCount = new Label();
        labelCount.textProperty().bind(ss.messageProperty());

        Button btnStart = new Button("Start Task");
        btnStart.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                ss.start();
            }
        });

        VBox vBox = new VBox();
        vBox.setPadding(new Insets(5, 5, 5, 5));
        vBox.setSpacing(5);
        vBox.getChildren().addAll(
                labelCount,
                btnStart);

        StackPane root = new StackPane();
        root.getChildren().add(vBox);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }

    private class MyScheduledService
                extends ScheduledService<Void> {

        int period,x=1;
        String msg = "working";

        MyScheduledService(int _period) {
            this.period = _period;
        }

        @Override
        protected Task<Void> createTask() {
            /*setOnCancelled(new EventHandler<WorkerStateEvent>() {
                @Override
                public void handle(WorkerStateEvent event) {
                    System.out.println("cancel");
                    x=1;
                    restart();
                }
            });*/
            return new Task(){
                @Override
                protected Void call() throws Exception {
                    setPeriod(Duration.millis(period));
                    setDelay(Duration.millis(period));
                        if(isCancelled()) {
                            updateMessage("Cancel");
                            System.out.println("Cancel");
                        }
                    updateMessage(String.valueOf(x));
                    //System.out.println(x + " - " + msg);
                        if(x%3==0){
                            msg += ".";
                            updateMessage(String.valueOf(x));
                            System.out.println(x + " " + msg);
                            cancel();
                        }
                    x++;
                    return null;
                }
            };
        }

    }

}


...
Рейтинг: 0 / 0
03.04.2014, 10:43
    #38603901
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
korshun
Код: java
1.
2.
3.
4.
5.
6.
        btnStart.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                ss.start();
            }
        });



Это че за анахронизм ещё? Java 8 же!

Что-то типа такого должно быть.
Код: java
1.
 btnStart.setOnAction((event)-> ss.start(););
...
Рейтинг: 0 / 0
03.04.2014, 10:49
    #38603917
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
updateMessage() меняет message у Task. A Label привязан к message Service. Внимание вопрос. Message у Task и Service как-то связаны?
...
Рейтинг: 0 / 0
03.04.2014, 10:53
    #38603926
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Код: java
1.
btnStart.setOnAction((ActionEvent t) -> { ss.start(); });


:)
Не привык еще к лямбдам, принципиальных отличий же нет, насколько понимаю.
...
Рейтинг: 0 / 0
03.04.2014, 11:24
    #38603964
korshun
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
BlazkowiczupdateMessage() меняет message у Task. A Label привязан к message Service. Внимание вопрос. Message у Task и Service как-то связаны?
Вы хотите сказать, что нужно в bind() у label'a делать ссылку на Task ?
Если да, то я не понимаю, как это можно сделать
...
Рейтинг: 0 / 0
03.04.2014, 11:26
    #38603969
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
korshunВы хотите сказать, что нужно в bind() у label'a делать ссылку на Task ?
Если да, то я не понимаю, как это можно сделать
Я не знаю. Я спрашиваю. Мне пока некогда искать ответ в документации. Я думал вы уже знали ответ, если так сделали. Если не знаете, посмотрите в исходниках Task и Service.
...
Рейтинг: 0 / 0
03.04.2014, 11:55
    #38604028
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
ОК. Посмотрел. В методе Service.start(), после создания task, message property task и service связываются. Странно что не работает.
Вот тут на аналогичную проблему жалуются.
http://stackoverflow.com/questions/20514410/long-running-task-in-javafx-service-results-in-flickering-update-messages-in-bou
Но как я понял сообщение пишеться, затем затирается. Надо бы listener повесить на labelCount.text и посмотреть все изменения и откуда они приходят.
...
Рейтинг: 0 / 0
03.04.2014, 12:00
    #38604039
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
GUI + thread. Корректно ли ?
Blazkowicz
Вот тут на аналогичную проблему жалуются.
http://stackoverflow.com/questions/20514410/long-running-task-in-javafx-service-results-in-flickering-update-messages-in-bou

А не, то другое. Там выходит во время запуска сервиса, text у label стирается.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / GUI + thread. Корректно ли ? / 25 сообщений из 40, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]