0

I'm trying to understand what actually paints components in Swing. I read this article about painting in AWT and Swing and now tried to write the following simple program:

//A simple wrapper to understan how paint() works
public class MyButton extends JButton{
    /**
     * Default serialVersionUID
     */
    private static final long serialVersionUID = 1L;
    private final JButton jButton;

    public MyButton(JButton jButton) {
        this.jButton = jButton;
    }

    @Override
    public void paint(Graphics g){
        jButton.paint(g);
    }
}

But when I try to add MyButton to frame

JFrame frame = new JFrame("Hello swing");
JPanel panel = new JPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.add(new MyButton(button));
frame.add(panel);

it renders nothing

enter image description here

But after deleting

@Override
public void paint(Graphics g){
    jButton.paint(g);
}

it renders the empty button:

enter image description here

QUESTION: Why does it behave that way? Why does the delegating cause rendering to fail?

  • Is n't your jButton.paint() calls again paint( Graphics g ) ? and it is an endless recursion ? The JComponent of which JButton is child, handles the paint. If you override with paint( Graphics g ) it will call its own method and it seems your implementation doesn't do anything except calling itself over and over. – SomeDude Apr 16 '16 at 16:18
  • First of all you don't paint UI Components yourself ^^ – Marcel Apr 16 '16 at 16:19
  • @svasa No, that won't happen here. – Radiodef Apr 16 '16 at 16:19
  • Your simple wrapper is anything but simple. You're adding a non-rendered component to the wrapper, and then trying to paint the non-rendered component, so it makes sense that nothing will appear. – Hovercraft Full Of Eels Apr 16 '16 at 16:20
  • @ScriptKiddy Why that? In my case I need to provide some custom painting... –  Apr 16 '16 at 16:21
  • 3
    What are you trying to achieve with this wrapper? If it's to learn how painting works, don't do it this way, don't use a wrapper that doesn't make sense. Instead extend the component and work with its own paint or paintComponent method override. – Hovercraft Full Of Eels Apr 16 '16 at 16:21
  • @HovercraftFullOfEels I need to craft some kind of custom-renderd button. For that, I'm trying to understand how painting works... –  Apr 16 '16 at 16:21
  • 4
    Swing programs should override `paintComponent()` instead of overriding `paint()`; see also [*Painting and the UI Delegate*](http://www.oracle.com/technetwork/java/painting-140037.html#callbacks), for [example](http://stackoverflow.com/a/5755124/230513). – trashgod Apr 16 '16 at 16:22
  • @DmitriiBundin: you're not barking up the wrong tree, your current code is looking in the wrong forest. – Hovercraft Full Of Eels Apr 16 '16 at 16:23
  • @HovercraftFullOfEels Since I came from JSF where we're used to making lots of composite component/custom renderer and so forth, my first attempt was to create a composite component and modify its renderer for a bit. Is it a wrong way of doing things in swing? For instance, I want to combine `JLable` and `JButton` in a single composite compoenent for the reusability sakes. Therefore I'd code up some kind of custom renderer through overridng `paintComponent`... –  Apr 16 '16 at 16:27
  • No, you'd create a class that either extends or returns a JPanel and that holds a JLabel and a JButton. – Hovercraft Full Of Eels Apr 16 '16 at 16:29
  • 1
    @trashgod: not always. Sometimes you do want to override paint, especially if you want to have effects on borders and child components. I'm not sure if you've had a chance to read [Filthy Rich Clients](http://filthyrichclients.org/) by Haase and Guy, but it has a great example of using this to create a JButton that is transluscent. – Hovercraft Full Of Eels Apr 16 '16 at 16:34
  • Although that of course is the exception and not the rule – Hovercraft Full Of Eels Apr 16 '16 at 16:38

3 Answers3

1

First of all when you post a question you should post a proper SSCCE that demonstrates the problem. We can't copy/compile random lines of code. Until a problem is solved, you don't know what part of the code is causing the problem.

Why does the delegating cause rendering to fail?

My guess would be that the size of the button is (0, 0) so there is nothing to paint.

When you get rid of the custom paint method, then the real button can be painted because it does have a size because the layout manager has done its job.

camickr
  • 321,443
  • 19
  • 166
  • 288
0
public class Demo extends JFrame{
    public static void main(String[] args)
    {
        JPanel panel = new JPanel();
        getContentPane().setLayout(new BorderLayout());
        panel.add(new JButton("Test"));
        this.getContentPane().add(panel, BorderLayout.CENTER);
        this.setSize(200,200);
        this.setVisible(true);
    }
}

If you want to add UI Components do it like that, don't use paint in any way. If you want to paint for example a rectangle follow this tutorial: https://docs.oracle.com/javase/tutorial/uiswing/painting/

Marcel
  • 1,509
  • 1
  • 17
  • 39
0

Your paint method does not draw the MyButton object, but instead draws the JButton which is member of your class. The problem now is, that this Button has not been added to the panel and so it's drawn on nothing. By removing your paint method, super.paint(g) is called because your class has no paint method and so your button, but not the member JButton is drawn.

I hope you understand what I am trying to explain to you.

Tobias Brösamle
  • 598
  • 5
  • 18