Как установить новое значение (Дата) для свойства компонента Java? - PullRequest
3 голосов
/ 08 января 2020

Я программирую bean-компонент (я изучаю Java и Java bean-компоненты), который представляет собой цифровые часы с коэффициентом JLabel. Показанный текст будет выглядеть следующим образом: hh:mm:ss.

Когда я пытаюсь использовать компонент (часы) в новом проекте, он по умолчанию показывает дату системы (я запрограммировал компонент для работы таким образом) , Однако я хотел бы позволить разработчику (в данном случае самому) редактировать свойство "hora", чтобы установить другую дату. Поэтому, если разработчик вставит компонент в новый проект, текст должен соответствовать времени системы. Однако если разработчик отредактирует свойство "hora" и установит новую дату, например, еще на один час, показанный текст должен быть новым значением, в этом примере system date + 1 hour.

Мой текущий код работает частично :

Use of the bean in a new project with the date changed.

На предыдущем изображении:

  • Справа свойство "hora" имеет значение: системная дата + 1 час.
  • Слева в окне предварительного просмотра NetBeans отображается правильное время (системное время + 1 час). Разница в минутах заключается в том, что часы работают и меняют каждую секунду своего времени. Снимок экрана был сделан через несколько минут после редактирования значения свойства.
  • В центре проект работает и показывает неправильную дату (системную дату).
  • Пожалуйста, игнорируйте кнопку и счетчик, они только для целей тестирования.

Как я могу изменить это поведение? Поэтому, когда я запускаю проект, показанное время совпадает с выбранным в свойстве "hora"?

Соответствующий код:

public class Reloj extends JLabel implements Serializable {
    private Date hora = new Date();
    private SimpleDateFormat formatoHora;
    private boolean doceHoras = false;

    public Reloj() {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
             public void run() {
                setHora(new Date((getHora().getTime())+1000));

            }
        }, 0, 1000);
    }

    public Date getHora() {
        return this.hora;
    }

    public void setHora(Date hora) {
        this.hora = hora;
        this.setText(this.getFormatoHora().format(hora));
        this.repaint();
    }

    public SimpleDateFormat getFormatoHora() {
        if (this.isDoceHoras()) {
            this.formatoHora = new SimpleDateFormat("hh:mm:ss a");
        } else {
            this.formatoHora = new SimpleDateFormat("HH:mm:ss");
        }
        return this.formatoHora;
    }

    public void setDoceHoras(boolean doceHoras) {
        this.doceHoras = doceHoras;
        this.setHora(hora);
    }
}

Спасибо за помощь и извините за мой Engli sh.

1 Ответ

2 голосов
/ 09 января 2020

JavaBeans как компонент виджета

(я изучаю Java и Java бинов)

Насколько я знаю, используя JavaBeans как компонент в инструментах визуального дизайна никогда не завоевывал популярность. Я удивлен, что NetBeans все еще поддерживает это. Я рекомендую вам не тратить слишком много времени или усилий на этот аспект технологии JavaBean.

java .time

по умолчанию отображается дата система (я запрограммировал бин для работы таким образом).

Вы используете ужасные классы даты и времени, которые были заменены годами go современными java .time классы, определенные в JSR 310.

Никогда не используйте Date или SimpleDateFormat. Если вам необходимо взаимодействовать со старым кодом, который еще не обновлен до java .time , выполните все свои логи c в java .time и в конце выполните преобразование, используя новые методы добавлены к старым классам.

Для значения только для времени дня, без даты и без часового пояса, используйте LocalTime.

Часовой пояс

Получение текущего времени суток подразумевает получение текущего момента. И это требует часового пояса. В любой момент времени дата и время суток меняются по всему земному шару в зависимости от часового пояса.

Если часовой пояс не указан, JVM неявно применяет свой текущий часовой пояс по умолчанию. Это значение по умолчанию может измениться в любой момент во время выполнения (!), Поэтому ваши результаты могут отличаться. Лучше явно указать желаемый / ожидаемый часовой пояс в качестве аргумента. Если вы хотите использовать текущий часовой пояс JVM по умолчанию, проясните свое намерение, позвонив по номеру ZoneId.systemDefault(). Если критично, подтвердите зону с вашим пользователем.

Укажите правильное имя часового пояса в формате Continent/Region, например America/Montreal, Africa/Casablanca или Pacific/Auckland , Никогда не используйте 2-4 буквенные сокращения, такие как EST или IST, поскольку они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalTime lt = LocalTime.now( z ) ;

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

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.
LocalTime lt = LocalTime.now( z ) ;

Если это содержание имеет решающее значение, вы должны подтвердить часовой пояс с пользователем. По умолчанию система может не соответствовать намерениям пользователя, особенно если учесть, что мобильные устройства и ноутбуки легко перемещаются между часовыми поясами. В таком случае вы должны сохранить объект ZoneId в качестве поля члена в вашем классе виджетов или в другом месте, доступном для виджета.

