OVH Cloud OVH Cloud

tracé fantôme d'un bouton dans une fenêtre graphique

2 réponses
Avatar
Jean-Marc Vanel
J'ai une hiérarchie très simple de Component:
- contentPane avec BorderLayout
- JButton au Nord
- JPanel au centre sur lequel je trace du graphisme dans un thread à moi

Je regarde pourquoi il y a un tracé fantôme du bouton dans la fenêtre graphique.
Ce n'est pas un vrai bouton car en faisant un "dump" de
toute la hérarchie des composants AWT/Swing et on ne voit qu'un seul bouton.

J'emploie les grands moyens: je mets un point d'arrêt dans
AbstractButton.paintBorder()
Je vois 2 piles d'appels; apparemment c'est la 2ème qui est en trop.
COMMENT FAIRE POUR LA SUPPRIMER?

Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 1235 in AbstractButton))
JButton(AbstractButton).paintBorder(Graphics) line: 1235
JButton(JComponent).paint(Graphics) line: 809
JPanel(JComponent).paintChildren(Graphics) line: 647
JPanel(JComponent).paint(Graphics) line: 817
JLayeredPane(JComponent).paintChildren(Graphics) line: 647
JLayeredPane(JComponent).paint(Graphics) line: 817
JLayeredPane.paint(Graphics) line: 557
JRootPane(JComponent).paintChildren(Graphics) line: 647
JRootPane(JComponent).paintWithOffscreenBuffer(JComponent, Graphics, int,
int, int, int, Image) line: 4802
JRootPane(JComponent).paintDoubleBuffered(JComponent, Component, Graphics,
int, int, int, int) line: 4748
JRootPane(JComponent).paint(Graphics) line: 798
GraphicsCallback$PaintCallback.run(Component, Graphics) line: 21

GraphicsCallback$PaintCallback(SunGraphicsCallback).runOneComponent(Component,
Rectangle, Graphics, Shape, int) line: 60

GraphicsCallback$PaintCallback(SunGraphicsCallback).runComponents(Component[],
Graphics, int) line: 97
JFrame(Container).paint(Graphics) line: 1312
RepaintArea.paint(Object, boolean) line: 177
MFramePeer(MComponentPeer).handleEvent(AWTEvent) line: 405
JFrame(Component).dispatchEventImpl(AWTEvent) line: 3678
JFrame(Container).dispatchEventImpl(AWTEvent) line: 1627
JFrame(Window).dispatchEventImpl(AWTEvent) line: 1606
JFrame(Component).dispatchEvent(AWTEvent) line: 3477
EventQueue.dispatchEvent(AWTEvent) line: 456
EventDispatchThread.pumpOneEventForHierarchy(int, Component) line: 201
EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component)
line: 151
EventDispatchThread.pumpEvents(int, Conditional) line: 145
EventDispatchThread.pumpEvents(Conditional) line: 137
EventDispatchThread.run() line: 100
------------------------------------------------------------
Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 1235 in AbstractButton))
JButton(AbstractButton).paintBorder(Graphics) line: 1235 [local variables
unavailable]
JButton(JComponent).paint(Graphics) line: 809
JButton(JComponent).paintWithOffscreenBuffer(JComponent, Graphics, int,
int, int, int, Image) line: 4795
JButton(JComponent).paintDoubleBuffered(JComponent, Component, Graphics,
int, int, int, int) line: 4748
JButton(JComponent)._paintImmediately(int, int, int, int) line: 4692
JButton(JComponent).paintImmediately(int, int, int, int) line: 4495
RepaintManager.paintDirtyRegions() line: 410
SystemEventQueueUtilities$ComponentWorkRequest.run() line: 117
InvocationEvent.dispatch() line: 178
EventQueue.dispatchEvent(AWTEvent) line: 454
EventDispatchThread.pumpOneEventForHierarchy(int, Component) line: 201
EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component)
line: 151
EventDispatchThread.pumpEvents(int, Conditional) line: 145
EventDispatchThread.pumpEvents(Conditional) line: 137
EventDispatchThread.run() line: 100
---------------

