2014-12-07 62 views
0

基本上,我從BufferedImages中實時提取視頻圖像,並在處理後在JFrame中顯示它們。不幸的是,我對swing的處理非常糟糕,所以當圖像按照預期顯示在JFrame中時,它會爲每個新圖像產生一個新的JFrame(每秒24個)。訪問BufferedImages以更新JFrame組件

我送BufferedImages到GUI用:

UserInterface.main(currentFrame); 

,他們是由我的GUI類,它本質上是一個包含一個JFrame裏面一個JPanel裏面的當前圖像的JLabel接受:

public class UserInterface extends JFrame { 
private JPanel contentPane; 

public static void main(BufferedImage inputImage) throws IOException 
{ 
    UserInterface frame = new UserInterface(inputImage); 
    frame.setVisible(true); 
} 

public UserInterface(BufferedImage inputImage) throws IOException 
{  
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
    setBounds(50, 50, 1024, 768); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    setContentPane(contentPane); 
    contentPane.setLayout(null); 

    JLabel imageLabel = new JLabel(new ImageIcon(inputImage)); 
    add(imageLabel); 
    imageLabel.setBounds(11, 60, 480, 360); 
    contentPane.add(imageLabel);   
} 

任何人都可以建議如何打破這一點,使1只JFrame出現,其中我可以動態顯示所有圖像?

+0

'contentPane.setLayout(null);'Java GUI必須在不同的操作系統上工作',屏幕大小,屏幕分辨率等。因此,它們不利於像素的完美佈局。請使用佈局管理器或[它們的組合](http://stackoverflow.com/a/5630271/418556)以及[white space]的佈局填充和邊框(http://stackoverflow.com/a/17874718/ 418556)。 – 2014-12-07 03:36:06

回答

1

你應該重構imageLabel是的UserInterface一類成員,並更新其後盾ImageIcon每一幀。但是,這可能太慢,在這種情況下,您需要創建自己的面板類,該面板類會覆蓋paintComponent(Graphics)以繪製幀圖像。最後,您應該通過調用paintImmediately(getBounds())手動觸發該面板的重繪。大意如下的東西應該工作:

public class VideoPanel extends JPanel { 
    private BufferedImage frame; 

    public VideoPanel() { 

    } 

    public void setFrame(BufferedImage image) { 
     this.frame = image; 
     paintImmediately(getBounds()); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if(frame == null) return; 
     int width = frame.getWidth(); 
     int height = frame.getHeight(); 
     Dimension boundary = getSize(); 
     // Scale image dimensions with aspect ratio to fit inside the panel 
     int bwidth; 
     int bheight = ((bwidth = boundary.width) * height)/width; 
     if (bheight > boundary.height) { 
      bwidth = ((bheight = boundary.height) * width)/height; 
     } 
     // Center it in the space given 
     int x = Math.abs(boundary.width - bwidth)/2; 
     int y = Math.abs(boundary.height - bheight)/2; 
     g.drawImage(frame, x, y, bwidth, bheight, null); 
    } 
} 

您也可能會希望你吸取之前,以防止渲染的人工清除面板的背景。

+0

您的paintComponent方法打破了繪畫鏈。 – 2014-12-07 02:26:49

+0

@HovercraftFullOfEels我已經更新了我的答案,包括一個超級調用paintComponent。我的(也許是沒有根據的)不包括它的邏輯是,視頻面板可能永遠不會有孩子,並且自己清除畫布(使用fillRect)比委託給super.paintComponent快很多。 – Xyene 2014-12-07 02:34:28

+0

@Nox'paintComponent'繪製背景,但未清除「Graphics」上下文可能會導致出現其他繪製僞像,這是您並不真正需要的。 *「並自己清除畫布(使用fillRect)比委託給super.paintComponent快很多」* - 您是否有指標,因爲基本上這就是'super.paintComponent',默認情況下, – MadProgrammer 2014-12-07 02:42:25