[JAVA] Lorsque j'ai essayé de faire défiler automatiquement avec JScrollBar, le gestionnaire d'événements n'a été dessiné qu'une seule fois.

Il est resté bloqué et a été époustouflé pendant quelques heures, donc au lieu d'un mémo. Quiconque utilise Swing semble avoir échoué une fois.

Ce qui a été fait

J'essayais de créer quelque chose comme un shell auto-créé en Java, et j'essayais de faire défiler automatiquement JScrollPane. C'est le code source que j'ai écrit lors de la vérification.

MyShell.java


class MyShell extends JFrame implements ActionListener{
    MyShell{
//(Omis)
    String now = new File(".").getAbsoluteFile().getParent().toLowerCase();//Répertoire actuel

    JTextField text = new JTextField();//Zone de saisie
    text.addActionListener( this );
    JTextArea area = new JTextArea(now+"->");//Zone d'affichage
    JScrollPane scrollpane = new JScrollPane(area);

    JPanel p = new JPanel()
    p.add(text,BorderLayout.SOUTH);
    p.add(scrollpane);
//(Omis)
    }
    public void actionPerformed(ActionEvent e){
  	    String input = text.getText().toLowerCase();
  	    if(input.equals("exit")){System.exit(0);}//Pour résiliation forcée
        area.append(text.getText()+"\nPC->"+mani(input.split(" "))+"\n\n"+now+"->");//Ajouté à la zone de dessin
        text.setText("");//Effacer le contenu de la zone de saisie

        JScrollBar scrollBar = scrollpane.getVerticalScrollBar();
        scrollBar.setValue(scrollBar.getMaximum());
    }
    public String mani(String[] input){
        //Fonction d'interprétation des commandes
    }
//(Omis)
}

Pour le moment, actionPerformed est appelée lorsque la touche Entrée est enfoncée dans le champ de saisie de texte (lien de référence) ). Ensuite, immédiatement après avoir appuyé sur la touche Entrée, la commande est interprétée et ajoutée à la zone de dessin. Après cela, il a été défilé par la hauteur de la barre de défilement, et le bas de JTextArea a été affiché ...

Qu'est ce qui ne s'est pas bien passé

En conclusion, le processus enregistré comme gestionnaire d'événements est dessiné une fois tous les processus terminés. En d'autres termes, la taille qui peut être obtenue avec scrollBar.getMaximum () '' est la taille avant de redessiner, donc vous ne pouvez aller qu'au bas de JTextArea avant de redessiner. Si vous insérez également Thread.sleep (1000) dans la dernière ligne de ʻactionPerformed`, vous pouvez bien voir le comportement. Eh bien, si vous y réfléchissez bien, il vaut mieux faire le processus de dessin le moins de fois possible, et bien sûr, c'est naturel.

Solution

