I've added my JPanel derived class to the JFrame. Now when I want to draw an oval (using fillOval in my JPanel's paintComponent method) I see two ovals being painted. The problem disappears when I invoke super.paintComponent or when I invoke setContentPane in the JFrame class with my JPanel as parameter. The question is, why does it happen? Of course when the upper left corner of both JPanel and JFrame are in the same place, it doesn't happen. But somehow the JPanel isn't opaque unless I invoke super.paintComponent. The main question is why does it paint BOTH on the default content pane AND my JPanel. Thanks for help.
" The main question is why does it paint BOTH on the default content pane AND my JPanel."
It just appears that way, but actually you are seeing both being drawn on the panel. Always call super.paintComponent in the paintComponent method (no if ands or buts) or you will see paint artifacts as the one you're experiencing. The paintComponent method can be called for any number of reasons, and each time it's called, is another opportunity for paint artifacts to appear. Calling super.paintComponent wipes those out. When you set the content pane to the panel, it appears the paintComponent method is not being called more than once, so you don't get those artifacts. But to reiterate, always call super.paintComponent. Setting the content pane has nothing to do with the problem or the solution.
Related
Firstly, I make some panels overlap each other and setVisible for them when click. Everything goes fine until I use setBackGround(new Color(0,0,0,0)) for all panels to make them look like transparent, but setVisible(false) does not work, meaning that the current panel is still shown with others. It looks like:
This appears to be an issue with not setting setOpaque(false).
See JComponent.setOpaque()
This is alluded to in the JavaDoc for JComponent.setBackground
Sets the background color of this component. The background color is
used only if the component is opaque, and only by subclasses of
JComponent or ComponentUI implementations. Direct subclasses of
JComponent must override paintComponent to honor this property.
I have an LWJGL OpenGL Display showing up inside an AWT Canvas, which in turn is inside a Swing JPanel that is used as content pane for a Swing JFrame. At some point in the program, I want to switch the AWT Canvas containing the Display for a JComponent, so that instead of having something like that:
JFrame > JPanel > Canvas > Display
I have something like so:
JFrame > JPanel > JComponent
However, even though I remove the Canvas from the JPanel and add the JComponent, then revalidate the JPanel and repaint it, the Display still shows until I CTRL-ALT-SUPPR to task manager (my JFrame is set Undecorated and ExtendedState is JFrame.EXTENDED_BOTH, so it is full screen). At which point, the JComponent shows up like nothing ever happened..
I'll share the part of my code that does the transition so you can maybe help me point out what I have done wrong:
public static void switchTo(Container container){
pan.removeAll();
container.setBounds(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
pan.add(container);
frame.getContentPane().validate();
pan.revalidate();
pan.repaint();
}
where pan is my JPanel and frame is my JFrame.
I have also tried directly setting my JComponent as my JFrame's content pane, but that gives the exact same result.
The only way I managed to make it function correctly was by calling destroy() on the Display beforehand; however, I need to keep the OpenGL context running so that I don't have to re-initialize the Display and reload every texture when switching back to the Display, which would be quite a long process given the number of textures I have.
Thank you very much for any answer, I hope I made myself clear!
I'm programming the game hangman and I have a Label in the center for the word to be guessed, a score panel on the right(east) and a panel of button characters on the bottom(south). As i was moving onto painting the hangman gallows, i tried to paint a simple circle at first and add it to the left(west) of the frame, but only a small portion of the circle appeared, the problem seemed to be fixed temporarily when i maximized the frame and the resized it to its original size, how do i fix this? I created a class that extends JPanel and overrided its pain component method. what should i do so that it fully shows the circle when the program is launched.
I created a class that extends JPanel and overrided its pain component method. what should i do so that it fully shows the circle when the program is launched.
You also need to override the getPreferredSize() method to return the size of the panel so that the layout managers can use this information.
overrided its pain component method
You should be overriding the paintComponent() method, not the paint() method.
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
can please anyone explain the difference between JPanel.repaint() method and JFrame.repaint() method, i guess both calls the paintComponent() method in JPanel.
Please clarify, thanks
Calling repaint() on any Component will add a request to the repaint manager to paint that component. If conditions are correct, the manager will then arrange to have the Component's paint(...) method called. Since a Component's paint method will then call paintComponent(...), paintBorder(...) and paintChildren(...) this will have the component paint itself, its border and cascade painting recursively to all of its children, their children, their children's children, etc. Calling this on JFrame will cause this cascade to occur throughout the entire top-level window whereas calling it on a subcomponent will cause a repainting of that component and its children only.
Note that calling repaint() does not guarantee that the repaint manager will paint the component, especially if there are stacked requests. For more on the details, please read Painting in AWT and Swing.
1. When repaint() method is called then the Event handler thread notifies all the components , and then every component calls their paintComponent() method.
2. Calling JPanel.repaint() will have all the component within the JPanel to repaint(), and calling JFrame.repaint() will have all the component within the JFrame to repaint() .
3. Call JFrame.repaint() to repaint the JPanel too without the need of JPanel.repaint()....
In brief,
JPanel.repaint() will repaint itself and its children.
JFrame.repaint() will repaint itself and its children. But since JFrame is the base, this will repaint every component within.
Check "#Hovercraft Full Of Eels" answer for details.
I have a JFrame, which is the toplevel container for a window, and a single JComponent (that I have implemented) which is contained in the JFrame.
In part of my JComponent's logic, I need to resize the window to a specific size, but now matter what I try, it has not worked. I have tried calling setPreferredSize and setSize on the JFrame, the JComponent, and on the Container returned from calling getParent() on the component.
I have a feeling this has something to do with not calling pack after changing the size, but I cannot figure out how to access the JFrame from the JComponent to call pack on it (I am no swing expert).
Thank you
You can always get the top level window by calling the SwingUtilities#getWindowAncestor method:
Window topLevelWindow = SwingUtilities.getWindowAncestor(myComponent);
topLevelWindow.pack();
passing in your component. Just make sure that you only call this after the GUI has been rendered, else you'll get a nasty NullPointerException.