2012-04-10 34 views
8

Tôi muốn sử dụng một ScrollPane để hiển thị một hình ảnh trong Viewport của nó, và cũng có một lớp phủ (hoặc hộp, hoặc bất kỳ loại khác của đăng ký/đánh dấu vị trí) lớp phủ trên hình ảnh. Tôi cần lớp phủ để duy trì cố định khi cuộn (có nghĩa là hình ảnh dường như di chuyển "dưới" lớp phủ). Tôi sẽ cuộn Chế độ xem trong Chế độ xem ở mức cố định để cung cấp chuyển động mượt mà và lớp phủ là cung cấp tham chiếu đến một vị trí nhất định trong Chế độ xem. Về mặt khái niệm, hãy nghĩ về một bản đồ cuộn lớn trong khung nhìn và khung nhìn có hình chữ nhật không di chuyển (tương ứng với chính bản thân Viewport) đánh dấu một vùng có thể được phóng to dựa trên hành động của người dùng.Java: Làm cách nào để vẽ lớp phủ không cuộn trên Khung nhìn ScrollPane?

Tôi đoán (nhưng chưa được xác nhận) rằng việc triển khai ScrollPane xử lý hiển thị một cách hiệu quả (từ cửa hàng sao lưu, không phải vẽ lại toàn bộ Chế độ xem (hoặc thậm chí ViewPort) cho mỗi lần hiển thị từng phần mới) không cần phải ghi đè lên phương thức paint().

Tôi đã xem xét LayerPane và trong khi không làm chủ được nó, có vẻ như đây là phương pháp tiếp cận vũ lực. ScrollPane là một thành phần của một SplitPane và sẽ được di chuyển/thay đổi kích thước. Tôi hy vọng rằng tôi sẽ phải tự duy trì mối quan hệ chính xác giữa ViewPort và LayerPane bằng cách sử dụng định vị tuyệt đối. Tôi xa một chuyên gia về thiết kế GUI thực hiện & và tôi chắc chắn rằng tôi thiếu khả năng từ rõ ràng đến tối nghĩa và thanh lịch mà một người có kinh nghiệm sẽ biết.

Tôi đang mở cho bất kỳ đề xuất nào, không chỉ là đường dẫn tôi đã bắt đầu. Tôi có nên (tôi có thể) thêm một JPanel như một thành phần trong SplitPane của tôi, sau đó thêm một LayerPane để có chứa ScrollPane của tôi và lớp phủ (một JPanel) trên các lớp khác nhau trên LayerPane? Có chức năng nào trong ScrollPane để hỗ trợ điều này trực tiếp không? Tôi đã xem Hướng dẫn Java Swing và tài liệu API nhưng chưa thấy bất kỳ điều gì.

Cảm ơn.

UPDATE:

Cảm ơn bạn đã liên kết, trashgod. Điều này dễ hơn tôi tưởng. Không cần LayerPane, GlassPane, xor-based compositing ... Tôi không biết tại sao nó không xảy ra với tôi để cố gắng ghi đè JViewport.paint() để vẽ lớp phủ của mình - nhưng với mã bên dưới, tôi đã xác thực khái niệm sẽ cho tôi những gì tôi đang tìm kiếm. Chỉ cần sử dụng phân lớp của JViewport và nó làm những gì tôi muốn (trong trường hợp này phủ một hình chữ nhật ở trung tâm của Viewport trong khi hình ảnh cuộn bên dưới). Tôi không có chuyên gia về GUI và API Java cực kỳ rộng; Tôi không có ý tưởng làm thế nào các bạn giữ tất cả điều này trong đầu của bạn - nhưng cảm ơn!

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

Xem thêm ['ScrollPanePaint'] (http://stackoverflow.com/a/3518047/230513).Cập nhật: xem thêm [* Ngăn kính *] (http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html#glasspane). Một hoặc cả hai có thể giúp bạn xây dựng một [sscce] (http://sscce.org/). – trashgod

+1

Liên kết đó chỉ là cú huých tôi cần theo đúng hướng. Đã cập nhật câu hỏi với giải pháp. Cảm ơn trashgod. – ags

Trả lời

7

Thông thường, "chương trình Swing nên ghi đè paintComponent() thay vì trọng paint()," như đã đề cập trong Painting in AWT and Swing: The Paint Methods. Dựa trên ScrollPanePaint, vẽ bên dưới nội dung cuộn, ví dụ sau sẽ ghi đè paint() để vẽ trên nội dung cuộn.

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(); 
      } 
     }); 
    } 
} 

Lưu ý: Thiết lập một thành phần đục (ví dụ JTable) như một cái nhìn cho ô cuộn sẽ cho lỗi hình ảnh kỳ lạ, ví dụ như di chuyển các hộp cố định màu xanh khi di chuyển. Sử dụng setOpaque (false) trên thành phần khung nhìn để sửa lỗi đó.

+0

Kudos thành @ags để đề xuất phương pháp này. – trashgod

+0

@mKorbel: Xin lỗi nếu tôi không theo giao thức ở đây. Có một số gợi ý hay câu hỏi mà tôi đã bỏ lỡ? – ags

+0

Tôi chạy qua một số đề cập mơ hồ của paint() so với paintComponent(), nhưng tôi sẽ cần phải làm một số nghiên cứu để hiểu sự khác biệt và khi nào phù hợp. Cảm ơn một lần nữa cho con trỏ. – ags

Các vấn đề liên quan