0

I have made a program in Java, that uses JSoup to download an image from the internet, given a link, and saves it into a specific folder in my computer, upon the pressing of a button in the gui. Please note, the URL input is not necessarily the URL of the image itself, but of an HTML webpage containing the image. What I want to do next is to display that image on the screen. The problem is, I can't simply create an ImageIcon object preemptively, because the image file doesn't exist in the system yet in compile time.

Panel Class

public class AdditionPanel extends JPanel
{

    // ...
    static JTextPane textpane;
    JLabel paneInstructions;
    JButton linkOk;

    public AdditionPanel() throws IOException
    {

        textpane = new JTextPane();         
        paneInstructions = new JLabel("Paste the link here:");
        linkOk = new JButton(" OK ");

        // ...

        linkOk.addActionListener(new LinkOkPressed());

        // ...

        this.add(textpane);
        this.add(paneInstructions);
        this.add(linkOk);
    }
}

Action Listener

public class LinkOkPressed implements ActionListener
{
    JLabel test;
    @Override
    public void actionPerformed(ActionEvent e)
    {
        // ImageDownloader is a class I have created, that simply saves the image
        // from the given URL in a predetermined directory
        ImageDownloader.saveImage(ImageDownloader.getImageUrl(AdditionPanel.textpane.getText()));
        ImageIcon poster = new ImageIcon(getClass().getResource("/resources/imgtest.jpg"));
        test= new JLabel(poster);
        AdditionPanel.add(test);
    } 
}

So now I am trying to use SwingWorker to try to access the file only after the button has been pressed, and thus the file has been downloaded. This is what I have so far:

SwingWorker Class

public class SaveAndDisplay extends javax.swing.SwingWorker<Void, Void>
{

    private AdditionPanel additionPanel;

    public SaveAndDisplay(AdditionPanel addPanel)
    {
        additionPanel = addPanel;
    }

    @Override
    protected Void doInBackground() throws Exception
    {
        ImageDownloader.saveImage(ImageDownloader.getImageUrl(AdditionPanel.textpane.getText()));
        // Wait until the image is saved.

        return null;
    }

    @Override
    protected void done()
    {
        // The following line causes a "NullPointerException"           
        javax.swing.ImageIcon poster = new javax.swing.ImageIcon(LinkOkPressed.class.getResource("/resources/imgtest.jpg"));
        javax.swing.JLabel test= new javax.swing.JLabel(poster);
        test.setBounds(270, 70, 300, 250);
        additionPanel.add(test);
    }
}

The class above causes an exception when executed. Unfortunately, I am not very familiar with SwingWorker, and I have been stuck here for a while. Any help will be appreciated.

