2009-08-08 9 views
5

J'ai récemment acheté le livre Filthy Rich Clients et je l'ai trouvé vraiment utile et amusant. En me basant sur un exemple du livre, j'ai essayé d'implémenter un ScrollPane personnalisé qui affiche une "ombre" en bas de la vue sur le composant à afficher. Je me suis retrouvé avec le code ci-dessous. Cela fonctionne mais pas parfaitement. Spécifiquement, lorsque je fais défiler le volet en faisant glisser la barre de défilement tout fonctionne bien et la peinture est vraiment lisse. Mais quand je défile avec la souris, défile l'ombre scintille et je ne sais pas pourquoi. Quelqu'un peut-il m'aider?Comment désactiver le comportement de peinture par défaut de l'événement de défilement de roue sur JScrollPane

EDIT: La même chose se produit pour n'importe quel composant dans le volet de défilement. Editer le code pour afficher deux images pour voir le problème.

EDIT 2: J'ai isolé le problème de la façon dont le volet de défilement gère l'événement de la molette de la souris. Lors du défilement, le volet de défilement copie légèrement le contenu du port de visualisation vers le haut ou vers le bas en fonction de l'orientation du défilement, puis dessine la région qui apparaît. Mon code rend l'ensemble du composant "sale" mais c'est après que le composant ait décalé le contenu. Donc, momentanément, vous voyez le dégradé "ombre" déplacé jusqu'à ce qu'une repeinte soit émise. Des idées sur la façon de désactiver cette fonctionnalité?

import java.awt.AlphaComposite; 
import java.awt.Color; 
import java.awt.Container; 
import java.awt.GradientPaint; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.image.BufferedImage; 

import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JTextArea; 
import javax.swing.RepaintManager; 

public class Test { 

