2011-09-04 21 views
12

我想在JFrame的內容窗格中顯示大圖像。我想讓圖像或內容面板可以滾動,因爲圖像很大。我試圖用Jscrollpane來做,並將其添加到內容窗格中,但它不起作用。有沒有尋找解決方案,但最終沒有找到一個。有人可以指導我嗎?我的代碼都低於使圖像在JFrame內容窗格中滾動

FinalEnvironment.java

package environment; 

import java.awt.*; 
import java.net.URL; 

import javax.swing.*; 

public class FinalEnvironment{ 

public FinalEnvironment(){ 

    Image Eastlake; 
    URL EastlakeURL = null; 

    EastlakeURL = FinalEnvironment.class.getResource("/image1/eastlake_night.png"); 
    Eastlake = Toolkit.getDefaultToolkit().getImage(EastlakeURL); 

    JFrame frame = new JFrame("UniCat World"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(800, 600); 
    frame.setResizable(false); 
    frame.setLocationRelativeTo(null); 

    JMenuBar yellowMenuBar = new JMenuBar(); 
    Map map = new Map(800, 550, Eastlake); 
    yellowMenuBar.setOpaque(true); 
    yellowMenuBar.setBackground(Color.YELLOW); 
    yellowMenuBar.setPreferredSize(new Dimension(800, 50)); 
    frame.setJMenuBar(yellowMenuBar); 
    JScrollPane scroller = new JScrollPane(map); 
    scroller.setAutoscrolls(true); 
    scroller.setPreferredSize(new Dimension(800, 550)); 
    frame.getContentPane().add(scroller, BorderLayout.CENTER); 


    frame.setSize(800, 600); 
    frame.setVisible(true); 
} 

public static void main(String[] args){ 
    FinalEnvironment fe = new FinalEnvironment(); 
} 
} 

這裏是我的map.java

package environment; 

import java.awt.*; 

import javax.swing.*; 


public class Map extends JPanel{ 

    private int width; 
    private int height; 
    private Image img; 

    public Map(int width, int height, Image img){ 

     this.width = width; 
     this.height = height; 
     this.img = img; 
    } 

    protected void paintComponent(Graphics g) 
    { 
     super.paintComponents(g); 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.drawImage(img,0,0,2624,1696,null); 
    } 

} 

最後,我想向Jbuttons中對這個圖像的頂部。我應該調用一個Rectangle並將它放在contentpane中的圖像的頂部,然後使用Point來定位我的按鈕,或者我應該直接使用圖像或組件本身來執行它?我需要該按鈕能夠與圖像同步,而不是在內容窗格中進行靜態滾動。

感謝

+2

這是功課嗎? – Boro

+0

不是,它是我嘗試在我的項目中編碼的許多事情之一。 – Noble

+0

嘗試我爲自己建議的內容。那麼如果你還有一些問題,我可以發佈代碼示例。 – Boro

回答

14

我會做什麼在這裏:

1.Have面板(畫布)僅職責是畫給定的圖像獨立於真實圖像尺寸的覆蓋方法paintComponent()

super.paintComponent(g); 
    g.drawImage(image, 0, 0, null); 

2.確保畫布首選大小等於圖像實際大小。

3.有第二個面板作爲一個框架的內容窗格。

4.在它中,您將設置一個JScrollPane作爲其中心。

5.In滾動窗格視口將會從步驟1

組件6.增加的按鈕,畫布面板從步驟1將與圖像一起滾動。

7.將內容窗格(步驟3中的面板)添加到框架中,然後運行應用程序。

編輯: 帶按鈕的代碼示例添加到畫布上,它總是保持原位,與滾動位置或框架大小無關。

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.net.URL; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.imageio.ImageIO; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.SwingUtilities; 

public class ScrollImageTest extends JPanel { 
    private static final long serialVersionUID = 1L; 
    private BufferedImage image; 
    private JPanel canvas; 

