0

I try to add some components to an JPanel. paintComponent() is called, but the components won't display. revalidate() didn't work.

The structure looks like the following:

public class AbstractView extends JPanel implements ViewInterface {
}

public class GraphView extends AbstractView {
    public void doSomeStuff(){
        this.add(new ElementView());
        this.revalidate();
    }    
}

public class ElementView extends AbstractView {
    @Override
    public void paintComponent(Graphics g) {
        // this method is called but has no effect
        super.paintComponent(g);
        g.fillRect(0,0,100,100);
        this.repaint();
    }
}

I think that's the relevant code. Methods like getPreferredSize() and even getX(),getY(),getWidth(),getHeight() are implemented and seem to work like expected. I searched Google for hours, but nothing seems to help. Am i searching the bug at the right location?

edit:

Here is some more of the Code:

1:

public class AbstractView extends JPanel implements ViewInterface {
@Override
public void update() {}
@Override
public boolean containsPoint(Point p) {
    return false;
}
@Override
public ApplicationView topContainer() {
    return null;
}
@Override
public Dimension getPreferredSize() {
    return new Dimension(this.getBounds().getSize());
}
@Override Rectangle getBounds(){
    return Rectangle(0,0,0,0);
}
@Override
public int getX() {
   return this.getBounds().x;
}
@Override
public int getY() {
    return this.getBounds().y;
}
@Override
public int getWidth() {
    return this.getBounds().width;
}
@Override
public int getHeight() {
    return this.getBounds().height;
}

}

2:

class BodyView extends AbstractView {

Body body;

BodyView(Body b, AbstractView c){
    this.body = b;
    this.setLayout(null);
}

private int radius(){
    return (int) body.radius();
}

@Override
public void paintComponent(Graphics g) {
    // called but without effect
    super.paintComponent(g);
    g.setColor(this.color);
    int x = (int) body.position.at(0);
    int y = (int) body.position.at(1);
    int radius = radius();
    g.fillOval(x-radius, y-radius, 2*radius, 2*radius);
}

@Override
public Rectangle getBounds(){
    int radius = this.radius();
    return new Rectangle(getX() - radius - 2, getY() - radius - 2, 2*radius + 2, 2*radius + 2);
}

@Override
public int getX() {
    return (int) body.position.at(0);
}
@Override
public int getY() {
    return (int) body.position.at(1);
}
}

3:

class SpaceView extends AbstractView {

Space space;
Set<BodyView> bodyViews;

SpaceView(Space s, AbstractView c){
    this.space = s;
    this.initializeBodyViews();
    this.setLayout(null);
}

private void initializeBodyViews(){
    bodyViews = new HashSet<BodyView>();
    for(Body body : space.bodies){
        BodyView view = new BodyView(body, this);
        // new components are added here 
        addBodyView(view);
    }
}

public void addBodyView(BodyView view){
    bodyViews.add(view);
    this.add(view);
}
}

If this isn't enough to determine the problem i would like to refer to this Github.

jesper
  • 1
  • 3
  • 2
    `"Methods like getPreferredSize() and even getX(),getY(),getWidth(),getHeight() are implemented and seem to work like expected"` -- overriding getX and getY carries significant risk of malposition of the component. Calling `repaint()` within any painting method is something that never should be done. I think that you'll need to create and post a valid [mcve] for us to find the root cause of your problem and help you find a solution. – Hovercraft Full Of Eels Oct 03 '16 at 16:40
  • Overriding `getBounds()` to return a bounds with x=0, y=0, width=0, and height=0 seems like a big red flag to me, but if you're overriding it in all child classes it wouldn't cause an issue. It would cause an issue if you forget to do so though - I would still remove it from `AbstractView`to be safe. That might not be related to your problem, but if you did in fact forget, that would explain why nothing is displayed. – searchengine27 Oct 03 '16 at 17:26
  • Also, display stuff in general is a delicate flower to handle. You need to pay attention to the intricacy of how Swing, how the JVM, and how display stuff in general works under the hood. Make sure you're doing everything in the event dispatch thread, make sure you're not calling functions you shouldn't be calling (such as `#paintComponent()` that you mentioned you are calling), etc. Also, `#repaint()` (which you should be calling) only suggests to the java runtime to repaint, it's not forced and it may decide not to. – searchengine27 Oct 03 '16 at 17:29
  • I have to admit, these "no-gos" you mentioned were desperate tries. First i tried to do everything according to this https://docs.oracle.com/javase/tutorial/uiswing/painting/ lesson, which also didn't work. Can you spot any other obviously bugs that may cause the problem? Thank you very much! – jesper Oct 03 '16 at 17:58
  • 1
    the getX and getY are egregious, get rid of them first, as that's not how you want to postion components. Use those sorts of getters/setters in your logical, not your component, classes. Again a strong side recommendation to not call `repaint()` recursively within a painting method. That's makes for a crude and completely uncontrollable game loop, and there are so many better options available. For final answer, I will await your [mcve]. – Hovercraft Full Of Eels Oct 03 '16 at 19:32
  • 2
    `this.setLayout(null);` Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson Oct 03 '16 at 23:10

0 Answers0