I have a JPanel
that holds a few JLabel
that display some informations. And i use another JLabel to hold a background image that I'm going to get from a URL.
I have used GirdBagLayout
to set this up and this is what I have.
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.
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.
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);
}
}
CodePudding user response:
With the help suggested from trashgod and camickr,
[1]: https://stackoverflow.com/a/25043676/230513 this is how i have proceded.
- Add all the text holder JLabels to the JPanel
- write the paintComponent method as:
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(vidThumbnailIcon.getImage(), 0, 0,componentToPaint.getWidth(),componenttoPaint.getHeight(), componentToPaint);
}
- start a new Thread to download the image from URL using any multithreading technique such as SwingWorker or any other. and execute the downloading there then before the end, call
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
}
- finally call this thread object after the GUI set up
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