[英]How to load a background image without hiding components on top in Swing
I have a JPanel
that holds a few JLabel
that display some informations.我有一个JPanel
,其中包含一些显示一些信息的JLabel
。 And i use another JLabel to hold a background image that I'm going to get from a URL.我使用另一个 JLabel 来保存我将从 URL 获得的背景图像。 I have used GirdBagLayout
to set this up and this is what I have.我已经使用GirdBagLayout
来设置它,这就是我所拥有的。
Now The issue i have is this : Since the image if of high resolution, it takes time to load hence the app seems slow.现在我遇到的问题是:由于图像是高分辨率的,因此加载需要时间,因此应用程序似乎很慢。
vidThumbnailIcon = new ImageIcon(ImageIO.read(imageURL)) ////http link
thumbnailLabel.setIcon(vidThumbnailIcon);
I have tried to put the previous lines of code in a different thread but, since it loads later, it does paint over the previously inserted JLabels
That means all other components disappear.我试图将前面的代码行放在不同的线程中,但是由于它稍后加载,它确实会覆盖先前插入的JLabels
这意味着所有其他组件都消失了。 I also tried using the paint method like我也尝试过使用绘画方法,比如
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(vidThumbnailIcon.getImage(), 0, 0, this.getWidth(),this.getHeight(), null);
}
and paint the background of the JPanel with no success.并没有成功绘制JPanel的背景。
The only way i have found is to get the image first, load the image to the background, and then add other components on top.我发现的唯一方法是先获取图像,将图像加载到背景,然后在顶部添加其他组件。 But it's too slow, limited by my slow internet.但它太慢了,受我网速慢的限制。 Is there any alternative to this?有没有其他选择? Meaning, loading the image later but still not hiding everything else.意思是稍后加载图像但仍然没有隐藏其他所有内容。
The code编码
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);
}
}
With the help suggested from trashgod and camickr,在垃圾神和 camickr 建议的帮助下,
[1]: https://stackoverflow.com/a/25043676/230513 this is how i have proceded. [1]: https://stackoverflow.com/a/25043676/230513这就是我的处理方式。
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(vidThumbnailIcon.getImage(), 0, 0,componentToPaint.getWidth(),componenttoPaint.getHeight(), componentToPaint);
}
repaint()
.并在那里执行下载,然后在结束之前调用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
}
initGUIComponents(); loadThumbnail(); ///In this method, you create a thread, use it to load the image and then call repaint() inside here.
I'm not sure this is the best way to do it but atleast it worked for me.我不确定这是最好的方法,但至少它对我有用。 Thank family for the support感谢家人的支持
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.