簡體   English   中英

如何在 Swing 中加載背景圖像而不在頂部隱藏組件

[英]How to load a background image without hiding components on top in Swing

我有一個JPanel ,其中包含一些顯示一些信息的JLabel 我使用另一個 JLabel 來保存我將從 URL 獲得的背景圖像。 我已經使用GirdBagLayout來設置它,這就是我所擁有的。

來自 alux.com 頻道的 Youtube 視頻

現在我遇到的問題是:由於圖像是高分辨率的,因此加載需要時間,因此應用程序似乎很慢。

    vidThumbnailIcon = new ImageIcon(ImageIO.read(imageURL)) ////http link
    thumbnailLabel.setIcon(vidThumbnailIcon);

我試圖將前面的代碼行放在不同的線程中,但是由於它稍后加載,它確實會覆蓋先前插入的JLabels這意味着所有其他組件都消失了。 我也嘗試過使用繪畫方法,比如

 @Override
protected void paintComponent(Graphics g){
    super.paintComponent(g);
    g.drawImage(vidThumbnailIcon.getImage(), 0, 0, this.getWidth(),this.getHeight(), null);
}

並沒有成功繪制JPanel的背景。

我發現的唯一方法是先獲取圖像,將圖像加載到背景,然后在頂部添加其他組件。 但它太慢了,受我網速慢的限制。 有沒有其他選擇? 意思是稍后加載圖像但仍然沒有隱藏其他所有內容。

編碼

public class VideoDetailsView extends JPanel{

    private ImageIcon vidThumbnailIcon;
    private Video video;
    public VideoDetailsView(Video video){
        this.video = video;
        try{
            var imageLink = new URL(video.thumbnailLink);
            vidThumbnailIcon = new ImageIcon(ImageIO.read(imageLink));
        } catch (MalformedURLException ex) {
            vidThumbnailIcon = new ImageIcon("assets/icons/default_thumbnail.png");
        } catch (Exception ex) { 
            vidThumbnailIcon = new ImageIcon("assets/icons/default_thumbnail.png");
        }
        initGUIComponents();
    }

    private void initGUIComponents() {
        var vidTitleLabel = new JLabel(video.title);
        CustomComponent.customizeLabel(vidTitleLabel, 4);
        var vidViewsLabel = new JLabel(video.viewCount);
        CustomComponent.customizeLabel(vidViewsLabel, 1);
        var vidChannelLabel = new JLabel(video.channel);
        CustomComponent.customizeLabel(vidChannelLabel, 1);
        var vidDateLabel = new JLabel(video.releaseDate);
        CustomComponent.customizeLabel(vidDateLabel, 1);
        var vidDurationLabel = new JLabel(video.duration);
        CustomComponent.customizeLabel(vidDurationLabel, 1);
        var vidCommentsLabel = new JLabel(video.commentCount);
        CustomComponent.customizeLabel(vidCommentsLabel, 1);
        
        var layout = new GridBagLayout();    
        var gbc = new GridBagConstraints();
        setLayout(layout);
   
        gbc.weighty = 1;
        gbc.anchor = GridBagConstraints.WEST;
        addComponent(vidViewsLabel, this, layout,gbc, 0,0,1,1);
        addComponent(vidCommentsLabel, this, layout, gbc, 0,1,1,1);
        addComponent(vidChannelLabel, this, layout,gbc, 0,2,1,1);
        addComponent(vidDateLabel, this, layout,gbc, 0,3,1,1);
        addComponent(vidDurationLabel, this, layout,gbc, 0,4,1,1);
        gbc.weightx = 1;
        addComponent(vidTitleLabel, this, layout,gbc, 0,6,2,2);
        
    }
   public void addComponent(JComponent component, Container container,
            GridBagLayout layout, GridBagConstraints gbc,
            int gridx, int gridy,
            int gridwidth, int gridheight ){
            gbc.gridx = gridx;
            gbc.gridy = gridy;
            gbc.gridwidth = gridwidth;
            gbc.gridheight = gridheight;
            container.add(component,gbc);
    }
    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(vidThumbnailIcon.getImage(), 0, 0, this.getWidth(),this.getHeight(), null);
    }
}

在垃圾神和 camickr 建議的幫助下,

[1]: https://stackoverflow.com/a/25043676/230513這就是我的處理方式。

  1. 將所有文本持有者 JLabels 添加到 JPanel
  2. 將paintComponent方法寫為:
    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(vidThumbnailIcon.getImage(), 0, 0,componentToPaint.getWidth(),componenttoPaint.getHeight(), componentToPaint);
    }
  1. 使用任何多線程技術(例如 SwingWorker 或任何其他技術)啟動一個新線程以從 URL 下載圖像。 並在那里執行下載,然后在結束之前調用repaint()
public void run() {
        try{
                    var imageURL = new URL(thumbnailURL);
                    vidThumbnailIcon = new ImageIcon(ImageIO.read(imageURL));  
                } catch (MalformedURLException ex) {
                    vidThumbnailIcon = new ImageIcon("assets/icons/default_thumbnail.png");
                } catch (Exception ex) {
                    
                    vidThumbnailIcon = new ImageIcon("assets/icons/default_thumbnail.png");
                }
        repaint();///this helps display the image right after the downloading has ended
    }
  1. 最后在 GUI 設置后調用這個線程 object
     initGUIComponents(); loadThumbnail(); ///In this method, you create a thread, use it to load the image and then call repaint() inside here.

我不確定這是最好的方法,但至少它對我有用。 感謝家人的支持

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM