2012-04-10 42 views
8

我想使用ScrollPane在其視口中顯示圖像,並在圖像上疊加網格(或框或任何其他類型的註冊/位置標記)。我需要覆蓋層在滾動時保持固定(意味着圖像似乎移動到覆蓋層下)。我將以固定速率滾動視口中的視圖以提供平滑的動作,並且疊加層將提供對視口內某個位置的引用。從概念上講,可以考慮在Viewport中滾動的大型地圖,並且Viewport具有一個不移動的矩形(相對於視口本身),該矩形標記可根據某些用戶操作進行縮放的區域。我認爲(但還沒有確認)ScrollPane實現可以有效地處理View的渲染(從後臺存儲,不必爲每個新的部分曝光重新繪製整個View(甚至ViewPort)),所以更喜歡不必重寫paint()方法。Java:如何在ScrollPane視口上繪製非滾動疊加層?

我已經看過LayerPane,雖然沒有掌握它,但似乎這是一種蠻力的方法。 ScrollPane是SplitPane的一個組件,將被移動/調整大小。我期望我必須使用絕對定位手動維護ViewPort和LayerPane之間的正確關係。我遠不是GUI設計專家&的實現,我相信我錯過了一個有經驗的人知道的從明顯到晦澀和優雅的可能性。

我願意接受任何建議,而不僅僅是我開始下的路徑。我應該(我可以)在我的SplitPane中添加一個JPanel作爲一個組件,然後添加一個LayerPane到包含我的ScrollPane和LayerPane上不同圖層上的覆蓋圖(另一個JPanel)? ScrollPane中是否有直接支持這一功能的功能?我已經看過Java Swing教程和API文檔,但還沒有看到任何東西。

謝謝。

UPDATE:

感謝您的鏈接,trashgod。這比我預期的要容易得多。不需要LayerPane,GlassPane,基於xor的合成...我不知道爲什麼我沒有嘗試覆蓋JViewport.paint()來繪製覆蓋圖 - 但是通過下面的代碼,我驗證了這個概念給我我要找的東西。只需使用JViewport的子類,它就可以做我想做的事情(在這種情況下,在視圖中心覆蓋一個矩形,而圖像在下面滾動)。我不是GUI專家,Java API非常寬泛;我不知道你們是如何將這一切都放在你的頭上 - 但是,謝謝!

class MyViewport extends JViewport { 
    @Override 
    public void paint(Graphics g) { 
     super.paint(g); 
     Graphics2D g2 = (Graphics2D)g; 
     g2.setPaint(Color.BLACK); 
     g2.drawRect(getWidth()/4,getHeight()/4,getWidth()/2,getHeight()/2); 
    } 
} 
+2

請參閱['ScrollPanePaint'](http://stackoverflow.com/a/3518047/230513)。更新:另見[*玻璃窗格*](http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html#glasspane)。其中之一或兩者都可以幫助您構建[sscce](http://sscce.org/)。 – trashgod 2012-04-10 18:30:08

+1

該鏈接只是我需要的正確方向的微調。用解決方案更新了問題。感謝垃圾。 – ags 2012-04-10 19:55:28

回答

7

通常情況下, 「Swing程序應該重寫paintComponent(),而不是壓倒一切paint()」,如Painting in AWT and Swing: The Paint Methods提及。基於ScrollPanePaint,其中的滾動內容低於,下面的示例覆蓋paint()以繪製上面的的滾動內容。

ScrollPanePaint

import java.awt.*; 
import javax.swing.*; 

/** 
* @see https://stackoverflow.com/a/10097538/230513 
* @see https://stackoverflow.com/a/2846497/230513 
* @see https://stackoverflow.com/a/3518047/230513 
*/ 
public class ScrollPanePaint extends JFrame { 

    private static final int TILE = 64; 

    public ScrollPanePaint() { 
     JViewport viewport = new MyViewport(); 
     viewport.setView(new MyPanel()); 
     JScrollPane scrollPane = new JScrollPane(); 
     scrollPane.setViewport(viewport); 
     this.add(scrollPane); 
     this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     this.pack(); 
     this.setLocationRelativeTo(null); 
     this.setVisible(true); 
    } 

    private static class MyViewport extends JViewport { 

     public MyViewport() { 
      this.setOpaque(false); 
      this.setPreferredSize(new Dimension(6 * TILE, 6 * TILE)); 
     } 

     @Override 
     public void paint(Graphics g) { 
      super.paint(g); 
      g.setColor(Color.blue); 
      g.fillRect(TILE, TILE, 3 * TILE, 3 * TILE); 
     } 
    } 

    private static class MyPanel extends JPanel { 

     public MyPanel() { 
      this.setOpaque(false); 
      this.setPreferredSize(new Dimension(9 * TILE, 9 * TILE)); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      g.setColor(Color.lightGray); 
      int w = this.getWidth()/TILE + 1; 
      int h = this.getHeight()/TILE + 1; 
      for (int row = 0; row < h; row++) { 
       for (int col = 0; col < w; col++) { 
        if ((row + col) % 2 == 0) { 
         g.fillRect(col * TILE, row * TILE, TILE, TILE); 
        } 
       } 
      } 
     } 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new ScrollPanePaint(); 
      } 
     }); 
    } 
} 

注:設置用作滾動窗格會給奇怪視覺缺陷,例如滾動時移動所述固定藍色方塊的圖的不透明組分(例如JTable)。在視圖組件上使用setOpaque(false)來解決這個問題。

+0

爲了暗示這種方法,可以使用@ags來表示讚賞。 – trashgod 2012-04-10 22:48:07

+0

@mKorbel:對不起,如果我沒有按照協議在這裏。有沒有我錯過的建議或問題? – ags 2012-04-11 19:57:24

+0

我碰到了一些模糊的提及paint()與paintComponent()的問題,但我需要做一些研究來理解差異以及何時適合。再次感謝指針。 – ags 2012-04-11 19:57:56

相關問題