Pour les curieux, le source complet est ici:
http://cvs.sourceforge.net/viewcvs.py/ecolosim/src/ecolosim/simu/apps/MultipleModelsApp.java?rev=1.1.1.1&view=markup

2 réponses

Avatar
Bruno Nogent
Est-ce que tes appels a l'interface graphique se font bien dans le Thread de
l'interface graphique ?



"Jean-Marc Vanel" wrote in message
news:bueecg$coc$
J'ai une hiérarchie très simple de Component:
- contentPane avec BorderLayout
- JButton au Nord
- JPanel au centre sur lequel je trace du graphisme dans un thread à moi

Je regarde pourquoi il y a un tracé fantôme du bouton dans la fenêtre
graphique.

Ce n'est pas un vrai bouton car en faisant un "dump" de
toute la hérarchie des composants AWT/Swing et on ne voit qu'un seul
bouton.


J'emploie les grands moyens: je mets un point d'arrêt dans
AbstractButton.paintBorder()
Je vois 2 piles d'appels; apparemment c'est la 2ème qui est en trop.
COMMENT FAIRE POUR LA SUPPRIMER?

Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 1235 in
AbstractButton))

JButton(AbstractButton).paintBorder(Graphics) line: 1235
JButton(JComponent).paint(Graphics) line: 809
JPanel(JComponent).paintChildren(Graphics) line: 647
JPanel(JComponent).paint(Graphics) line: 817
JLayeredPane(JComponent).paintChildren(Graphics) line: 647
JLayeredPane(JComponent).paint(Graphics) line: 817
JLayeredPane.paint(Graphics) line: 557
JRootPane(JComponent).paintChildren(Graphics) line: 647
JRootPane(JComponent).paintWithOffscreenBuffer(JComponent, Graphics,
int,

int, int, int, Image) line: 4802
JRootPane(JComponent).paintDoubleBuffered(JComponent, Component,
Graphics,

int, int, int, int) line: 4748
JRootPane(JComponent).paint(Graphics) line: 798
GraphicsCallback$PaintCallback.run(Component, Graphics) line: 21


GraphicsCallback$PaintCallback(SunGraphicsCallback).runOneComponent(Componen

t,
Rectangle, Graphics, Shape, int) line: 60


GraphicsCallback$PaintCallback(SunGraphicsCallback).runComponents(Component[

],
Graphics, int) line: 97
JFrame(Container).paint(Graphics) line: 1312
RepaintArea.paint(Object, boolean) line: 177
MFramePeer(MComponentPeer).handleEvent(AWTEvent) line: 405
JFrame(Component).dispatchEventImpl(AWTEvent) line: 3678
JFrame(Container).dispatchEventImpl(AWTEvent) line: 1627
JFrame(Window).dispatchEventImpl(AWTEvent) line: 1606
JFrame(Component).dispatchEvent(AWTEvent) line: 3477
EventQueue.dispatchEvent(AWTEvent) line: 456
EventDispatchThread.pumpOneEventForHierarchy(int, Component) line:
201

EventDispatchThread.pumpEventsForHierarchy(int, Conditional,
Component)

line: 151
EventDispatchThread.pumpEvents(int, Conditional) line: 145
EventDispatchThread.pumpEvents(Conditional) line: 137
EventDispatchThread.run() line: 100
------------------------------------------------------------
Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 1235 in
AbstractButton))

JButton(AbstractButton).paintBorder(Graphics) line: 1235 [local
variables

unavailable]
JButton(JComponent).paint(Graphics) line: 809
JButton(JComponent).paintWithOffscreenBuffer(JComponent, Graphics,
int,

int, int, int, Image) line: 4795
JButton(JComponent).paintDoubleBuffered(JComponent, Component,
Graphics,

int, int, int, int) line: 4748
JButton(JComponent)._paintImmediately(int, int, int, int) line: 4692
JButton(JComponent).paintImmediately(int, int, int, int) line: 4495
RepaintManager.paintDirtyRegions() line: 410
SystemEventQueueUtilities$ComponentWorkRequest.run() line: 117
InvocationEvent.dispatch() line: 178
EventQueue.dispatchEvent(AWTEvent) line: 454
EventDispatchThread.pumpOneEventForHierarchy(int, Component) line:
201

