Results 1 to 18 of 18
  1. #1
    ShirlyPunk is offline Member
    Join Date
    Mar 2010
    Posts
    8
    Rep Power
    0

    Default Trouble with paintComponent()

    I have two subclassed components, a JPanel and a JButton. I've overwritten their paintComponent() methods to handle their display. Problem is, I've put the new JButtons in the new JPanel, and the graphics arent displaying properly. I've done a little testing and found that whenever the JButtons are being repainted, they are calling the JPanels paint methods as well, but the JPanel's paintComponent method is only being given the graphics context for the small region that needs to be updated.
    The way my graphics are displayed, this won't work. I have to repaint the entire JPanel every time. Does anyone know how to do this?
    And before the question comes up, yes I realize repainting the whole thing doesn't seem like the most efficient approach, but I have yet to put together a suitable workaround and would prefer this method anyway.

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by ShirlyPunk View Post
    I have two subclassed components, a JPanel and a JButton. I've overwritten their paintComponent() methods to handle their display. Problem is, I've put the new JButtons in the new JPanel, and the graphics arent displaying properly. I've done a little testing and found that whenever the JButtons are being repainted, they are calling the JPanels paint methods as well, ...
    I'm not sure why this should be occurring, as the painting of the button should have little effect on the need to paint or not paint the JPanel. A small example program will show that this is so.


    ...but the JPanel's paintComponent method is only being given the graphics context for the small region that needs to be updated.
    I'm not sure I understand this. Perhaps what you mean to say is that the component's repaint method that takes either a Rectangle or several int parameters is being called. If so, I'm not sure if you can control this. Thinking out loud, I suppose if you overrode repaint(...) ..., but I've never done this myself. Hopefully a graphics guru will help you out here.

    Much luck.
    Last edited by Fubarable; 03-12-2010 at 12:49 AM.

  3. #3
    ShirlyPunk is offline Member
    Join Date
    Mar 2010
    Posts
    8
    Rep Power
    0

    Default

    I suppose I should explain how I came to the understanding I did. When I suspected that the JPanel was updating oddly, I placed a line in the paintComponent method of the JPanel that printed out to console the dimensions of the graphic everytime the method was called. At first the dimensions were predictable; the dimensions of the JPanel. Then, as I interacted with components within the JPanel that caused them to be redrawn, the console spat out much smaller dimensions; exactly the dimensions of the components being redrawn.
    The only explanation I could come up with was that paintComponent of the JPanel was being called to repaint the position the JButton was in before the JButton called its paintComponent method
    The logic kinda makes sense. How often do we really need to update the WHOLE component. However, in this case I do.

  4. #4
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default

    If you need more help post your SSCCE.

  5. #5
    ShirlyPunk is offline Member
    Join Date
    Mar 2010
    Posts
    8
    Rep Power
    0

    Default

    Aight. Here's an attempt. This is a trimmed down version of the JButton subclass
    Java Code:
    public class SubButton extends JButton {
      private static AnimationThread animator;
      private static ImageIcon frame1, frame2, frame3; // Initialized in static initializer
      private Dimension size = new Dimension(frame1.getIconWidth(), frame2.getIconHeight());
      private ImageIcon currentFrame;
      public SubButton() {
        // Initializes the animation frames
        setMinimumSize(size);
        setMaximumSize(size);
        setPreferredSize(size);
        setBorder(null);
        setBorderPainted(false);
        setOpaque(false);
        // Begin the animationthread if its not already running
      }
      public void paintComponent(Graphics g) {
        g.drawImage(currentIcon, 0, 0, null);
      }
      private static AnimationThread extends Thread {
        // Code to cycle through the animation images and call update() on the SubButtons
      }
    }
    And here is the trimmed down JPanel
    Java Code:
    public class SubPanel extends JPanel {
      private ImageIcon someIcon1, someIcon2; //Used to build the background image
      private SubButton button;
      public SubPanel() {
        button = new SubButton();
        add(button);
        setOpaque(false);
      }
      public void paintComponent(Graphics g) {
        Rectangle bounds = g.getBounds();
        System.out.println("Height: " + bounds.height + "\nWidth: " + bounds.width);  // For diagnosing the problem at hand
        BufferedImage buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D drawBuffer = buffer.createGraphics();
        // Draw to the drawBuffer
        g.drawImage(buffer, 0, 0, null);
      }
    }
    Now, if the Panel is being handed its full Graphics context, then paintComponent should print out the full dimensions of the Panel every time it is called. It does the first time. But when something happens that requires the panel to be redrawn (further diagnoses has revealed that it doesn't matter if the SubButton calls for this or any other component) such as being overlayed with another window, or a tooltip popup, it prints out a very small set of dimensions.

  6. #6
    ShirlyPunk is offline Member
    Join Date
    Mar 2010
    Posts
    8
    Rep Power
    0

    Default

    Almost immediately after my last post I came up with a possible workaround. I've inserted
    Java Code:
    g = getGraphics();
    as the first line of my paintComponent method of SubPanel. getGraphics returns the full graphics context of the component, which is what I want.
    However, if anyone knows how to have that full Graphics be handed to paintComponent in the first place, I would much prefer that. Just seems 'cleaner'.
    Or even better, find a way to get the relationship between the smaller Graphics and the full Graphics. If I had that, I could just draw the full background to some offscreen buffer, and just paint the portion that needs to be updated.
    Last edited by ShirlyPunk; 03-12-2010 at 06:43 PM. Reason: Further insight

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    This is not an SSCCE, and thus we cannot test your code to see what is wrong. Please review the link for more info. Also, I'm curious on what is going on in that Thread. Are you calling update on anything, because I always thought that this was not necessary and even frowned upon in Swing. Also, are you creating a new BufferedImage with each call of paintComponent, and if so, why?

    Much luck!

  8. #8
    ShirlyPunk is offline Member
    Join Date
    Mar 2010
    Posts
    8
    Rep Power
    0

    Default

    Well, what is actually happening with the thread is a bit convoluted. It would be a bit difficult to explain here, but I can say that there are checks involved that make sure update isn't being called if the component doesn't actually need to be updated.
    Originally yes, the BufferedImage was being created every time paintComponent was being called. The BufferedImage was being used for the sake of manual double buffering. I created it fresh every time because I was having difficulty creating it once and repainting it every time.
    Since then I've solved that problem so that the background image is only redrawn when the SubPanel is resized.

    Furthermore, I've have found a solution to the problem I've been having. However, I would still appreciate answers to the questions in my previous posting. To that end I'll include another attempt at a representation of the relevant code:
    Java Code:
    import javax.swing.JPanel;
    import java.awt.event.ComponentAdapter;
    import java.awt.event.ComponentEvent;
    import java.awt.image.BufferedImage;
    import java.awt.Graphics2D;
    import java.awt.Color;
    import java.awt.Rectangle;
    
    public class SubPanel extends JPanel {
      private BufferedImage background;
    
      public SubPanel() {
        setOpaque(false);
        addComponentListener(new ComponentAdapter() {
          public void componentResized(ComponentEvent e) {
            SubPanel ref = (SubPanel)e.getSource();
            if(ref.getWidth() != 0 && ref.getHeight() != 0) // Makes sure I'm not updating the BufferedImage before the SubPanel is actually displayed
              updateBackgroundImage();
          }
        });
      }
    
      // The actual background is more than just red, but that isn't relevant so I'm just putting in some dummy graphics
      public updateBackgroundImage() {
        background = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D)background.getGraphics();
        g.setColor(Color.RED);
        g.fillRect(0, 0, getWidth(), getHeight());
      }
    
      public void paintComponent(Graphics g) {
        Rectangle bound = g.getClipBounds();
        System.out.println("Height: " + bound.height + "\nWidth: " + bound.width); // This outputs the size of the Graphics being handed to paintComponent
        g.drawImage(background, 0, 0, null);
      }
    }
    Just throw this into a JFrame and it should work. Then do something that will cause a partial repainting ( dragging another window over the JFrame works fine, as well as bringing up a tooltip text). The console output demonstrates my question.

  9. #9
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    How about adding a repaint() at the end of the updateBackgroundImage method. e.g.,
    Java Code:
    import javax.swing.*;
    import java.awt.event.ComponentAdapter;
    import java.awt.event.ComponentEvent;
    import java.awt.image.BufferedImage;
    import java.awt.*;
    
    public class FuSwing2 {
      private static void createAndShowGUI() {
        SubPanel subPanel = new SubPanel();
        subPanel.setPreferredSize(new Dimension(400, 300));
        
        JFrame frame = new JFrame("FuSwing2 Application");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(subPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            createAndShowGUI();
          }
        });
    
      }
    }
    
    class SubPanel extends JPanel {
      private BufferedImage background;
    
      public SubPanel() {
        setOpaque(false);
        addComponentListener(new ComponentAdapter() {
          public void componentResized(ComponentEvent e) {
            SubPanel ref = (SubPanel) e.getSource();
            if (ref.getWidth() != 0 && ref.getHeight() != 0) 
              updateBackgroundImage();
          }
        });
      }
    
      public void updateBackgroundImage() {
        background = new BufferedImage(getWidth(), getHeight(),
            BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D) background.getGraphics();
        g.setColor(Color.RED);
        g.fillRect(0, 0, getWidth(), getHeight());
        repaint(); // **** add repaint here ****
      }
    
      public void paintComponent(Graphics g) {
        Rectangle bound = g.getClipBounds();
        System.out.println("Height: " + bound.height
            + "\nWidth: " + bound.width); // This outputs the size of the Graphics
        // being handed to paintComponent
        g.drawImage(background, 0, 0, null);
      }
    }

  10. #10
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default

    Just throw this into a JFrame and it should work.
    No, that is your job. that is part of a SSCCE. You've been asked to read the SSCCE link a couple of times. You want help. Wouldn't it be nice if 2 o3 or 4 people looked at your problem? Why should everyone have to take the time to create the frame and add the panel to the frame? Make it easy for us to help you.

    Sometimes Pete is just too nice, but maybe next time he won't be around when you have a question.

  11. #11
    ShirlyPunk is offline Member
    Join Date
    Mar 2010
    Posts
    8
    Rep Power
    0

    Default

    I'm apparently not conveying my question properly. My question is, why is paintComponent() being handed only a portion of the JPanel's full graphical area, and/or how do I ensure that it always recieves it's FULL graphical area. I apologize for the miscommunication.

    To camickr, the source code really isn't even important since my question is generic in nature. All components have a paintComponent method, and I believe that all components are subject to the situation I've described. And if anyone viewing this thread doesn't feel compelled to go out of their way to throw my code into a program to try and help, then I ask them not to waste their time on my question. It's really not that important.

  12. #12
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by ShirlyPunk View Post
    I'm apparently not conveying my question properly. My question is, why is paintComponent() being handed only a portion of the JPanel's full graphical area, and/or how do I ensure that it always recieves it's FULL graphical area. I apologize for the miscommunication.
    But it's not a problem for us, and that may be the reason why we're having a difficult time helping you.

    To camickr, the source code really isn't even important since my question is generic in nature.
    Oh, but it is important, as most of us don't have any problem with the way that Swing handles painting. If your program is having problems with it, then a small compilable program that demonstrates this problem is the best way of letting us understand what's going on. On that note, if my "fix" in your code above doesn't help you, then you might get better help if you post another small program that better illustrates the problem.

    All components have a paintComponent method, and I believe that all components are subject to the situation I've described. And if anyone viewing this thread doesn't feel compelled to go out of their way to throw my code into a program to try and help, then I ask them not to waste their time on my question. It's really not that important.
    I've thrown your code into a program and found a fix. If this isn't what you're looking for, then you need to give us a better sample program. I'm behind camickr 100% on this one. Again, it's all a matter of how will you convey the essence of your problem in the easiest way possible -- and a compliant SSCCE helps extremely well in this. But hey, it's up to you and how quickly you want your issue resolved.

    Best of luck.

  13. #13
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Incidentally, I couldn't find a getBounds() method for the Graphics class. Do you mean getClipBounds() instead? And have you tried messing with the setClip(...) method?

  14. #14
    ShirlyPunk is offline Member
    Join Date
    Mar 2010
    Posts
    8
    Rep Power
    0

    Default

    Again, the fault of miscommunication is mine. And don't meant to imply that I don't appreciate your help Fuba. I just found camickr's comments to be a bit confrontational.
    Also, I should add that this problem is by no means urgent. I'm a student putting some extra effort into a project over spring break is all.
    Yes, I did mean getClipBounds(). I used getBounds in a similar context someplace else and got the two switched.
    Calling repaint() from the end of updateBackgroundImage() will force the JPanel to be repainted when it's size is altered, but that is already happening. My problem is that my paintComponent method can only paint the entire JPanel at once, but when only a portion of the JPanel needs to be repainted (as is the case when a child component needs to be repainted, or when another window is placed partially over the JPanel) it is only being given the graphics area for the portion that needs to be repainted. If I could get the whole graphics context, or better yet, offsets of the smaller graphical area compared to the full graphical area of the JPanel, then I would have something I can work with.
    Unfortunately I'm out the door at the moment, but when I get a chance, I will write up a full SSCCE, and make sure it's compilable on it's own.

  15. #15
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default

    I just found camickr's comments to be a bit confrontational.
    You've made 7 postings. I've answered 10's of thousands of posting (in this forum and others). Usually I can "read between the lines" to understand what people are asking.

    In this case I couldn't so I asked you to post a SSCCE. You posted bits and pieces of code and Pete also had to remind you that is was NOT a SSCCE and also provide a link again. You provide more code which was still NOT a SSCCE. So it is you who is being uncooperative. I still don't understand what you are doing or understand why you think you need the Graphics of the panel. Swing manages repainting of components in a very reasonable manner and as Pete has said I've never had any problems. Most probles are caused by newbies who don't know what they are doing. And without code we can't guess what mistakes you might be making.

  16. #16
    ShirlyPunk is offline Member
    Join Date
    Mar 2010
    Posts
    8
    Rep Power
    0

    Default

    You know what, forget it. Fuba has been very patient and understanding, and despite the fact that it took me so long to fully understand what an SSCCE is, he's still done his best to help. But I won't tolerate camickr any more. You've been demeaning and stubborn every step of the way, and this last post even came to flat out insults
    Most probles are caused by newbies who don't know what they are doing.
    I couldn't just be a person with a question, now apparently I'm an idiot. I'd rather have my question go unanswered then risk any further contact with you.

  17. #17
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,762
    Blog Entries
    7
    Rep Power
    21

    Default

    Quote Originally Posted by ShirlyPunk View Post
    You know what, forget it. Fuba has been very patient and understanding, and despite the fact that it took me so long to fully understand what an SSCCE is, he's still done his best to help. But I won't tolerate camickr any more. You've been demeaning and stubborn every step of the way, and this last post even came to flat out insults I couldn't just be a person with a question, now apparently I'm an idiot. I'd rather have my question go unanswered then risk any further contact with you.
    All that Camickr asked was that you supplied a small, compiling and running program that showed the same problems you were struggling with; that's an SSCCE and you refused to supply one. I've seen zillions of correct answers by Camickr in Sun's Java forum (in the Swing section mostly) and I cant find his request unreasonable; you just threw a fit and that is not the attitude to have in the programming field.

    kind regards,

    Jos

  18. #18
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    I second what Jos had to say. I might have played "good cop" in this thread, but regardless, camickr is and always has been the "smart cop". If we both answer a question in a java forum, then my recommendation will automatically be to follow his advice, not mine, because he knows more than I'll ever know. He didn't ask for much here, and you'll find that if you follow his requests, you'll usually get a quick and helpful answer from him.

    Much luck.

Similar Threads

  1. paintComponent is not working
    By spazattack in forum New To Java
    Replies: 1
    Last Post: 12-18-2009, 04:48 AM
  2. Working around paintcomponent
    By sahhhm in forum New To Java
    Replies: 2
    Last Post: 05-16-2008, 03:43 AM
  3. Problem going outside paintComponent
    By Thez in forum Java 2D
    Replies: 9
    Last Post: 12-08-2007, 05:59 PM
  4. Drawing outside paintComponent()
    By DarkSide1 in forum Java 2D
    Replies: 2
    Last Post: 11-08-2007, 11:36 PM
  5. paint() and paintComponent()
    By goldhouse in forum Java 2D
    Replies: 1
    Last Post: 07-17-2007, 04:43 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •