2009-08-08 13 views
5

Niedawno kupiłem książkę Filthy Rich Clients i uznałem ją za naprawdę użyteczną i zabawną. Opierając się na jednym przykładzie z książki, próbowałem implementować niestandardowy ScrollPane, który wyświetla "cień" w dolnej części swojego widoku na wyświetlanym komponencie. Skończyłem z kodem poniżej. Działa, ale nie idealnie. Zwłaszcza gdy przewijam okienko przeciągając pasek przewijania, wszystko działa poprawnie, a obraz jest naprawdę gładki. Ale kiedy przewijam za pomocą myszki, cień migocze i nie mam pojęcia dlaczego. Czy ktoś może mi pomóc?Jak wyłączyć domyślne zachowanie malowania zdarzeń przewijania kół na JScrollPane

EDYCJA: To samo dzieje się dla każdego składnika w panelu przewijania. Edytowano kod, aby wyświetlić dwie ramki, aby zobaczyć problem.

EDIT 2: Wyodrębniono problem w taki sposób, w jaki okienko przewijania obsługuje zdarzenie kółka myszy. Podczas przewijania okienka przewijania kopiuje zawartość portu widoku nieco w górę lub w dół w zależności od orientacji przewijania, a następnie rysuje region, który pojawia się w widoku. Mój kod sprawia, że ​​cały komponent jest "brudny", ale to jest po tym, jak komponent przestawił zawartość. Natychmiast widzisz, że gradient "cień" jest nie na miejscu, dopóki nie zostanie odmalowane. Wszelkie pomysły na wyłączenie tej funkcji?

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

zobacz mój post http://stackoverflow.com/questions/8197261/jtable-how-to-change-background-color, dzięki za wspaniałe pytanie +1 – mKorbel

Odpowiedz

3

Czy Próbowaliśmy dzwonić setWheelScrollingEnabled (false) na obiekcie ScrollPane?

Z javadoc:

włącza/wyłącza przewijania odpowiedzi na ruch myszy koła. Przewijanie kół jest domyślnie włączone przez .

Aktualizacja po komentarzu przez Savvas poniżej.

Być może pomoże Ci metoda "setScrollMode (int)" w oknie roboczym. Ta metoda określi, w jaki sposób swing przewija widok.

Możesz otrzymać rzutnię bezpośrednio z ScrollPane za pomocą metody getViewPort(). Dostępne są następujące opcje:

BLIT_SCROLL_MODE 
BACKINGSTORE_SCROLL_MODE 
SIMPLE_SCROLL_MODE 

Według javadoc BLIT_SCROLL_MODE użyje Graphics.copyArea więc może spróbować jednego z pozostałych.

+0

chcę zachować zachowanie przewijania. To, czego nie chcę, to zachować sposób, w jaki okienko przewija się samo podczas przewijania. Nie używa ona najwyraźniej metody repaint, ale używa metody Graphics.copyArea (x, y, width, height, dx, dy). Następnie odmalowuje się nowo malowany obszar, a ponieważ oznaczyłem cały komponent jako zabrudzony, moja metoda malowania wciąga się. Ale po kopii to tak, że miga –

+0

Thanx. To działało jak urok. Zarówno JViewport.BACKINGSTORE_SCROLL_MODE, jak i JViewport.SIMPLE_SCROLL_MODE działają tak, jak chcę. –

Powiązane problemy