IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

[Dessin] Savoir quand une partie de la fanêtre est visible


Sujet :

AWT/Swing Java

  1. #1
    Invité
    Invité(e)
    Par défaut [Dessin] Savoir quand une partie de la fanêtre est visible
    Bonjour,

    J'ai crée un composant qui dessine de nombreuses cellules. Ce composant étend JPanel et surcharge public void paint(Graphics g) pour déléguer à une sous classe de ComponentUI.
    Tout fonctionne parfaitement (du moins comme je le voulais) à une exception prêt :
    Lorsque j'affiche une autre fenêtre au dessus de mon panel, il arrête de se dessiner (normal) mais si je bouge cette fenêtre, une zone grise reste la ou se trouvait ma fenêtre (voir pièce jointe) et lorsque je retourne sur mon composant, cette zone grise reste jusqu'à ce qu'un événement produise le redessinement.

    Actuellement, j'ai ajouté un WindowListener qui se charge d'appeler repaint() lorsque la fenêtre contenant mon panel est activée (WindowListener#windowActivated(WindowEvent e)), je n'ai donc plus cette zone grise lorsque je retourne sur mon composant mais je l'ia toujours lorsque je délace une fenêtre par dessus (voir pièce jointe).

    Y à t'il moyen d'éviter ce comportement non bloquant mais assez moche ?

    Merci
    Images attachées Images attachées  

  2. #2
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Pourquoi surcharger paint alors que tu peux directement faire un setUI et ne pas modifier le code de la méthode paint (en faisant ceci tu dérègles un peu tout ce qui est gestion des zones au niveau java, srtout si tu n'as pas ensé à faire un appel à super.paint(g) ).


    cf: http://today.java.net/pub/a/today/20...component.html
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par sinok Voir le message
    Pourquoi surcharger paint alors que tu peux directement faire un setUI et ne pas modifier le code de la méthode paint (..., surtout si tu n'as pas pensé à faire un appel à super.paint(g) ).
    Je me suis basé sur cet article : http://java.sun.com/products/jfc/tsc...ChristmasTree/ et ils y surchargent paint.
    Je n'ai pas besoin d'appeler super.paint car toutes les zones sont redessinées.

    J'ai retiré ma surcharge de paint et j'ai le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public Grid(final GridModel model) {
        	super(null);
        	this.model = model;
        	header = new GridHeader(model, this);
     
        	addHierarchyListener(new InternalViewPortHeaderRegister());
     
        	Dimension dimension = new Dimension(getWidth(), model.getRowCount()*getRowHeight());
        	setPreferredSize(dimension);
     
        	setUI(new InternalGridUid());
    	}
     
            // Pas de surcharge de paint, juste un appel à repaint dans l'évenement windowActivated
    Mais j'ai toujours le même résulat (zone grose derrière les autres fenêtres)

  4. #4
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Quelle version de java utilises tu?
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  5. #5
    Invité
    Invité(e)
    Par défaut
    J'utilise le JDK 1.5.0_16

    Et voici mon ComponentUI :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    private final class InternalGridUi extends ComponentUI {
     
      private final InternalRowNameComponent rowNameComp = new InternalRowNameComponent();
     
       private final Rectangle rowNameBounds = new Rectangle(0, 0, 0, getRowHeight());
       private final Rectangle colGroupBounds = new Rectangle(0, 0, 0, getRowHeight()); 
     
       @Override
       public void paint(Graphics g, JComponent c) {    	
       	// Row names take some percent of the width
       	rowNameBounds.width = (int) (getSize().width*NAME_CELLS_WIDTH_WEIGHT);
       	// Cell start just after the names and share the left space
       	colGroupBounds.x = rowNameBounds.width;
       	colGroupBounds.width = 
       		((getSize().width-rowNameBounds.width)/model.getGroupCount());
     
       	for (int row=viewPort.getViewPosition().y/getRowHeight(); row<model.getRowCount(); row++) {
       		drawRow(g, row);
       	}
       }
     
       private void drawRow(Graphics g, int row) {
       	Graphics drawingGrahpics = null;    	
       	rowNameComp.setBounds(0, 0, rowNameBounds.width, getRowHeight());    	
       	rowNameBounds.y = row*getRowHeight();
     
       	// Avoid drawing rows that are outside the visible area
       	if ( !rowNameBounds.intersects(g.getClipBounds()) )
       		return;
     
        rowNameComp.setName(model.getRowName(row));        		
        drawingGrahpics = g.create(rowNameBounds.x, rowNameBounds.y, 
        		rowNameBounds.width, rowNameBounds.height);
        try {
        	rowNameComp.paint(drawingGrahpics);
        } finally {
        	drawingGrahpics.dispose();
        }
     
        for (int group=0; group<model.getGroupCount(); group++) {
        	drawGroup(g, group, row);
        }
       } // drawRow
     
       private void drawGroup(Graphics g, int group, int row) {
       	Graphics drawingGrahpics = null;
       	Component cellComponent  = null;
       	final int cellCount = model.getGroupSize(group);
       	final int cellWidth = colGroupBounds.width/cellCount;
     
       	// Place the cell to the corresponding row
       	colGroupBounds.y = row*getRowHeight();
       	// Start at the begining of the previous group
       	colGroupBounds.x = rowNameBounds.width+(group*colGroupBounds.width)
       		+(group*getSpacerWidth());
     
       	// Fill a rectangle with the cell background to avoid drawing many 
       	// tiny rectangles behind each cells.
       	g.setColor(getCellBackground());
       	g.fillRect(colGroupBounds.x, colGroupBounds.y, 
       			colGroupBounds.width, getHeight());
     
       	for (int cell=0; cell<cellCount; cell++) {
     
       		// Avoid drawing cells that are outside the visible area
           	if ( !g.getClipBounds().intersects(colGroupBounds) )
           		continue;
     
       		cellComponent = renderer.getGridCellRendererComponent(
       				Grid.this, model.getValueAt(row, group, cell), row, group, cell);
       		cellComponent.setBounds(0, 0, cellWidth-2, getRowHeight()-2);
       		// cellWidth*cell to compute the start point for the cell
       		drawingGrahpics = g.create(colGroupBounds.x+1+(cellWidth*cell), 
       				colGroupBounds.y+1, cellWidth, colGroupBounds.height-1);
           try {
           	cellComponent.paint(drawingGrahpics);
           	// Draw the grid border around the cell.
           	drawingGrahpics.setColor(UIManager.getColor("Table.gridColor"));
           	drawingGrahpics.drawLine(0, 0, 0, colGroupBounds.height);
           	drawingGrahpics.drawLine(0, colGroupBounds.height-2, cellWidth, colGroupBounds.height-2);
           	if ( cell==cellCount-1 ) {
           		drawingGrahpics.drawLine(cellWidth-2, 0, cellWidth-2, colGroupBounds.height);	
           	}
           } finally {
           	drawingGrahpics.dispose();
           }        
       	}
       } // drawGroup
     
    }

  6. #6
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Donc en fait tu ne fais que subir le fameux bug du rectangle gris de Swing qui a toujours existé en version pré 1.6. C'est à dire qu'avant java 1.6, swing ne proposait pas de véritable double buffering natif.

    Y'a donc pas grand chose de possible en fait...

    Ou au pire tu déclenches de repaint de façon périodique avec un Timer Swing qui se lance quand la fenêtre perd le focus et s'arrête quand la fenêtre le regagne (ou pareil sur activation/désactivation c'est au choix).
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par sinok Voir le message
    Y'a donc pas grand chose de possible en fait...
    C'est bien ce que je "craignais". Enfin, comme je le disais c'est juste pas joli mais ça n'a rien de non fonctionnel donc je laisse comme ça.
    Mais au moins quand on me diras "héé il y à truc gris qui reste" je pourrais dire "c'est le fameux bug du rectangle gris de Swing qui a toujours existé en version pré 1.6. C'est à dire qu'avant java 1.6, swing ne proposait pas de véritable double buffering natif."


    Merci beaucoup pour ton aide.

  8. #8
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Apparemment tu redéssinne tout à chaque fois... c'est peut-ête un peu trop long d'où l'apparition du cadre gris.
    Par curiosité affiche le temps mis par ta méthode de dessin...


    Sinon... Pourquoi ne pas utiliser une JTable ???

    a++

    [edit] Et en réalité ce n'est pas vraiment un bug de Swing, mais plutôt un bug récurrent des applications Swing. En surchargeant trop l'EDT on l'empêche de faire le reste de son travail et l'interface se fige.
    Java 6 évite seulement le désagrément visuel...

  9. #9
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Par curiosité affiche le temps mis par ta méthode de dessin...

    Sinon... Pourquoi ne pas utiliser une JTable ???
    Un petit calcul sur System.currentTimeInMillis() me donne une fourchetet qui vas de 32ms a 15ms.

    Je n'utilise pas une JTable car bien que ça y ressemble c'est totalement différent dans son fonctionnement.

    Et sinon comment puis-je faire pour ne pas toujours redessiner ?

  10. #10
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    J'allais te dire de vérifier le clipbound... mais tu le fais déjà

    Tu peux peut-être essayer de faire du double-buffering. C'est à dire de dessiner ton composant (et ses changements) dans une BufferedImage, puis de te contenter de dessiner cette image lors du paint().

    a++

  11. #11
    Invité
    Invité(e)
    Par défaut
    J'ai fais modifié la méthode paint(Graphics g, JComponent c) de mon ComponentUI comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public void paint(Graphics g, JComponent c) { 
     
        		BufferedImage buffer = new BufferedImage(g.getClipBounds().width, 
        				g.getClipBounds().height, BufferedImage.TYPE_INT_RGB);
        		Graphics bufferGraphics = buffer.getGraphics();
        		bufferGraphics.setClip(g.getClipBounds().x, g.getClipBounds().y, 
        				g.getClipBounds().width, g.getClipBounds().height);
     
        		// Row names take some percent of the width
        		rowNameBounds.width = (int) (getSize().width*NAME_CELLS_WIDTH_WEIGHT);
        		// Cell start just after the names and share the left space
        		colGroupBounds.x = rowNameBounds.width;
        		colGroupBounds.width = 
        			((getSize().width-rowNameBounds.width)/model.getGroupCount());
     
        		for (int row=viewPort.getViewPosition().y/getRowHeight(); row<model.getRowCount(); row++) {
        			drawRow(bufferGraphics, row);
        		}
     
        		g.drawImage(buffer, 0, 0, null);
        		buffer.flush();
        	}
    Le résultat est bien sur un peu différent de ce que j'avais avant (couleurs et lors du scroll) mais ça ne change rien pour mon problème original.
    Côté performances, j'ai parfois des temps de 0 ms mais la plupart du temps ils sont plus longs (entre 16 et 47 ms). Je note l'idée au cas ou j'aurais de gros temps de génération avec des données de production..

    Par contre je ne comprend pas pourquoi il met parfois 0 ms à me dessiner mon composant (qui existe et à une taille > 0)

  12. #12
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Tout simplement car la précision du currentTimeInMillis nedescend pas en dessous de 16ms sous windows. De fait tout ce qui est contenu entre 0 et 16 vaut soit 0 soit 16.
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  13. #13
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par sinok Voir le message
    Tout simplement car la précision du currentTimeInMillis nedescend pas en dessous de 16ms sous windows. De fait tout ce qui est contenu entre 0 et 16 vaut soit 0 soit 16.
    Waw génial ! J'aime ce genre de petites infos qui font que l'on est modérateur ou pas ou que tt le monde nous pose des questions ou pas..

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Savoir quand une variable ou un tableau est vide
    Par cryptorchild dans le forum Langage
    Réponses: 1
    Dernier message: 17/02/2006, 08h40
  2. [javascript]Savoir quand une frame est chargée
    Par LE NEINDRE dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 22/08/2005, 09h18
  3. Comment savoir quand une JFrame est rafraichie?
    Par mardona dans le forum Agents de placement/Fenêtres
    Réponses: 1
    Dernier message: 19/08/2005, 12h20
  4. Savoir quand une hotkey est relachée
    Par kriterium dans le forum Composants VCL
    Réponses: 2
    Dernier message: 24/07/2004, 14h44
  5. [JScrollPane]Comment savoir quand une scrollbar apparait ?
    Par FrigoAcide dans le forum Composants
    Réponses: 4
    Dernier message: 29/04/2004, 10h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo