I am trying to display a filled oval on the screen using a subclass of JPanel
when I try to add an object of this subclass to a JFrame with FlowLayout the oval is not displayed correctly I don't know what the problem is. Could you help me please?
here's my code
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillOval(0, 0, 50, 50);
}
in main
JFrame frame = new JFrame("Ball");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300,300);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setLayout(new FlowLayout());
BallPanel ball = new BallPane();
frame.add(ball);
See the Javadoc of the FlowLayout:
A flow layout lets each component assume its natural (preferred) size
Since you do some custom painting, the BallPanel cannot compute its preferred size (which is based on the components you add the panel). So override in the BallPanel class the getPreferredSize method to return correct dimensions (correct means matching your custom painting). Consider doing the same for the getMinimumSize and getMaximumSize.
What I always use when I have to debug Swing layout problems is to add borders to my components in specific colors. That way you clearly see the size your components take in their parent container, which might be a good starting point for debugging. In your case, it would show a very tiny panel ;-)
When you create any custom component and do custom painting you need to override the getPreferredSize() method to return the size of the custom component. Ideally you would also overrid the minimum/maximum sizes as well.
Then the layout manager can do its job.
Related
I have a main panel with a border layout containing another panel in the center.
Because I want to paint inside the centered panel I have to get the bounds of it.
panel_main.add(panel, BorderLayout.CENTER);
I wanted to save the bounds in a rectangle like this:
Rectangle bounding = new Rectangle
(panel.getX(), panel.getY(), panel.getWidth(), panel.getHeight());
But every argument seems to be 0. So how do I get the bounds of the panel?
Could I get the bounds of the BorderLayout instead?
But every argument seems to be 0.
All Swing components have a size of (0, 0) when they are created. Components are only given a size when the frame is packed and made visible.
Because I want to paint inside the centered panel I have to get the bounds of it.
You override the paintComponent() method of the panel. Then you can use the getSize() method to control where the painting is done.
You will also need to override the getPreferredSize() method of the panel so the layout manager can pack() the frame properly.
Read the section from the Swing tutorial on Custom Painting for more information and working examples to get you started.
I created a class that extends a JFrame and added a JPanel inside it, but the paintComponents() method doesn't draw anything on the JPanel. Heres the code for the paintComponents(), I chose to use double image buffering.
public void paintComponents(Graphics graphics) {
panel.paintComponents(graphics);
bufferedImage = createImage(sizeX, sizeY);
Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
for (ImageData myImage : imageData) {
g.drawImage(myImage.getImage(), myImage.getX(), myImage.getY(), null);
}
graphics.drawImage(bufferedImage, 0, 0, null);
}
Is there anything wrong with this? Btw, I tried paint() and it worked but I dont think it's the proper way to do this.
Thanks for your time. :)
Do not extend a top level component such as a JFrame. Instead keep an instance of a frame, and add a panel to that. All custom painting or addition of components is done in the panel.
When doing custom painting in a panel, do it in the paintComponent method (not paintComponents do not override that).
Other tips
Remember to call super.paintComponent(g);. This is important to ensure that borders and padding etc. are accounted for.
Swap null for this. Every JComponent is an ImageObserver.
please note that JFrame is NOT a JComponent! In fact, the paintComponents(Graphics) method is NEVER called. A fix would be subclassing JPanel and adding your subclassed panel to the frame as the content pane. In the panel override the paintComponents(Graphics) method.
I am trying to write a code to generate a graph like this: http://www.mathgoodies.com/lessons/graphs/images/line_example1.jpg
I need more than one different line (I hope that's what they are called).
I'm just starting to learn awt and swing. After exhausting three hours of work, I couldn't manage a way to draw a line on top of any other drawing.
I'll try to explain my problem with an example.
Lets say I draw a square like this:
JFrame window = new JFrame();
window.setLayout(null);
window.setVisible(true);
Graph graph = new Graph();
window.add(graph);
//-------------------
public class Graph extends JPanel {
....
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(150, 20, x, y);
}
....
}
How do I draw another line or anything else on top of this white square whithout drawing the line in the Graphs paintComponent method? How do I add another JPanel on top of another one, so that both of them are visible? (I'm using JPanel to add some buttons)
Hopefully you can understand what I'm asking.
Thank you!
How do I draw another line or anything else on top of this white square whithout drawing the line in the Graphs paintComponent method?
All custom painting should be done in the paintComponent() method. I'm not sure why you want to add another panel that paints on line. Keep it simple and keep all the painting code in one place.
If you want to add other components (like a JPanel) to the panel then you would use layout managers to lay out the components properly. You would also need to make the components non-opaque by using the setOpaque(...) method.
Another way to layer components is to use a JLayeredPane.
Start by reading the Swing tutorial. There are sections on:
Using Layout Managers
Using Layered Panes.
Following code work for visualizing a molecule on a JPanel except it does not rescale when I change the size of JPanel at runtime. The Chemistry Development Kit is used for generating rendered Image. A molecule is passed to MoleculeViewer for visualizing. What am I doing wrong??
What am I doing wrong??
why you needed to setSize(new java.awt.Dimension(400, 400));
put your image = new BufferedImage(this.WIDTH, this.HEIGHT, BufferedImage.TYPE_INT_RGB); as Icon to the JLabel, then you can remove anything about paintComponent()
then you can return JLabel instead of JPanel, but JLabel is translucent by default, or put JLabel to the JPanel by using proper LayoutManager in this case BorderLayout.CENTER
you have to check how way you added MoleculeViewer, what LayoutManager is there used???, because only usage of LayoutManager can this job correctly to resize (or not resize) Container's childs with Top-Level Container,
MoleculeViewer must retuns PreferredSize for its parent
Adding following resolved the not redrawing upon scaling problem
renderer.paint(molecule_, new AWTDrawVisitor(g2), new Rectangle2D.Double(0, 0, w, h), false);
g2.dispose();
}
else
I have a JPanel where I draw shapes. this panel is added to a scrollPane. but the scrolling doesn't work when a shape is out of the scene. is there an easy way to autoscroll or I have to do it programmatically.
Thank you
I'm assuming you're using the JPanel as a canvas for custom drawing(i.e. you're not adding any JComponents to it). If that's case, the JScrollPane has no way of knowing how large the JPanel is and will just size it to exactly fill the scrollPane's viewport(which means you'll never actually get scroll bars).
To fix this issue you should override getPreferredSize on your JPanel.
#Override
public Dimension getPreferredSize() {
int height = calculateHeight();
int width = calculateWidth();
return new Dimension(width, height);
}
Edit:
Also, since you're doing custom drawing make sure to call revalidate whenever the shapes you want to draw change. This tells swing that it needs to re-think the layout/size of the JPanel.