jFrames зависают от этого кода? (код прилагается): Netbeans 8.2

Я сталкиваюсь с проблемой в моем java-приложении: когда новые jFrames открываются, щелкнув jButton, немного замораживается и после его открытия (время замораживания 1-2 минуты / 3 минуты). Я пока не мог найти, что происходит не так. но у меня есть некоторые сомнения в приведенном ниже коде. этот код для получения системного времени и даты и отображения всех jFrames. так что этот код есть во всех jFrames. теперь у меня вопрос, происходит ли это замораживание из-за этого кода ..? или может какие то другие причины ..? Если в этом коде есть ошибки, пожалуйста, скажите мне, что также ... Я использую NEtbeans 8.2. заранее спасибо.

код:

public AdminHome() {
    initComponents();

    new Thread(new Runnable() {
        @Override
        public void run() {

            while (true) {
            Date d=new Date();

            SimpleDateFormat sd=new SimpleDateFormat("yyyy - MM - dd");
            String s =  sd.format(d);
            String s1 = d.toString();
            String ar[]=s1.split(" ");

            jLbl_Date.setText(s);  
            jLbl_Time.setText(ar[3]);
            }  
        }
    }).start();

}

person siper camm    schedule 22.02.2017    source источник


Ответы (3)


Эти два звонка:

jLbl_Date.setText(s);  
jLbl_Time.setText(ar[3]);

должны происходить в EDT (поток отправки событий), поскольку компонентами графического интерфейса нужно управлять из EDT. Вы можете поместить их в EDT, обернув их с помощью SwingUtilities:

SwingUtilities.invokeLater(() -> {
    Date d=new Date();

    SimpleDateFormat sd=new SimpleDateFormat("yyyy - MM - dd");
    String s =  sd.format(d);
    String s1 = d.toString();
    String ar[]=s1.split(" ");

    jLbl_Date.setText(s);  
    jLbl_Time.setText(ar[3]);
});

Однако проблема все равно осталась бы. Поскольку ваш поток не спит между обновлением меток, вы можете заполнить EDT запросами на обновление, что приведет к зависанию вашего графического интерфейса. Вы можете исправить это, добавив Thread.sleep(1000); после обновления меток.

Более элегантный подход - использовать таймер поворота вместо вашего потока:

Timer timer = new Timer(1000, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            Date d=new Date();

            SimpleDateFormat sd=new SimpleDateFormat("yyyy - MM - dd");
            String s =  sd.format(d);
            String s1 = d.toString();
            String ar[]=s1.split(" ");

            jLbl_Date.setText(s);  
            jLbl_Time.setText(ar[3]);
        }
});            
timer.setInitialDelay(0);
timer.start();

Таймер качания заботится о том, чтобы код с actionPerformed-методом выполнялся на EDT. У него есть дополнительное преимущество, заключающееся в том, что он объединяет события, если это необходимо - еще один механизм, предотвращающий переполнение EDT событиями.

person Calculator    schedule 22.02.2017
comment
Ты подтолкнул меня на это! +1 - person Colin; 22.02.2017

Возможно, вы создали отдельный поток, но все обновления пользовательского интерфейса относятся к потоку AWT. Следовательно, очень частые вызовы методов jLbl_date.setText() и jLbl_time.setText() этим потоком фактически блокируют поток AWT напрямую.

Попробуйте добавить sleep(1000) после jLbl_Time.setText().

person Subhranil    schedule 22.02.2017
comment
Также setText вызовы должны быть SwingUtilities.InvokeLatered. - person Colin; 22.02.2017
comment
Да, должно, поправьте меня, если я ошибаюсь, но AWT не ограничивает доступ к многопоточному пользовательскому интерфейсу, как JavaFX. - person Subhranil; 22.02.2017
comment
@Subhranil, спасибо за твой ответ. Я попробовал то, что вы сказали сейчас. но он показывает ошибку. пожалуйста, не могли бы вы изменить мой код и прокомментировать здесь ...? это так полезно для меня. - person siper camm; 22.02.2017
comment
JLabel - это Swing, и его не следует изменять никаким потоком, кроме потока отправки событий. - person Colin; 22.02.2017
comment
Привет, @Colin__s, ты сказал, что я не понял. пожалуйста, не могли бы вы объяснить, как изменить мой код ...? это более полезно для меня. Я просто новичок в java ... - person siper camm; 22.02.2017
comment
@sipercamm нет ничего, что называется ошибкой. Вставьте исключение. - person Subhranil; 22.02.2017
comment
Я знаю и понимаю, что @Colin__s, мне просто интересно, вызовет ли это какое-либо исключение. - person Subhranil; 22.02.2017
comment
@Subhranil, здесь: Исключение в потоке Thread-2 java.lang.RuntimeException: Некомпилируемый исходный код - Ошибочный тип символьного файла: sleep at view.AdminStudent $ 1.run (AdminStudent.java:55) at java.lang.Thread.run (Thread .java: 745) - person siper camm; 22.02.2017
comment
Нет, насколько я знаю, это не вызовет исключения. - person Colin; 22.02.2017
comment
Между тем это проблема netbeans. stackoverflow.com/questions/2333285/ - person Subhranil; 22.02.2017

Похоже, вы создали поток для запуска бесконечного цикла для обновления некоторых полей даты и времени. Это не очень хороший способ добиться того, что вы хотите делать.

Лучшим решением было бы использовать javax.swing.Timer с коротким интервалом и обновлять пользовательский интерфейс с помощью прикрепленного прослушивателя действий.

ActionListener timerListener = new ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        Date d=new Date();

        SimpleDateFormat sd=new SimpleDateFormat("yyyy - MM - dd");
        String s =  sd.format(d);
        String s1 = d.toString();
        String ar[]=s1.split(" ");

        jLbl_Date.setText(s);  
        jLbl_Time.setText(ar[3]);
    }
};

Timer t = new javax.swing.timer(1000, timerListener).start();

Что-то вроде вышеперечисленного должно помочь. Это избавит вас от необходимости пересекать границы потоков для обновления пользовательского интерфейса и существенно снизит загрузку процессора по сравнению с предыдущим решением.

person Colin    schedule 22.02.2017
comment
Я добавил ур код. но получил ошибку, и этот jframe также не запускается ... его говорят, что здесь нет основного метода, прикрепленного к вашему коду в моем коде: - person siper camm; 22.02.2017
comment
общедоступный AdminStudent () {initComponents (); ActionListener timerListener = новый ActionListener {public void actionPerformed (ActionEvent e) {Date d = new Date (); SimpleDateFormat sd = новый SimpleDateFormat (гггг - ММ - дд); Строка s = sd.format (d); Строка s1 = d.toString (); Строка ar [] = s1.split (); jLbl_Date.setText (s); jLbl_Time.setText (ar [3]); }} Таймер t = новый javax.swing.timer (1000, timerListener) .start (); } - person siper camm; 22.02.2017
comment
Я пропустил ; в конце прослушивателя действий - person Colin; 22.02.2017