2009-05-29 4 views
0

J'ai une classe personnalisée qui étend JLabel. Pour les instances spécifiques de cette classe, je veux ajouter un peu d'espace au texte sur le côté gauche. J'ai besoin de l'espacement lorsque je place l'arrière-plan de ce JLabel et je ne veux pas que le texte corresponde juste à côté du bord de l'arrière-plan coloré. Je pêchais autour d'un peu et mis en œuvre ce (dans la fonction de peinture):Méthode setBorder pour JLabel provoquant un problème de peinture

if (condition) { 
    bgColor = Color.red; 
    setBackground(bgColor); 
    setOpaque(true); 
    // This line merely adds some padding on the left 
    setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); 
} 
else { 
    setOpaque(false); 
} 

Cela semble fonctionner en ce qu'elle ajoute l'espacement que je veux, mais il a un effet secondaire malheureux en ce qu'il semble briser la repeindre tout le reste de l'application ... il semble que seul ce composant particulier est repeindre et pas le reste de l'application. J'ai finalement suivi jusqu'à l'appel de setBorder spécifiquement ... la mise en place de tout type de frontière semble provoquer le même comportement brisé. Nous avons deux versions différentes de notre application, une qui s'exécute en Java 1.5 et une qui s'exécute en Java 1.6, la version Java 1.6 semble fonctionner correctement tandis que la version Java 1.5 ne fonctionne pas. Il n'est pas possible de mettre à jour l'ancienne version vers Java 1.6 ... J'ai besoin de quelque chose qui fonctionnera dans Java 1.5. En outre, j'ai essayé ceci (juste pour voir à quoi il ressemblait):

setHorizontalTextPosition(JLabel.CENTER); 

Et qui semble aussi briser le repeindre exactement de la même manière. J'ai regardé à travers la source de notre application et trouvé d'autres endroits où nous avons défini des bordures (y compris des bordures vides), mais nous n'avons pas pu en trouver sur JLabels (seulement des panneaux, des boutons, etc.). Quelqu'un a-t-il déjà vu quelque chose comme ça? Savoir comment le réparer? Ou peut-être une autre façon d'obtenir l'espacement dont j'ai besoin qui peut contourner le bug? Merci.

+0

D'où appelez-vous ce code? Si c'est dans le constructeur, tout devrait bien se passer ... si c'est à partir de paintComponent() ou quelque chose comme ça, vous pourriez rencontrer le genre de problème que vous décrivez. –

Répondre

3

Le problème est que vous appelez ce code dans la méthode de peinture. Vous ne devriez pas faire cela car cela gèlerait l'EDT avec des boucles non désirées dans le pipeline de peinture swing.

Vous devez placer ce code sur le constructeur et modifier l'état de conception des composants ailleurs dans le cycle de vie de l'application.

Si vous voulez en savoir un peu plus sur la peinture Swing, veuillez lire le message "Swing painting pipeline" sur pushing-pixels.org.

Notez que vous pouvez utiliser BorderFactory.createCompoundBorder pour combiner deux bordures. Ensuite, vous pouvez définir l'espacement avec le emptyBorder et tout autre pour dessiner la bordure extérieure.

EDIT: Exemple ajouté.

package com.stackoverflow.swing.paintpipeline; 

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Random; 

import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 
import javax.swing.border.Border; 


public class JLabelSetBorderPaintProblem extends JLabel { 

    public JLabelSetBorderPaintProblem(String text) { 
     super(text); 
    } 

    /* 
    * @see javax.swing.JComponent paint(java.awt.Graphics) 
    */ 
    @Override 
    public void paint(Graphics g) { 
     super.paint(g); 
     // You can not call setBorder here. 

     // Please check javadoc. 
    } 

    /* 
    * @see javax.swing.JComponent paintBorder(java.awt.Graphics) 
    */ 
    @Override 
    protected void paintBorder(Graphics g) { 
     super.paintBorder(g); 
     // Here is where the Swing painting pipeline draws the current border 
     // for the JLabel instance. 

     // Please check javadoc. 
    } 

    // Start me here! 
    public static void main(String[] args) { 
     // SetBorder will dispatch an event to Event Dispatcher Thread to draw the 
     // new border around the component - you must call setBorder inside EDT. 
     // Swing rule 1. 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override public void run() { 
       // Inside EDT 
       JFrame frame = new JFrame("JLabel setBorder example"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       // Add the JLabel 
       final JLabelSetBorderPaintProblem label = new JLabelSetBorderPaintProblem("Just press or wait..."); 
       frame.add(label); 

       // And change the border... 
       label.addMouseListener(new MouseAdapter() { 
        @Override public void mousePressed(MouseEvent e) { 
         label.setBorder(BORDERS.get(new Random().nextInt(BORDERS.size()))); 
        } 
       }); 

       // ...whenever you want 
       new Timer(5000, new ActionListener() { 
        @Override public void actionPerformed(ActionEvent e) { 
         label.setBorder(BORDERS.get(new Random().nextInt(BORDERS.size()))); 
        } 
       }).start(); 

       frame.pack(); 
       frame.setVisible(true); 
      } 
     }); 

    } 

    public static final List<Border> BORDERS; 
    static { 
     BORDERS = new ArrayList<Border>(); 
     BORDERS.add(BorderFactory.createLineBorder(Color.BLACK)); 
     BORDERS.add(BorderFactory.createLineBorder(Color.RED)); 
     BORDERS.add(BorderFactory.createEtchedBorder()); 
     BORDERS.add(BorderFactory.createTitledBorder("A border")); 
    } 
} 
+0

Cela semble définitivement être le noeud du problème. Nous avons résolu le problème en créant la bordure en tant que statique globale (comme les autres bordures de l'application) et en définissant la bordure dans la méthode de peinture. Je n'ai toujours pas une idée assez précise de ce qui se passe ici, mais cela semble résoudre le problème, donc je vais l'appeler assez bon. – Morinar

Questions connexes