Hi All,

I have two major problems and they may or may not be linked. My main problem is with an application that I am creating. So far, I have only created the GUI using Netbeans 6.8. When I run the app through Netbeans then everything works fine. However, when I run the jar file through the command line I have problems. The initial image, in the main menu, flickers once and then disappears. If I press the "next image" button, however, the following images stabilize. But if I open up a new window, again, the image flickers, in that new window, and then disappears. The images in the main menu below, however, are still stable. So, it seems to be just an initial reaction. The other strange thing is that the program reacts differently on different machines. On my desktop this is what happens (Windows XP OS). On the university desktop the image in the main menu flickers once and then disappears but the images in the other windows are stable (Windows XP OS). On a laptop with Vista OS all the images are stable but the menus seem to overlap one another. On a laptop with Ubuntu the whole application works fine.
If I add a wait, on my machine, then the image stays there for the duration of the wait. However, I cannot use a wait as the GUI is interactive and the user needs to be able to do things when they want to and not be locked out of the GUI whilst waiting. I also added a -Dsun.java2d.noddraw=true flag, on my machine, which stabilized the images but caused the main menu to minimize to the taskbar when a button, which opened a new window, was pressed. After the new window was disposed of you have to manually restore the main menu window to its position from the taskbar. Which is, of course, totally useless. I struggled to find any posts addressing this issue though I did see posts that said that you should override paintComponent for swing and not paint. I tried doing this however, Netbeans 6.8 gives me the error message "Cannot find symbol: super.paintComponent(java.awt.Graphics) Location:javax.swing.JFrame" And yes, I have imported all the correct packages. So my questions are:

1. Do you have an answer for why the images flicker once and then disappear- and a solution
2. If you think that the problem does lie with paintComponent not being used then how do I get Netbeans to recognize the super.paintComponent(g) command?

I am posting some code to illustrate what I have done:

public void source(Graphics g)
    {
        imageSrc = null;
        try {
             Name(); // Gets the String for the URL
             imageSrc = ((new File(getName())).toURI()).toURL();
             bi = ImageIO.read(imageSrc);
             len = bi.getWidth();
             if (len > 1800.5) temp = 0.08; // works out ratio for scaling image down
             else temp = 0.2;              //   to - images are too large for JPanel 
             g = PhotoPanel.getGraphics();
             Graphics2D g2 = (Graphics2D) g;
             g2.drawImage(bi, AffineTransform.getScaleInstance(temp,temp), null);
        }
        catch (MalformedURLException e) {
        }
        catch (IOException e){}
    }
  
    @Override
    public void paint(Graphics g)
    {
        super.paint(g);
        source(g);
    }

This is really urgent and any help would be greatly appreciated.

Thanks in advance. :)

Recommended Answers

All 13 Replies

That is not a portability issue. You do not simply grab a components graphics and paint to it, as that "painting" will be "removed" the next time the component refreshes. You need to rewrite this "PhotoPanel" class and give it a "setImage(image)" method and then, in that class, override paintComponent to draw the Image. Then you call setImage(image) followed by validate() and/or repaint().

Hi Masijade,

Thanks for answering me. I have tried to implement what you suggested. And I hope that I have done it correctly. I probably haven't though :( as, now, no image is appearing whatsoever. I created a PhotoPanel class like so:

public class PhotoPanel extends javax.swing.JPanel{
    private double len, temp;
    private URL imageSrc;
    private BufferedImage bi;

    public void setImage()
    {
       imageSrc = null;
        try {
             MainMenu GUI = new MainMenu();
             GUI.Name();
             imageSrc = ((new File(GUI.getName())).toURI()).toURL();
             bi = ImageIO.read(imageSrc);
             len = bi.getWidth();
             if (len > 1800.5) temp = 0.08;
             else temp = 0.2;
        } catch (MalformedURLException e) {
        }
        catch (IOException e){}
    }


    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        MainMenu GUI = new MainMenu();
        g = GUI.PhotoPanel.getGraphics();
        Graphics2D g2 = (Graphics2D) g;
        g2.drawImage(bi, AffineTransform.getScaleInstance(temp,temp), null);
    }
}

And then called it from my MainMenu class like so:

@Override
    public void paint(Graphics g)
    {
        super.paint(g);
        PhotoPanel image = new PhotoPanel();
        image.setImage();
        validate();
        repaint();
    }

What am I doing wrong? Thanks again for the help.

Drop lines 27 & 28. That is exactly what I told you not to do.

Also, the setImage method should take an image as an argument, not open any GUI and ask for one. IOW, you should ask for and load the image elsewhere and pass the loaded image to the PhotoPanel.

Okay. So, I have dropped the two lines. And changed the code somewhat. But still nothing:

PhotoPanel class:

public void setImage(BufferedImage bi)
    {
             len = bi.getWidth();
             if (len > 1800.5) temp = 0.08;
             else temp = 0.2;
    }


    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.drawImage(bi, AffineTransform.getScaleInstance(temp,temp), null);
    }

MainMenu Form:

public void Source()
    {
        imageSrc = null;
        try {
             Name();
             imageSrc = ((new File(getName())).toURI()).toURL();
             bi = ImageIO.read(imageSrc);
             PhotoPanel image = new PhotoPanel();
             image.setImage(bi);
            /* len = bi.getWidth();
             if (len > 1800.5) temp = 0.08;
             else temp = 0.2;*/
        } catch (MalformedURLException e) {
        }
        catch (IOException e){}
    }

    @Override
    public void paint(Graphics g)
    {
        super.paint(g);
        Source();
        //PhotoPanel image = new PhotoPanel();
        //image.setImage(bi);
        validate();
        repaint();
    }

