2012-12-13 28 views
4

我試圖將JScrollPane(大於屏幕)的主視口和標題保存爲PNG圖像文件。我創建了3個類擴展JPanel(MainTablePanel,MapsHeaderPanel和ItemsHeaderPanel)並將它們設置爲視口。他們每個人都有這個方法:JScrollPane內容到圖像

public BufferedImage createImage() { 
    BufferedImage bi = new BufferedImage(getSize().width, getSize().height, BufferedImage.TYPE_INT_ARGB); 
    Graphics g = bi.createGraphics(); 
    paint(g); 
    g.dispose(); 
    return bi; 
} 

每個班級也有一個paint方法,其繪製背景,然後調用super.paint()畫一些標籤。例如:

public void paint(Graphics g){ 
     g.setColor(Color.BLACK); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     g.setColor(new Color(255, 255, 0, 50)); 
     // for loop that paints some vertical yellow lines 
     for(int i=0; i<getWidth(); i+=K.mW){ 
      g.fillRect(i-1, 0, 2, getHeight()); 
      if(i%(K.mW*5)==0){ 
       g.fillRect(i-2, 0, 4, getHeight()); 
      } 
     } 
     // called to pain some rotated JLabels 
     super.paint(g); 
    } 

來自外部的JFrame我又試圖將其保存爲PNG文件,使用此代碼:

BufferedImage tableImg = mainTableP.createImage(); 
BufferedImage topImg = mapsHeaderP.createImage(); 
BufferedImage leftImg = itemsHeaderP.createImage(); 

ImageIO.write(tableImg, "png", new File(s.homeDir+"/table.png")); 
ImageIO.write(topImg, "png", new File(s.homeDir+"/top.png")); 
ImageIO.write(leftImg, "png", new File(s.homeDir+"/left.png")); 

這是應用程序運行的截圖:screenshot

而且這是導出的頭文件:top

如果我評論「super.paint(g)」指令,我得到一個正確的圖像(因此沒有所有JLables,cl早)。 看起來像第二個paint(super.paint(g))被繪製到BufferedImage中,並將元素放在它的JPanel之外。有人可以解釋我這種行爲?謝謝。

==========編輯SSCCE ================================= ===

這應該編譯。你可以按原樣執行它,並在c:\中找到兩個圖像(top.png和left.png),它們應該與兩個標題相同。不幸的是,他們不是。背景不繪。此外(特別是如果你看看left.png),你可以看到標籤被塗刷兩次並移位(例如,注意「Left test 21」)。

import java.awt.*; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import javax.imageio.ImageIO; 
import javax.swing.*; 

public class Main { 

    public static void main(String[] args) { 

     JFrame frame = new JFrame(); 
     frame.setLayout(null); 
     frame.setSize(800, 600); 

     JScrollPane scrollP = new JScrollPane(); 
     scrollP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 
     scrollP.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); 

     MyPanel top = new MyPanel(); 
     for(int i=0; i<30; i++){ 
      JLabel label = new JLabel("Test "+i); 
      label.setOpaque(false); 
      label.setBounds(50*i, 40, 50, 20); 
      label.setForeground(Color.GREEN); 
      top.add(label); 
     } 
     top.setLayout(null); 
     top.setOpaque(false); 
     top.setPreferredSize(new Dimension(50*30, 200)); 
     top.validate(); 

     MyPanel left = new MyPanel(); 
     for(int i=0; i<30; i++){ 
      JLabel label = new JLabel("Left test "+i); 
      label.setBounds(0, 50*i, 100, 20); 
      label.setForeground(Color.RED); 
      left.add(label); 
     } 
     left.setLayout(null); 
     left.setOpaque(false); 
     left.setPreferredSize(new Dimension(200, 50*30)); 

     MyPanel center = new MyPanel(); 
     center.setLayout(null); 
     center.setOpaque(false); 
     center.setPreferredSize(new Dimension(50*30, 50*30)); 

     scrollP.setViewportView(center); 
     scrollP.setColumnHeaderView(top); 
     scrollP.setRowHeaderView(left); 

     scrollP.setBounds(0, 50, 750, 500); 
     frame.add(scrollP); 

     frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     frame.setVisible(true); 

     try{ 
      BufferedImage topImg = top.createImage(); 
      ImageIO.write(topImg, "png", new File("C:/top.png")); 

      BufferedImage leftImg = left.createImage(); 
      ImageIO.write(leftImg, "png", new File("C:/left.png")); 
     }catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 


} 

class MyPanel extends JPanel{ 
    public void paint(Graphics g){ 
     g.setColor(Color.BLACK); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     g.setColor(new Color(255, 255, 0, 50)); 
     for(int i=0; i<getWidth(); i+=50){ 
      g.fillRect(i-1, 0, 2, getHeight()); 
     } 
     super.paint(g); // COMMENT this line to obtain background images 
    } 

    public BufferedImage createImage() { 
     BufferedImage bi = new BufferedImage(getSize().width, getSize().height, BufferedImage.TYPE_INT_ARGB); 
     Graphics g = bi.createGraphics(); 
     paint(g); 
     g.dispose(); 
     return bi; 
    } 
} 
+0

如果你調用'super.paint(g);'作爲'paint();'中的第一行呢? –

+0

@Nikolay Kuznetsov可能不是關於視口 – mKorbel

+1

@塞巴斯蒂安Ikaros Rizzo這個問題是不能回答,以更好的幫助更快發佈[SSCCE](http://sscce.org/),短,可運行,編譯 – mKorbel

回答

0

我無法重現的任何異常行爲,但我要猜你忘了遷移的圖像油漆原點(g.translate())來匹配您的期望。另外,爲了安全起見,請勿使用圖像類型ARGB。使用圖像類型RGB。這是完全可能的,你的具體Java實現是怪罪。實施沒有任何合同,只能在子組件上只調用一次油漆。