2009-08-08 4 views
5

Recentemente ho acquistato il libro Filthy Rich Clients e l'ho trovato davvero utile e divertente. Basandomi su un esempio tratto dal libro, ho provato a implementare un ScrollPane personalizzato che visualizza una "ombra" nella parte inferiore della sua vista sul componente da visualizzare. Ho finito con il codice qui sotto. Funziona ma non perfettamente. Nello specifico, quando faccio scorrere il riquadro trascinando la barra di scorrimento, tutto funziona correttamente e il dipinto è davvero scorrevole. Ma quando scorro con il mouse scorro i tremolii dell'ombra e non ho idea del perché. Qualcuno può aiutarmi?Come disattivare il comportamento di pittura predefinito dell'evento di scroll wheel su JScrollPane

MODIFICA: La stessa cosa accade per qualsiasi componente nel riquadro di scorrimento. Modificato il codice per visualizzare due frame per vedere il problema.

MODIFICA 2: Ho isolato il problema relativo al modo in cui il riquadro di scorrimento gestisce l'evento della rotellina del mouse. Quando si scorre il riquadro di scorrimento, il contenuto della porta di visualizzazione viene copiato leggermente verso l'alto o verso il basso in base all'orientamento dello scorrimento e quindi disegna la regione che viene visualizzata. Il mio codice rende l'intero componente "sporco" ma ciò avviene dopo che il componente ha spostato il contenuto. Quindi momentaneamente vedi il gradiente "ombra" fuori posto fino a quando non viene emesso un repaint. Qualche idea su come disabilitare questa funzionalità?

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

vedere il mio post http://stackoverflow.com/questions/8197261/jtable-how-to-change-background-color, grazie per l'ottima domanda +1 – mKorbel

risposta

3

Avete provato a chiamare setWheelScrollingEnabled (false) sull'oggetto ScrollPane?

Dal javadoc:

abilita/disabilita lo scorrimento in risposta al movimento del mouse ruota. Lo scorrimento delle ruote è abilitato per default .

Aggiornamento in seguito al commento di Savvas di seguito.

Forse il metodo "setScrollMode (int)" sul viewport può aiutarti. Questo metodo determinerà il modo in cui l'oscillazione scorre la vista.

È possibile ottenere il viewport direttamente da ScrollPane con il metodo getViewPort(). Sono disponibili le seguenti opzioni:

BLIT_SCROLL_MODE 
BACKINGSTORE_SCROLL_MODE 
SIMPLE_SCROLL_MODE 

Secondo javadoc BLIT_SCROLL_MODE utilizzerà Graphics.copyArea quindi forse provare uno degli altri.

+0

voglio mantenere il comportamento di scorrimento. Quello che non voglio è mantenere il modo in cui il pannello di scorrimento si disegna durante lo scorrimento. Apparentemente non usa il metodo repaint ma usa il metodo Graphics.copyArea (x, y, width, height, dx, dy). Dopo che il ridisegno è stato chiamato per dipingere l'area appena introdotta e poiché ho marcato l'intero componente come sporco, il mio metodo di pittura entra in gioco. Ma dopo il copyArea, quindi, lampeggia il numero –

+0

Grazie. Ha funzionato come un fascino. Sia JViewport.BACKINGSTORE_SCROLL_MODE che JViewport.SIMPLE_SCROLL_MODE funzionano come voglio. –