Так что если разработчик вставит компонент в новый проект текст должен быть временем системы.

Вы можете анализировать вводимый пользователем текст. Если в стандартном формате ISO 8601 , ЧЧ: ММ: СС с 24-часовыми часами, вам не нужно беспокоиться об указании шаблона форматирования. Классы java .time по умолчанию используют стандартные форматы при разборе / генерации текста.

String input = "23:01:23" ;
LocalTime lt = LocalTime.parse( input ) ;

Если вы хотите локализовать отображаемый текст, представляющий значение нашего LocalTime объект, используйте DateTimeFormatter. Укажите Locale, чтобы определить человеческий язык и культурные нормы , используемые при локализации . И укажите FormatStyle, чтобы сказать, как долго или сокращенно.

Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ) ;

Поиск, чтобы узнать больше. Об этом уже много раз говорилось о переполнении стека.

Dynami c update

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

Я подозреваю, что вы действительно хотите, чтобы две части, работающие вместе: отображение времени суток и часовой пояс. Если вы пытаетесь разрешить пользователю смещать отображение часов в соответствии со своим часовым поясом, вы должны сделать это, позволив пользователю указать часовой пояс (как обсуждалось выше). Другими словами, смещение часов должно быть следствием, а не причиной. Пользователь управляет свойством часового пояса, и часы автоматически изменяют свое время, как видно из смещения, используемого людьми региона, представленного этим часовым поясом.

Другая проблема: обновление Periodi c. Вы используете Timer и TimerTask, два класса, которые были заменены структурой Executor . В частности, в Swing вы должны использовать класс javax.swing.Timer (см. Tutorial ), а не java.util.Timer.

Обязательное предупреждение: никогда не открывайте, не обновляйте и не манипулируйте виджетами Swing из фонового потока. Делайте это только в потоке пользовательского интерфейса.

Пример приложения

Вот простой и быстрый пример приложения Swing. Это не компонент JavaBean. И я мало что помню о Swing. Но это может немного помочь вам. Вы можете видеть, как изменение часового пояса (ZoneId) обновляет время суток, смещая его к смещению, действующему в настоящее время в этой зоне.

Screenshot of localized time-of-day with a field to enter a time zone.

package org.example;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.DateTimeException;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;

/**
 * Hello world!
 */
public class App extends JFrame
{
    ZoneId zoneId;
    LocalTime localTime;
    JTextField timeZone;
    JLabel displayTime;
    DateTimeFormatter formatter;


    public App ( )
    {
        initUI();
    }

    private void initUI ( )
    {

        setTitle( "Simple example" );
        setSize( 300 , 200 );
        setLocationRelativeTo( null );
        setDefaultCloseOperation( EXIT_ON_CLOSE );

        // Widgets
        this.zoneId = ZoneId.systemDefault();
        this.timeZone = new JTextField( this.zoneId.getId() , 20 );
        this.localTime = LocalTime.now( this.zoneId );
        Locale locale = Locale.CANADA_FRENCH;
        this.formatter = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM );
        this.displayTime = new JLabel( this.localTime.format( this.formatter ) );

        this.timeZone.addActionListener( new ActionListener()
        {
            @Override
            public void actionPerformed ( ActionEvent event )
            {
                System.out.println( "The entered text is: " + timeZone.getText() );
                try
                {
                    zoneId = ZoneId.of( timeZone.getText() );
                    localTime = LocalTime.now( zoneId );
                    String output = LocalTime.now( zoneId ).format( formatter );
                    displayTime.setText( output );
                }
                catch ( DateTimeException e )
                {
                    System.out.println( "BAD INPUT - The user gave an invalid time zone: " + timeZone );
                }
            }
        } );

        // Arrange
        JPanel panel = new JPanel();
        panel.add( this.displayTime );
        panel.add( this.timeZone );
        this.add( panel );
    }

    public static void main ( String[] args )
    {

        EventQueue.invokeLater( ( ) -> {

            var ex = new App();
            ex.setVisible( true );
        } );
    }
}

О java .time

В java .time встроен фреймворк Java 8 и позже. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Чтобы узнать больше, см. Учебник Oracle . И поиск переполнения стека для многих примеров и объяснений. Спецификация: JSR 310 .

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java .time классы.

Вы можете обмениваться java .time объектами непосредственно с вашей базой данных. Используйте драйвер JDB C , совместимый с JDB C 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где взять классы java .time?

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 и более поздних версий - часть стандартного API Java со связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большинство функций java .time перенесено на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android связывают реализации классов java .time .
    • Для более ранних Android (<26) <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP проект адаптируется ThreeTen-Backport (упомянуто выше). См. Как использовать ThreeTenABP… .

ThreeTen-Extra Проект расширяет java .time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java .time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

...