    public ScrollImageTest() { 
     try { 
      this.image = ImageIO.read(new URL("http://interviewpenguin.com/wp-content/uploads/2011/06/java-programmers-brain.jpg")); 
     }catch(IOException ex) { 
      Logger.getLogger(ScrollImageTest.class.getName()).log(Level.SEVERE, null, ex); 
     } 

     this.canvas = new JPanel() { 
      private static final long serialVersionUID = 1L; 
      @Override 
      protected void paintComponent(Graphics g) { 
       super.paintComponent(g); 
       g.drawImage(image, 0, 0, null); 
      } 
     }; 
     canvas.add(new JButton("Currently I do nothing")); 
     canvas.setPreferredSize(new Dimension(image.getWidth(), image.getHeight())); 
     JScrollPane sp = new JScrollPane(canvas); 
     setLayout(new BorderLayout()); 
     add(sp, BorderLayout.CENTER); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JPanel p = new ScrollImageTest(); 
       JFrame f = new JFrame(); 
       f.setContentPane(p); 
       f.setSize(400, 300); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 
+0

我現在可以使圖像滾動。謝謝!仍然在按鈕上工作。如果我遇到問題,將在此處或在此主題中發佈評論。謝謝! – Noble

+0

@Noble樂意幫忙。嘗試將按鈕添加到畫布上,例如在您的「地圖」中。 'map.add(new JButton(「OK」));'如果我理解與圖像同步正確,它應該按照你的需要工作。我想隨着它的移動而移動,對吧? – Boro

+2

@Noble:如果您的程序面臨新問題,需要我們的幫助,那麼最好的辦法就是在SO上提出一個新問題。如果需要,您可以鏈接到此問題,但爲新問題創建新問題將增加您獲得及時幫助的機會。 –

5

如果使用尺寸來設置地圖的首選尺寸,該怎麼辦?例如,給地圖這個方法:

// method in the Map class 
@Override 
public Dimension getPreferredSize() { 
    return new Dimension(width, height); 
} 

這樣的地圖的JPanel將採取了必要的空間來顯示整個圖像。另外,爲什麼paintComponent方法中的drawImage方法具有大的數字magic?爲什麼不使用那裏的寬度和高度呢? 編輯1:或甚至沒有指定圖像的大小,正如Boro在他的回答中所建議的(1+對他)。

+0

嗨@Hovercraft全鰻我認爲你所建議的應該做到這一點。或者在構造函數中,他可以使用'setPreferredSize(...)'而不是覆蓋它。無論如何,在重新讀取代碼之後,OP的真正問題在於'setPreferredSize()'方法不適用於進入'ScrollPane'的面板。相反,我發現它設置爲'ScrollPane',在這種情況下它是不必要的,因爲它被設置爲邊界佈局的中心,並且忽略了組件的寬度和高度。 – Boro

+0

雅,我改變了我的代碼,不指定像Boro建議的圖像大小。大的魔法數字實際上是由我進行測試的硬編碼。 – Noble

3

除了其他有用的答案之外,您可能還希望學習使用鼠標手勢滾動任意內容的example

+0

+1有趣。起初我以爲這是模仿智能手機滾動(即拖動)的東西。順便說一句,你知道這種模仿手機行爲的API嗎? – Boro

+0

@Boro:對不起,沒有。 – trashgod

5

爲什麼每個人都在重新發明輪子?不需要自定義面板來繪製圖像!

所有你需要做的就是創建一個JLabel並添加一個ImageIcon到標籤,你不會有問題。該標籤將:

  1. 以(0,0)原始大小(這正是自定義代碼所做的)繪製圖像。

  2. 根據圖像大小確定圖像的首選大小。現在滾動將自動發生。

而且很少有任何理由使用了setPreferredSize()方法,因爲所有組件具有默認優選尺寸。所以你不應該設置菜單欄的默認大小。我設置首選大小的唯一時間是在JScrollPane上。這將允許框架以合理的尺寸打包,然後滾動條將根據標籤中圖像的大小自動出現。

+1

好點。在一個自定義組件中,是否有理由優先重寫'getPreferredSize()'與調用'getPreferredSize()'? – trashgod

+1

在自定義組件中,您應該始終重寫getPreferredSize(),因爲隨着組件屬性更改,大小可能會動態更改。 – camickr

+0

ImageIcon似乎有一個相當低的維度限制,似乎甚至依賴於平臺。在Win 10下,我可以將32768x400 RGB圖像顯示爲嵌入在JLabel中的ImageIcon,在Ubuntu 16.10下,最大寬度似乎在16384和32768之間。很酷的是,這不會引發錯誤,您將開始搜索..... – user1050755