Results 1 to 20 of 20
  1. #1
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

    Question Objects painting themselves?

    Is it possible for objects to paint themselves? At the moment, I have a JPanel with a paint method and all objects that I want painted I call from the paint method with an argument of the Graphics object.

    This takes a long time and limits me with instances of certain objects that I don't know exist until runtime.

    I'm sure it will probably be a very simple problem, but I don't know where to start.

    Thank you in advance :)

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

    Default

    Objects can paint themselves, sure, just as a JPanel or other JComponent knows to paint itself. But just what are you asking here? Is that can objects be painted outside of the paintComponent method? AFAIK, most painting in Swing is done passively as you are doing it, in the paintComponent method. BufferedImages can be drawn outside of paintComponent with their extracted Graphics object, but still they are then displayed in the paintComponent method.

    I guess what I think we need here is more context that can help us understand just what you are asking.

    Much luck and welcome to the forum!

  3. #3
    JavaJuJitZu is offline Member
    Join Date
    Jan 2010
    Posts
    26
    Rep Power
    0

    Default

    @Fubarable
    Although not the best practice one can grab a graphics object from the component and paint directly onto it. It is better to override the painComponent and call repaint() when you need to update. The AWT event queue then handles the timing of the painting.

    However something to explore in your own time. Make a JPanel, add a mouse listener, catch the dragging event and try the following
    Java Code:
    mousedragged(mouseevent event){
    Graphics g = panel.getGraphics();
    g.drawRect(event.x,event.y,5,5);
    g.dispose();
    }
    As to the ops question, objects painting themselves is a deeper topic, ideally your JPanel and components you add to it should be able to handle their own painting. A standard application with just various swing widgets such as text fields and buttons should not require you to code your own paintComponent methods. Simply change whatever you need and call repaint() if necessary.

    If you are writing your own Swing components, you need to extend the correct classes and write whatever customizations you need to the paintComponent() method and it should paint itself correctly.

    I recommend your read as much as you can about swing, java2d and come back with some code your working on. As fubar said we will be in much better position to help you if you make your post a bit more clear and specific (some example code would be nice).
    Last edited by JavaJuJitZu; 02-03-2010 at 06:38 AM. Reason: added g.dispose() as Jdoc says method creates graphics Context, so we should dispose when not used.

  4. #4
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

    Default

    Sorry, for my vagueness, I was rushing to finish the post before I left.
    I have just migrated from flash, so the graphics in Java are currently my biggest barrier.

    So, my problem at the moment is this:

    I have created a class extending a JPanel which is added to my main application. Let's call this class "window".

    In window's method, I have added several classes which extend Component.
    In each of these Components I have a method which I made to paint them: drawItem(Graphics g)

    In my window's paint method I then call each component's drawItem method and feed it Graphics.

    The thing is, when I want to create a component without giving it a reference, I want it to paint, but of course, I won't be able to call it's drawItem method.


    So the code for my Window includes:

    Java Code:
    public class Window extend JPanel implements Runnable{
    [INDENT]
    MyComponent c;
    public Window(){
    [INDENT]
     c = new MyComponent();
    
    ...
    [/INDENT]
    }
    
    ...
    
    public void paint(Graphics g){
    [INDENT]
    super.paint(g);
    c.drawItem(g);
    g.dispose();[/INDENT]
    }
    
    ...
    [/INDENT]
    }
    My feeling is that it has something to do with the super.paint() method, because from the sources I have already looked at, it seems that it is crucial for what I want to achieve.

    Some more advice would be great!
    Thanks for the help so far though!

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

    Default

    1) Since this is a Swing app, you may wish to have your "components" extend JComponent which is Swing's answer to AWT's component.
    2) If you add these JComponents to your Window JPanel via the add(...) method, then the component's paintComponent method will be called whenever the Java or the OS decides that it needs to repaint the region that the component sits on.

  6. #6
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

    Default

    Thank you Fubarable! that is exactly what I am looking for!
    Just one thing, is there a way to reference these components so that I can replace:
    Java Code:
    MyComponent c = new MyComponent();
    with something equivalent for the add() method?

    And thank you again for your help, it is much appreciated and saved me a lot of time.

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

    Default

    Quote Originally Posted by martypapa View Post
    Just one thing, is there a way to reference these components so that I can replace:
    Java Code:
    MyComponent c = new MyComponent();
    with something equivalent for the add() method?
    It may be that it's been a busy day here at work, but I'm not sure that I quite understand what you're asking for here. Could you clarify this a bit?

    And thank you again for your help, it is much appreciated and saved me a lot of time.
    You're quite welcome.

  8. #8
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

    Default

    I am very sorry again, what I am asking is if it is possible to create a reference to my component if I use the add() method. I want to be able to change the properties of my JComponents now, but I can't do so unless I feed it through an argument when I create it (which I don't really want to be doing as it will get quite messy).

    So basically, as in my the previous post, I could change the properties of the component, c by calling something like:
    Java Code:
    c.backColor = Color.red;
    c.width = 20;
    c.height = 10;
    That's how I did it before, but now if I use add(), how will I modify these variables?

    Thanks

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

  10. #10
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

    Default

    Hmmm well I tried out the JComponent, and it seems to be working as I want except for one major problem, it isn't actually painting on the screen. I tested to see if the paintComponent method was running, and it was.

    Am I missing a vital line?
    I've tried changing the paintComponent() method to paint() method, added a super.paint methods, but can't seem to get any better results.

    It wouldn't be the ordering of painting either, because there is nothing else where my component should be painting.

    Here is all the main code for my JComponent:
    Java Code:
    public class MyComponent extends JComponent{
        ....
        public void MyComponent(...){
            ...
        }
    
        public void paintComponent(Graphics g1){
                Graphics2D g = (Graphics2D)g1;
                g.setColor(Color.red);
                g.fillRect(0, 0, 800, 600);
                System.out.println("now painting");
        }
    }
    So I get the "now painting" output, but no rectangle is being painted...

    Thanks

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

    Default

    I don't think that looking at just your paintComponent method will lead us to a solution as more info and code will likely be required. think that you're going to have to distill your code into the smallest bit that compiles, runs, and yet shows your problem, an SSCCE (please see the link). Post this, and we'll be able to reproduce your problem and likely find a solution quickly.

    Much luck!

  12. #12
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

    Default

    Here is a severely cut-down version of my java application. It includes 3 classes and is animated by thread (I kept this part in because it might have something to do with the problem).

    Anyway, thank you for having a look at this!
    Attached Files Attached Files

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

    Default

    Better to place your shortened code into one file and then post that file here with code tags, so that we have to do less work to help you. For the benefit of others, here is your code:
    Java Code:
    import javax.swing.*;
    import java.awt.*;
    
    public class Main extends JFrame {
      JFrame frame;
    
      public Main() {
        frame = new JFrame();
        frame.add(new Test());
        frame.setSize(100, 100);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
      }
    
      public static void main(String[] args) {
        new Main();
      }
    }
    
    class Test extends JPanel implements Runnable {
      private Thread thread;
    
      public Test() {
        add(new MyComponent());
        this.validate();
      }
    
      public void addNotify() {
        super.addNotify();
        thread = new Thread(this);
        thread.start();
      }
    
      public void paint(Graphics g) {
        super.paint(g);
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
      }
    
      public void run() {
        long startTime = System.currentTimeMillis();
        long timeDiff, sleepTime;
        while (true) {
          repaint();
    
          timeDiff = System.currentTimeMillis() - startTime;
          sleepTime = 50 - timeDiff;
    
          if (sleepTime < 0)
            sleepTime = 1;
          try {
            Thread.sleep(sleepTime);
          } catch (InterruptedException e) {
          }
          startTime = System.currentTimeMillis();
        }
      }
    }
    
    class MyComponent extends JComponent {
    
      public void paint(Graphics g) {
        g.setColor(Color.red);
        g.fillRect(0, 0, 100, 100);
        System.out.println("is painting");
      }
    
    }
    I see several problems, but the one that's bothering you the most is that you are creating a JComponent but not allowing it to have any size. Since the JPanel acting as a container uses FlowLayout by default, it will allow any components added to size themselves to their default size which here is 0 by 0, and so you won't see the JComponent at all.

    One solution is to give your JComponent object a preferredSize via setPreferredSize, or give your JPanel a layout that tells the JComponent to fill it up completely, such as BorderLayout.

    There are other serious issues here, including your use of paint rather than paintComponent. Also why the while (true); what is its purpose? Whould a Swing Timer be better here?

  14. #14
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

    Default

    Thank you, thank you, thank you. Sorry, for the inconvenience of the multiple files, next time I'll do what you did.

    The reason I am using this method of timing is because I read somewhere that it provided better results and more accurate timing. Is this true? Because my game heavily is based on solid and constant timing.

    I am using paintComponent() in my actual game, but mistakenly put paint() in this one. But may I ask what the difference is? They both seem to do the same thing.

    Thanks, if you don't hear any more from me on this topic, you've solved my troubles.

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

    Default

    Quote Originally Posted by martypapa View Post
    Thank you, thank you, thank you. Sorry, for the inconvenience of the multiple files, next time I'll do what you did.
    No need to apologize. My suggestions were just that, suggestions, not criticisms.

    The reason I am using this method of timing is because I read somewhere that it provided better results and more accurate timing. Is this true? Because my game heavily is based on solid and constant timing.
    I must plead ignorance here as I don't do game programming. For the simple animations that I do, Swing Timer's work just fine. But I do know for critically timed applications, they're not enough.

    I am using paintComponent() in my actual game, but mistakenly put paint() in this one. But may I ask what the difference is? They both seem to do the same thing.
    In Swing, paint is responsible for painting the component (it calls paintComponent for this), the component's borders, and the component's children. If your paint routine doesn't mess with borders or children, it is best not to override paint. Also, if you use paint, you lose Swing's double buffering capabilities.

    Thanks, if you don't hear any more from me on this topic, you've solved my troubles.
    Best of luck, and nice to have met you.

  16. #16
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

    Default

    Just one more thing, is there a way to layer my components how I like? At the moment on my JPanel, I call super.paint(g) and then I draw an image that I want for the background. I am assuming super.paint(g) is what tells all the components in the JPanel to run the paintComponent() method?

    So basically, what I am asking is whether I can layer my components, but still use the paintComponent() where the component takes care of its own painting.

    Thanks again!

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

  18. #18
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

    Default

    Thanks, but how would I go about layering say for example two components.
    Say I have MyComponent and MyComponent2, and they overlap.
    How would I specify the ordering so that I could make MyComponent2 show up in front of MyComponent?

    Thanks

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

    Default

    If these are widgets, JComponents, then you'd use a JLayeredPane

    If these on the other hand are graphical objects, then you'd probably hold them in an ArrayList or LinkedList and use the same list for drawing and (backwards) for mouse listening.

  20. #20
    martypapa is offline Member
    Join Date
    Feb 2010
    Posts
    21
    Rep Power
    0

Similar Threads

  1. painting problem
    By hannes in forum New To Java
    Replies: 3
    Last Post: 01-17-2010, 11:44 AM
  2. JPanel not always painting everything
    By ekted in forum AWT / Swing
    Replies: 0
    Last Post: 11-26-2009, 11:24 AM
  3. Jpanel painting problem
    By kcakir in forum AWT / Swing
    Replies: 3
    Last Post: 04-15-2009, 10:21 PM
  4. Replies: 1
    Last Post: 01-22-2009, 04:25 PM
  5. Hovering mouse over a button and painting
    By gtraylo in forum AWT / Swing
    Replies: 2
    Last Post: 04-24-2008, 09:33 AM

Posting Permissions

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