(Si vous recherchez correctement sur le net, vous pouvez obtenir autant d'informations que vous le souhaitez ...)

Pensez à un seul gestionnaire d'événements comme n'autorisant que les changements d'état et un seul appel de repeindre. Même si vous appelez repaint plusieurs fois, la méthode paintComponent ne sera appelée qu'une seule fois. Source: https://teratail.com/questions/75183

Après une enquête plus approfondie, cet article est ... Certaines personnes étaient coincées avec la même chose ... J'ai mis le code de cet article dans ʻactionPerformed` et cela a bien fonctionné.

De plus, Swing semblait être une conception à un seul fil.

La méthode invokeLater () ... se déclenche après que tous les événements AWT en attente ont été traités

Source: http://wisdom.sakura.ne.jp/system/java/swing/swing4.html

Résumé

  1. N'essayez pas de faire quoi que ce soit avec un gestionnaire d'événements
  2. Fondamentalement, le gestionnaire d'événements n'effectue le traitement de dessin qu'une seule fois à la fin.
  3. Si vous souhaitez effectuer un traitement de dessin à partir d'un autre thread du gestionnaire d'événements dans Swing, utilisez invokeLater ()

De côté

En passant, j'ai également essayé d'utiliser «paintImmediately». Apparemment, seul le processus de dessin est utilisé et les autres valeurs numériques sont mises à jour après la fin du gestionnaire d'événements.

MyShell.java


actionPerformed(ActionEvent e){
    System.out.println(scrollbar.getValue()+"#"+scrollbar.getMaximum()+"#"+area.getHeight());
    p.paintImmediately(0,0,5000,5000);
    System.out.println(scrollbar.getValue()+"#"+scrollbar.getMaximum()+"#"+area.getHeight());
}

c'est tout.

Recommended Posts

Lorsque j'ai essayé de faire défiler automatiquement avec JScrollBar, le gestionnaire d'événements n'a été dessiné qu'une seule fois.
Problèmes auxquels j'étais accro lors de la création de l'environnement digdag avec docker
Une histoire à laquelle j'étais accro lors de l'obtention d'une clé qui a été automatiquement essayée sur MyBatis
Ce à quoi j'étais accro lors de l'introduction de la bibliothèque JNI
J'ai essayé d'augmenter la vitesse de traitement avec l'ingénierie spirituelle
Ce à quoi j'étais accro avec l'API REST Redmine
Lorsque j'ai essayé d'exécuter Azure Kinect DK avec Docker, il a été bloqué par le CLUF
L'histoire à laquelle j'étais accro lors de la création de STS
J'ai essayé de résoudre le problème de la "sélection multi-étapes" avec Ruby
J'ai essayé de créer un environnement de serveur UML Plant avec Docker
J'ai essayé d'implémenter la fonction de prévisualisation d'image avec Rails / jQuery
J'ai essayé de traduire le message d'erreur lors de l'exécution d'Eclipse (Java)
Ce à quoi j'étais accro lors de la mise en œuvre de l'authentification Google avec des rails
J'ai vérifié car la réponse était étrange lors du débogage avec Tomcat 8
J'ai essayé de vérifier le fonctionnement du serveur gRPC avec grpcurl
Faites défiler automatiquement l'arrière-plan avec libGDX
J'ai essayé d'interagir avec Java
J'ai essayé d'expliquer la méthode
J'ai essayé de comprendre le flux lors de l'analyse d'image avec Vision Framework et Core ML
[Rails] J'étais accro aux paramètres nginx lors de l'utilisation d'Action Cable.
Une histoire à laquelle j'étais accro lors du test de l'API à l'aide de MockMVC
J'ai essayé de résoudre le problème de la séquence Tribonacci en Ruby, avec récurrence.
J'ai essayé de visualiser l'accès de Lambda → Athena avec AWS X-Ray
J'étais accro aux tests unitaires avec l'opérateur de tampon dans RxJava
J'étais coincé avec la gestion des fuseaux horaires lors du formatage avec SimpleDateFormat
J'ai essayé de mesurer et de comparer la vitesse de Graal VM avec JMH
Lorsque j'essaye de m'inscrire avec devise, il redirige automatiquement vers root_path
J'ai essayé de résumer les méthodes utilisées
Comme la commande du utilisée lorsque la capacité est pleine est difficile à utiliser, j'ai essayé de l'envelopper avec du rubis
J'ai essayé de démarrer avec Web Assembly
J'étais accro à la méthode du rouleau
J'ai essayé d'implémenter le modèle Iterator
J'étais accro au test Spring-Batch
J'ai essayé de résumer l'API Stream
Ce que j'ai essayé quand je voulais obtenir tous les champs d'un haricot
J'ai essayé de comparer la technologie d'infrastructure des ingénieurs ces jours-ci avec la cuisine.
J'ai essayé de résumer à nouveau le projet qui était difficile à première vue
[JavaScript] Le cas le plus fort lorsque j'ai essayé de résumer les parties que je ne comprends pas
J'ai essayé de générer automatiquement une classe à convertir d'une classe de données en un bundle avec APT
J'ai essayé de vérifier AdoptOpenJDK 11 (11.0.2) avec l'image Docker
J'ai essayé de faire une authentification de base avec Java
J'ai essayé de gérer la configuration des jambes de force avec Coggle
[Rails] J'ai essayé de faire passer la version de Rails de 5.0 à 5.2
J'ai essayé d'organiser la session en Rails
J'étais accro à faire onActivityResult () avec DialogFragment
J'ai essayé de configurer tomcat pour exécuter le servlet.
J'ai essayé de casser le bloc avec java (1)
Ce à quoi j'étais accro lors du développement d'une application Spring Boot avec VS Code
Notez que j'étais accro au traitement par lots avec Spring Boot
Lors de la création de la première page, j'étais coincé avec la gestion des images (super débutant)