EventDispatchThread.pumpEventsForHierarchy(int, Conditional,
Component)

line: 151
EventDispatchThread.pumpEvents(int, Conditional) line: 145
EventDispatchThread.pumpEvents(Conditional) line: 137
EventDispatchThread.run() line: 100
---------------

Pour les curieux, le source complet est ici:

http://cvs.sourceforge.net/viewcvs.py/ecolosim/src/ecolosim/simu/apps/MultipleModelsApp.java?rev=1.1.1.1&view=markup


Avatar
Jean-Marc Vanel
Bruno Nogent wrote:
Est-ce que tes appels a l'interface graphique se font bien dans le Thread de
l'interface graphique ?


J'ai essayé; ça "marche" en ce sens que je n'ai plus le tracé fantôme du bouton.
Mais le Thread des évènements graphiques (AWT-eventQueue-0) ne donne plus du
tout la main à l'utilisateur. Et ce, alors que j'y ai inséré un :
Thread.sleep(30);
qui suffit bien dans la version actuelle, pas belle mais qui marche.
Il faut bien comprendre que mon dessin graphique est la visualisation en temps
réel d'une simulation qui dure aussi longtemps que l'utilisateur le veut et qui
prend presque 100% du CPU.

Dans le tutorial Java de Sun (Threads and Swing):
http://java.sun.com/docs/books/tutorial/uiswing/overview/threads.html
on trouve ceci:
Two JComponent methods are safe to call from any thread: repaint and revalidate.
These methods queue requests to be executed on the event-dispatching thread.

J'utilise donc repaint().

Je viens de trouver un article assez détaillé que je vais lire:
http://java.sun.com/products/jfc/tsc/articles/painting/index.html

J'ai concentré ici le problème en 80 lignes:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
* Created on 29 jan. 2003
* @author J.M. Vanel - $HEADER$
*/
public class TestSimpleGraphicsRealTime implements Runnable {
Container realTimePanel_;
private Graphics2D g_;

private int tailleX_ = 1000;
private int tailleY_ = 1000;

/** */
public static void main(String[] args) {
TestSimpleGraphicsRealTime appli = new TestSimpleGraphicsRealTime();
try {
appli.afficheFenetre();
} catch (Exception e) {
System.out.println("Erreur interne");
e.printStackTrace();
}
}

protected void afficheFenetre() throws Exception {
JFrame j = new JFrame( getClass().getName() );
addVisualizationPanel( j.getContentPane() );
j.pack();
j.setSize( tailleX_, tailleY_);
j.setVisible(true);
WindowAdapter windowListener = new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
};
j.addWindowListener(windowListener);

Thread t = new Thread(this, "mise à jour bestiaux");
t.start();
}

/** Ajoute dans le panneau donné la visualisation de la simulation;
* on peut donc utiliser ceci dans une autre fenêtre et une autre application. */
public void addVisualizationPanel(Container contentPane) {
realTimePanel_ = new Panel();
contentPane.setLayout( new BorderLayout() );
contentPane.add(realTimePanel_, BorderLayout.CENTER );

JButton but = new JButton("Arrêter/relancer simulation");
contentPane.add( but, BorderLayout.NORTH );
}

/** Ce Thread met à jour la visualisation de la simulation en appelant
(indirectement)
* {@link Panel.paintComponent()}
* @see java.lang.Runnable#run()
*/
public void run() {
while ( true ) {
if ( realTimePanel_ != null )
realTimePanel_.repaint();
try {
Thread.sleep(30);
} catch (InterruptedException e) { System.exit(0); }
}
}

/** Cette classe met à jour la visualisation de la simulation */
class Panel extends JPanel {
protected void paintComponent(Graphics g) {
int x = (int) (Math.random() * tailleX_ );
int y = (int) (Math.random() * tailleY_ );
g.drawOval (x,y, 4, 4);
}
}
}