    public static void main(String[] args) { 
     JFrame f = new JFrame("Table"); 
     JFrame f1 = new JFrame("Text Area"); 
     Object[] names = new Object[] { "Title", "Artist", "Album" }; 
     String[][] data = new String[][] { 
       { "Los Angeles", "Sugarcult", "Lights Out" }, 
       { "Do It Alone", "Sugarcult", "Lights Out" }, 
       { "Made a Mistake", "Sugarcult", "Lights Out" }, 
       { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, 
       { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, 
       { "Los Angeles", "Sugarcult", "Lights Out" }, 
       { "Do It Alone", "Sugarcult", "Lights Out" }, 
       { "Made a Mistake", "Sugarcult", "Lights Out" }, 
       { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, 
       { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, 
       { "Los Angeles", "Sugarcult", "Lights Out" }, 
       { "Do It Alone", "Sugarcult", "Lights Out" }, 
       { "Made a Mistake", "Sugarcult", "Lights Out" }, 
       { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, 
       { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, 
       { "Los Angeles", "Sugarcult", "Lights Out" }, 
       { "Do It Alone", "Sugarcult", "Lights Out" }, 
       { "Made a Mistake", "Sugarcult", "Lights Out" }, 
       { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, 
       { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, 
       { "Los Angeles", "Sugarcult", "Lights Out" }, 
       { "Do It Alone", "Sugarcult", "Lights Out" }, 
       { "Made a Mistake", "Sugarcult", "Lights Out" }, 
       { "Kiss You Better", "Maximo Park", "A Certain Trigger" }, 
       { "All Over the Shop", "Maximo Park", "A Certain Trigger" }, 
       { "Going Missing", "Maximo Park", "A Certain Trigger" } }; 
     JTable table = new JTable(data, names); 
     f.getContentPane().add(new ShadowScrollPane(table)); 
     f1.getContentPane().add(new ShadowScrollPane(new JTextArea(20, 50))); 
     RepaintManager.setCurrentManager(new RepaintManager(){ 
      @Override 
      public void addDirtyRegion(JComponent c, int x, int y, int w, int h) { 
       Container con = c.getParent(); 
       while (con instanceof JComponent) { 
        if (!con.isVisible()) { 
         return; 
        } 
        if (con instanceof ShadowScrollPane) { 
         c = (JComponent)con; 
         x = 0; 
         y = 0; 
         w = con.getWidth(); 
         h = con.getHeight(); 
        } 
        con = con.getParent(); 
       } 
       super.addDirtyRegion(c, x, y, w, h); 
      } 
     }); 
     f.pack(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setVisible(true); 
     f1.pack(); 
     f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f1.setVisible(true); 
    } 

} 

@SuppressWarnings("serial") 
class ShadowScrollPane extends JScrollPane { 

    private final int h = 50; 
    private BufferedImage img = null; 
    private BufferedImage shadow = new BufferedImage(1, h, BufferedImage.TYPE_INT_ARGB); 

    public ShadowScrollPane(JComponent com) { 
     super(com); 
     Graphics2D g2 = shadow.createGraphics(); 
     g2.setPaint(new Color(50, 50, 50)); 
     g2.fillRect(0, 0, 1, h); 
     g2.setComposite(AlphaComposite.DstIn); 
     g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h, new Color(1, 1, 1, 0.6f))); 
     g2.fillRect(0, 0, 1, h); 
     g2.dispose(); 
    } 

    @Override 
    public void paint(Graphics g) { 
     if (img == null || img.getWidth()!=getWidth() || img.getHeight() != getHeight()) { 
      img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); 
     } 
     Graphics2D g2 = img.createGraphics(); 
     super.paint(g2); 
     Rectangle bounds = getViewport().getVisibleRect(); 
     g2.scale(bounds.getWidth(), -1); 
     int y = (getColumnHeader()==null)?0:getColumnHeader().getHeight(); 
     g2.drawImage(shadow, bounds.x, -bounds.y - y-h, null); 
     g2.scale(1,-1); 
     g2.drawImage(shadow, bounds.x, bounds.y + bounds.height-h+y, null); 
     g2.dispose(); 
     g.drawImage(img, 0, 0, null); 
    } 
} 
+0

s'il vous plaît voir mon poste http://stackoverflow.com/questions/8197261/jtable-how-to-change-background-color, merci pour la grande question +1 – mKorbel

Répondre

3

Avez-vous essayé d'appeler setWheelScrollingEnabled (false) sur l'objet ScrollPane?

De l'javadoc:

active/désactive le défilement dans réponse au mouvement de la roue de la souris . Le défilement des roues est activé par par défaut.

Mise à jour suite au commentaire de Savvas ci-dessous. La méthode "setScrollMode (int)" de la fenêtre d'affichage peut peut-être vous aider. Cette méthode va déterminer comment swing fait défiler la fenêtre.

Vous pouvez obtenir la fenêtre directement à partir du ScrollPane à l'aide de la méthode getViewPort(). Vous avez les options suivantes:

BLIT_SCROLL_MODE 
BACKINGSTORE_SCROLL_MODE 
SIMPLE_SCROLL_MODE 

Selon le javadoc BLIT_SCROLL_MODE utilisera Graphics.copyArea alors essayez peut-être l'un des autres.

+0

je veux garder le comportement de défilement. Ce que je ne veux pas, c'est conserver la façon dont le volet défile en se déplaçant. Il n'utilise pas la méthode repaint mais utilise la méthode Graphics.copyArea (x, y, largeur, hauteur, dx, dy). Après que le repaint est appelé pour peindre la zone nouvellement introduite et parce que j'ai marqué le composant entier comme sale, ma méthode de peinture entre en jeu. Mais après le copyArea donc il y a clignotant –

+0

Thanx. Cela a fonctionné comme un charme. Les deux JViewport.BACKINGSTORE_SCROLL_MODE et JViewport.SIMPLE_SCROLL_MODE fonctionnent comme je le veux. –

Questions connexes