I am still a student so please excuse the stupid question but if I don't specify the JPanel "PhotoPanel" for the image to load into how does it get there? As the JPanel "PhotoPanel" is just one of many panels in my GUI.

Thanks again for help.

Well, setImage needs to actually assign the image given to an instance variable, of course. Otherwise, bi, essentially, doesn't exist anymore once the setImage method is finished, of course.

And don't override paint, and definately do call this setImage from within paint or paintComponent.

Here, in pseudo code

class PhotoPanel extends JPanel {
  BufImage bi;

  void setImage(BufImage localBi) {
    // do whatever with localBi
    bi = localBi
  }

  void paintComponent(Graphics g) {
    super.paintComponent(g);
    G2D g2d = (G2D) g;
    g2d.drawImage(...)
  }
}

class main {
  void main() {
    photopanel p = new photopanel();
    displayGui
    askForImageURL
    BufImage bi = loadImageFromURL
    p.setImage(bi);
    p.validate();
    p.repaint();
  }
}

That's all there is to it.

Hi Again. So I tried this out and still no images.

PhotoPanel class:

public class PhotoPanel extends javax.swing.JPanel{
    private double len, temp;
   // private URL imageSrc;
    private BufferedImage bi;

    public void setImage(BufferedImage bi)
    {
             len = bi.getWidth();
             if (len > 1800.5) temp = 0.08;
             else temp = 0.2;
             this.bi = bi;
    }


    
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.drawImage(bi, AffineTransform.getScaleInstance(temp,temp), null);
    }
}

MainMenu Class:

public void Name()
    {
        count++;
        setName("G:\\NetBeansProjectsF\\wmales\\wmale000"+count+"f.JPG");
    }

    public URL Source()
    {
        imageSrc = null;
        try {
             Name();
             imageSrc = ((new File(getName())).toURI()).toURL();
        } catch (MalformedURLException e) {
        }
        catch (IOException e){}
        return imageSrc;
    }
    
    
    public void paint(Graphics g)
    {
          super.paint(g);
    }

Main Class:

public static void main(String[] args) {
        MainMenu GUI = new MainMenu();
        GUI.setVisible(true);
        try
        {
            PhotoPanel i = new PhotoPanel();
            URL image = GUI.Source();
            BufferedImage bi = ImageIO.read(image);
        
             i.setImage(bi);
             i.validate();
             i.repaint();
        }
        catch (MalformedURLException e) {
        }
        catch (IOException e){}
    }

Also, in case I misunderstood you about main class being THE main class I also tried placing the code that is currently within the main class - except for making the GUI visible - in the MainMenu constructor but that didn't work either.

Well, where are you actually displaying PhotoPanel? I see you crating one, but you are not adding that Panel to anything. Part of "displayGui" in that Psuedo code above also inlvolves creating PhotoPanel and adding it to a JFrame of some sort. Then later you simply use setImage(image) and validate/repaint on the already displayed PhotoPanel object. You do not create a new PhotoPanel everytime you change the image, especially when you don't even do anything with that PhotoPanel. It doesn't just magically pop up onto the screen somewhere, you know?

Edit: Also, as already said, do not override paint, even if all it is doing is calling super.paint.

I have already got a Photopanel that has been created in my MainMenu class. I call it from the main class by saying:

MainMenu GUI = new MainMenu();
GUI.photoPanel.validate();

So far so good. The problem arises, however, with calling the setImage method in the way in which you seem to be indicating I should. The setImage procedure is in my PhotoPanel class. So I have to create an instance of that class in order to be able to call that procedure. This prevents me from saying:

GUI.PhotoPanel.setImage(bi); // setting it to the JPanel

I would have to say:

PhotoPanel i = new PhotoPanel  // The class PhotoPanel - sorry shouldn't 
                                          // use duplicate variable names
GUI.PhotoPanel.i.setImage(bi); // which, of course, doesn't work

Am I missing something? Also, I am coding in NetBeans 6.8 which makes the initial coding of the GUI really quick and easy but adding custom code into it is somewhat trickier.

Take a look at this.

class A {
  private JPanel p = new JPanel();
  public JPanel getP() {
    return p;
  }
}

class B {
  A a = new A();

  public void doit() {
    a.getP().add(new JLabel("A"));
  }
}

That's the way you do it.

For those of you that find a similar problem I found the answer:

Netbeans 6.5 and higher requires installing the full jdk 6u20

That's what the problem was - I didn't have the right version of the jdk installed

http://wiki.netbeans.org/FaqRunningOnJre

All solved :)

That doesn't change the fact that you are going about it all wrong. I would like to know how you got anything to work at all without the "full" jdk.

Okay, so installing the right version of the jdk didn't fix the problem, though it did serve to make the output, from Netbeans or from the command line, behave in the same way.

However, I have fixed the problem. Firstly, I made the move to JGrasp as I found Netbeans too finicky and giving too little control.

Next, I created a class that extends the JPanel and houses my paintComponent method, as Masijade suggested I do. In this class, I put (among other code):

MainMenu parent = null;
public PhotoPanel(MainMenu m)
	{
		parent = m;
	}

and call it in my MainMenu class:

JPanel photo = new PhotoPanel(this);

This serves to place the images in that particular JPanel. I got this code from another forum.

I also then realized that the reason that the image was overpainting once is that I was calling my source() method after I called super.paintComponent(g). Placing it before the call to super.paintComponent(g) cleared that problem up.

Thanks Masijade for replying and for steering me in the right direction.

Problem now really solved :)

 JavaPicture image = (JavaPicture)images.elementAt(nextImage);
 image.saveImage(".movtemp.jpg");

When i Compile it says Symbol Cannot be found.What do i do to compile the program?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.