ChronoApp

m@rcwabo Messages postés 6 Date d'inscription jeudi 20 octobre 2016 Statut Membre Dernière intervention 3 mai 2019 - 21 oct. 2016 à 00:32
m@rcwabo Messages postés 6 Date d'inscription jeudi 20 octobre 2016 Statut Membre Dernière intervention 3 mai 2019 - 3 mai 2019 à 17:05
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/101669-chronoapp

m@rcwabo Messages postés 6 Date d'inscription jeudi 20 octobre 2016 Statut Membre Dernière intervention 3 mai 2019
3 mai 2019 à 17:05
Merci.
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 127
22 oct. 2016 à 16:45
Bonjour m@rcwabo,

En premier lieu, je signale qu'il est nécessaire d'avoir swing-layout.jar dans son classpath pour compiler et exécuter ton code, en raison des dépendances
org.jdesktop.layout.*


Ensuite, ce code se veut, je cite "Une simple application des threads en java", or il n'en est rien, puisque hormis le code généré automatique par Netbeans, on n'utilise pas de threads.

D'ailleurs, parlons du code généré automatiquement par Netbeans, d'une part il ne permet pas d'apprendre à programmer en Java puisque l'éditeur fait toute la partie graphique, d'autre part le code généré est particulièrement affreux, sans parler de la nécessité d'ajouter des dépendances comme mentionné plus haut.

Ainsi donc, si on reprends le code, on peut allègrement simplifier le tout, en commençant par la méthode
runHorloge()
qui est a priori ton seul code perso.

private void runHorloge() {
    Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            displayTime();
        }
    }, 0, 1, TimeUnit.SECONDS);
}

private void displayTime() {
    long millis = System.currentTimeMillis();
    String hour = String.format("%1$tH:%1$tM", millis);
    int sec = (int) (millis / 1000) % 60;
    jPbSeconds.setValue(sec);
    jtfHourContainer.setText(hour);
}

Ici, j'ai fait un vrai traitement de thread, en utilisant un ExecutorService qui va automatiquement être appelé par Java toutes les secondes, ce qui est plus fiable que ta boucle
while(true)
avec des
Thread.sleep(1000);
qui ne prennent pas en compte le temps que tu passes à effectuer chaque action d'affichage.

Remarque, depuis Java 8 on peut simplifier l'écriture des interface fonctionnelles (comme Runnable) avec des lambda expressions. Exemple :

private void runHorloge() {
    Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
        () -> displayTime(), 0, 1, TimeUnit.SECONDS);
}

Quant au code de l'interface graphique, une fois qu'on enlève ce qui n'était utile qu'à Netbeans et pas au programme lui même, ça devient super simple.
Notons au passage que dans le code suivant je me suis débarrassé de la dépendance sur swing-layout.jar c'est donc du pur Java.

package com.chronoApp.gij;

import java.awt.*;
import java.util.concurrent.*;
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;

public class ChronoApp extends JFrame {

    private static final long serialVersionUID = 1L;

    private final JProgressBar jPbSeconds;
    private final JTextField jtfHourContainer;

    public ChronoApp() {
        setTitle("ChronoApp 2.0!");
        setIconImage(Toolkit.getDefaultToolkit().getImage("src/com/chronoApp/gij/ico_image.jpg"));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocationByPlatform(true);
        setResizable(false);
        setAlwaysOnTop(true);

        jPbSeconds = new JProgressBar(0, 59);

        jtfHourContainer = new JTextField();
        jtfHourContainer.setEditable(false);
        jtfHourContainer.setForeground(Color.LIGHT_GRAY);
        jtfHourContainer.setBackground(Color.DARK_GRAY);
        jtfHourContainer.setFont(new Font("Segoe UI", 0, 92));
        jtfHourContainer.setHorizontalAlignment(JTextField.CENTER);
        jtfHourContainer.setBorder(null);

        GroupLayout jPGlobalContainerLayout = new GroupLayout(getContentPane());
        jPGlobalContainerLayout.setHorizontalGroup(jPGlobalContainerLayout.createParallelGroup()
                .addComponent(jPbSeconds, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 241, Short.MAX_VALUE)
                .addComponent(jtfHourContainer, Alignment.TRAILING));
        jPGlobalContainerLayout.setVerticalGroup(jPGlobalContainerLayout.createSequentialGroup()
                .addComponent(jPbSeconds, GroupLayout.PREFERRED_SIZE, 42, GroupLayout.PREFERRED_SIZE)
                .addComponent(jtfHourContainer));
        getContentPane().setLayout(jPGlobalContainerLayout);

        pack();
    }

    private void displayTime() {
        long millis = System.currentTimeMillis();
        String hour = String.format("%1$tH:%1$tM", millis);
        int sec = (int) (millis / 1000) % 60;
        jPbSeconds.setValue(sec);
        jtfHourContainer.setText(hour);
    }

    private void runHorloge() {
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
                () -> displayTime(), 0, 1, TimeUnit.SECONDS);
    }

    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel(NimbusLookAndFeel.class.getName());
        } catch (Exception e) {
        }

        ChronoApp app = new ChronoApp();
        app.runHorloge();
        app.setVisible(true);
    }
}

Un code total de 70 lignes, à comparer aux 190 lignes de ton code initial, pour faire la même chose... il ne faut juste pas laisser Netbeans faire lui même le code !
Rejoignez-nous