2017-10-05 20 views
1

我試圖設置一個系統,使用Swing呈現項目的快速列​​表,因爲它的佈局管理器完全適合我的情況。然而,在嘗試使用文本包裝時,我發現演示JFrame中顯示的結果與調用.print/.paint(All)時得到的結果不同。爲什麼JFrame的輸出與.paint方法不同,以及如何解決這個問題?

這是一個最小的,完整的,並且可驗證例如:

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

public class TextWrapTest { 

    public static void main(String[] args) throws IOException { 
     final JPanel panel = new JPanel(new GridBagLayout()); 
     final GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.gridy = 0; 
     gbc.weightx = 1; 
     gbc.fill = GridBagConstraints.HORIZONTAL; 

     panel.add(new JLabel("<html>This is a piece of text."), gbc); 
     gbc.gridy++; 
     panel.add(new JLabel("<html>This is a very long piece of text that needs to be wrapped in order to fit in the frame."), gbc); 
     gbc.gridy++; 
     panel.add(new JLabel("<html>Another piece of text."), gbc); 

     // Output the frame 
     final JFrame frame = new JFrame(); 
     frame.setUndecorated(true); 
     frame.setSize(200, 200); 
     frame.add(panel); 

     frame.setVisible(true); 

     // Output the image 
     final BufferedImage image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_RGB); 
     frame.paintAll(image.getGraphics()); 
     ImageIO.write(image, "png", new File("output.png")); 
    } 

} 

JFrame中:https://i.stack.imgur.com/zbTPz.png
output.png:https://i.stack.imgur.com/OcM4x.png

正如你所看到的,其結果顯然是不同的,文本拒絕使用.getGraphics()

繪製使用GridBagConstraints,甚至嘗試使用JTextArea的文本包裝,而不是打包無濟於事。

在這個問題上的任何幫助將不勝感激,因爲我不知道如何讓paint方法服從文字環繞。

此致,
倫斯Rikkerink

+0

首先要畫到屏幕上,你應該避免調用'paintAll',堅持'printAll',因爲這會刪除所有的雙緩衝​​和其他一些相關問題 – MadProgrammer

+0

你可以也是在與UI的競爭狀態中變得實現並着色 – MadProgrammer

+0

@MadProgrammer這似乎是問題所在。添加'Thread.sleep(1000);'解決了他的問題 – XtremeBaumer

回答

2

可能有許多原因,但是,我會建議避免paintpaintAll,因爲他們調用API的雙緩衝方面,可能會導致之前的延遲圖像實際上被繪製到Graphics上下文中。相反,我建議使用printAll,因爲它在繪畫時會禁用雙緩衝。

另一個問題可能是框架可能無法在屏幕上實現(或甚至沒有完全繪製)。調用setVisible會調用很多後臺工作,並會調用EDT回調以啓動繪畫過程。在這種情況下,我建議在UI顯示後使用SwingUtilities.invokeLater塊。

這會做一些事情,首先,我可以將任務放置在事件隊列中,在事件隊列創建完成後,但更重要的是,它會同步繪畫,所以你不打架EDT試圖在同一時間

SwingUtilities.invokeLater(new Runnable() { 
    @Override 
    public void run() { 
     final BufferedImage image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_RGB); 
     Graphics2D g2d = image.createGraphics(); 
     frame.paintAll(g2d); 
     g2d.dispose(); 
     ImageIO.write(image, "png", new File("output.png")); 
    } 
}); 
相關問題