I want to paint simple oval. In the following code, if I add draw a oval on Jpanel then it doesn't work however it works fine if I draw on frame. Following is the code which works.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class Controller {
public Controller() {
View view = new View();
Model model = new Model(100, 100, 100, 100);
view.paintModel(model);
}
public static void main(String[] args) {
Controller c = new Controller();
}
public class View extends JFrame {
private JPanel jpanel;
public View() {
this.setBounds(0, 0, 500, 500);
this.setLayout(new BorderLayout());
jpanel = new JPanel();
jpanel.setBackground(Color.WHITE);
jpanel.setLayout(null);
this.add(jpanel, BorderLayout.CENTER);
this.setVisible(true);
this.validate();
}
public void paintModel(Model model) {
jpanel.add(new ModelView(model));
jpanel.validate();
jpanel.repaint();
}
}
public class Model {
public int xPos;
public int yPos;
public int height;
public int width;
public Model(int xPos, int yPos, int height, int width) {
super();
this.xPos = xPos;
this.yPos = yPos;
this.height = height;
this.width = width;
}
}
public class ModelView extends JComponent {
private Model model;
public ModelView(Model model) {
super();
setBorder(new LineBorder(Color.RED));
this.model = model;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(model.xPos + model.width, model.yPos
+ model.height);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.fillOval(model.xPos, model.yPos, model.width, model.height);
}
}
}
First of all, you are not calling super.paintComponent
in you ModelView
class, this is incredibly important, especially when dealing with transparent components like JComponent
Secondly, you've provide no layout information of the ModelView
, that is, the component has no preferred, minimum or maximum size hint, so many of the layout managers will consider it to have a size of 0x0
, which is what is happening here.
JPanel
by default uses FlowLayout
which will use the components preferred size to lay it out.
Update the ModelView
to provide some sizing hints (in most cases, overriding getPreferredSize
should be sufficient) or use a different layout manager on the JPanel
you are adding the ModelView
to which doesn't care about such things (like BorderLayout
for example)
Updated
Additionally, you "may" be painting beyond the visual bounds of the component, for example, you create a model using, Model model = new Model(100, 100, 100, 100)
then you render that model using g.fillOval(model.xPos, model.yPos, model.width, model.height)
, but the preferredSize
of your component is only new Dimension(model.width, model.height)
, you are actually painting your oval at the right, lower edge (outside) of the component
Unless you intend to write you own layout manager to manage this, you should be taking the x/y offset into account when calculating the preferred size of the component, for example, new Dimension(model.xPos + model.width, model.yPos + model.height)
For example...sorry, I butchered your code a little to seed the model...
The red line is just a LineBorder
which shows the boundaries of the ModelView
component
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class View extends JFrame {
private JPanel jpanel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
new View();
}
});
}
public View() {
this.setBounds(0, 0, 500, 500);
this.setLayout(new BorderLayout());
jpanel = new JPanel();
jpanel.setBackground(Color.WHITE);
this.add(jpanel, BorderLayout.CENTER);
Model model = new Model(100, 100, 100, 100);
paintModel(model);
this.setVisible(true);
}
public void paintModel(Model model) {
jpanel.add(new ModelView(model));
jpanel.validate();
jpanel.repaint();
}
public class ModelView extends JComponent {
private Model model;
public ModelView(Model model) {
super();
setBorder(new LineBorder(Color.RED));
this.model = model;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(model.xPos + model.width, model.yPos + model.height);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.fillOval(model.xPos, model.yPos, model.width, model.height);
}
}
public class Model {
public int xPos;
public int yPos;
public int height;
public int width;
public Model(int xPos, int yPos, int height, int width) {
super();
this.xPos = xPos;
this.yPos = yPos;
this.height = height;
this.width = width;
}
}
}