DimK
  • 301
  • 4
  • 16
  • Please read "How to create a [mcve]". Then use the [edit] link to improve your question (do not add more information via comments). Otherwise we are not able to answer your question and help you. You pasted quite a bit of code, but what is the actual problem your code results in? – GhostCat Mar 24 '19 at 17:48
  • @GhostCat Thanks for replying. I tried to improve my question. Please have a look and see if it is acceptable now. – DimK Mar 24 '19 at 17:57
  • 1
    You have not posted a valid [mcve] as we still cannot compile or run your code. Some comments however: 1) you state that an exception occurs, but you provide no information on what exception nor where it is thrown, two key bits of information that is necessary to understand your exact problem. 2) You should not be using `setBounds(...)` or null layouts. 3) Your `additionPanel` variable is never initialized in the code you've posted, and so it looks to be at high risk for throwing a NullPointerException. – Hovercraft Full Of Eels Mar 24 '19 at 18:16
  • 1
    4) You've have made some fields static that most definitely shouldn't be static, such as your `static JTextPane textpane`, and this suggests that you've got program design issues. 5) Are you reading an image from URL to disk and then from disk to program? If so why? Why not read from URL directly into program? You can still write to disk, but this way is more efficient than what you're doing – Hovercraft Full Of Eels Mar 24 '19 at 18:19
  • 1
    For instance, why not have your `ImageDownloader.saveImage(...)` method write the image to disk and also ***return*** the image obtained. Your SwingWorker could then be declared a `SwingWorker` and it could return the image obtained from within the `doInBackground()` method, and then retrieve it from within the `done()` method by calling `get()`. Note that `get()` should *always* be called on a worker, often from within the `done()` method, if only to capture and handle any exceptions that might occur from the background thread. – Hovercraft Full Of Eels Mar 24 '19 at 18:24
  • @HovercraftFullOfEels Thanks for the observations! 1) I have already done exactly that in a comment in the SwingWorker Class 2) I'd be very happy to discuss Swing practices after figuring out this problem 3) Is it not initialized by the class' constructor? 4) All the static fields are that way because they created errors. I don't know why, I'm sorry! 5) I want the image to be saved, so that it can be loaded and displayed again in the future by the program – DimK Mar 24 '19 at 18:31
  • @HovercraftFullOfEels This is a small fraction of my program, so I can't post enough code for it to be runnable without pasting 15 classes. Why don't you go ahead and compile your comments into an answer, so that we can discuss more easily? Again, thanks for the help! – DimK Mar 24 '19 at 18:32
  • 3) yes, it may be. Didn't see that. 4) which means that you don't yet understand fully the concept of static and instance, and should know this before doing complex GUI work. You're trying to access the offending fields in a static way -- off of the class and not the instance, and you're fixing things ***backwards*** -- making fields static when you should be accessing them from the instance. – Hovercraft Full Of Eels Mar 24 '19 at 18:37
  • And I'll be happy to post an answer when the question is in fact answerable. Again please create and post a valid [mcve]. And you still haven't told us what exception you're getting. Please focus the question and the code. – Hovercraft Full Of Eels Mar 24 '19 at 18:38
  • 1
    Possible duplicate of [*To display an image*](https://stackoverflow.com/q/4530428/230513); complete examples may be found among the answers. – trashgod Mar 24 '19 at 18:48
  • @trashgod: you could Mjölnir the question, no? – Hovercraft Full Of Eels Mar 24 '19 at 18:55
  • @trashgod: also, I up-voted your answer to that question long ago, but I would recommend updating it so that you remove the `icon` field from your Worker class and instead obtain the Icon object within `done()` by calling `get()` on the worker after completion. This way your code can handle worker exceptions. – Hovercraft Full Of Eels Mar 24 '19 at 18:58
  • @HovercraftFullOfEels: I defer to you; I think the _real_ problem is having no place to put the loaded image; I smell a null layout; instead, I'd look at storing the images some place accessible to a list or table renderer. – trashgod Mar 24 '19 at 19:01
  • @trashgod: or a JLabel initialized without an Icon, thus with a preferred size of 0,0. If this were the case, I sometimes create an empty ImageIcon of size big enough to display the images of interest, and then put this within a JScrollPane. – Hovercraft Full Of Eels Mar 24 '19 at 19:06
  • @trashgod Thanks for the comments. I tried to adjust your answer from the other question to my problem, and now it does not throw an exception, nor does it display the image, though. I also noticed that calling the function `icon.getIconHeight()` from within `done()` causes a `NullPointerException`. – DimK Mar 24 '19 at 19:12
  • @HovercraftFullOfEels I appreciate the patience. Unfortunately, I can't find a way to post an example that is both minimal and complete (perhaps an Austrian could prove that none such exists). If you have any more feedback on the current situation, I'd be thankful. Otherwise, I'll try to express the problem differently in another question in the future. – DimK Mar 24 '19 at 19:17
  • Your posting too much unrelated code, meaning you still have work to do to isolate where the problem is occurring and only post that code (plus additional code needed to compile and run). – Hovercraft Full Of Eels Mar 24 '19 at 19:20
  • 1
    @DimK: The updated [example](https://stackoverflow.com/a/4530659/230513) simply resizes the frame; HovercraftFullOfEels' idea of updating a scroll pane's content may be more practical. In either case a [mcve] will allow you to study the problem in isolation be fore attacking it in your application. – trashgod Mar 25 '19 at 02:10

0 Answers0