Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 16 of 16

Thread: Nimbus PLAF: and a double call to repaint() inside a runnable interface

  1. #1
    Java kindergarten chronoz13's Avatar
    Join Date
    Mar 2009
    Location
    Philippines
    Posts
    659
    Thanks
    177
    Thanked 30 Times in 28 Posts

    Default Nimbus PLAF: and a double call to repaint() inside a runnable interface

    ok let me put the codes first because I might be stating everything as bizarre as i see it

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.ArrayList;
     
    public class DoubleCallToRepaintWithNimbusPLAFBizzareProblem {
     
        private java.util.List<String> words;
        private boolean stopSlide;
        private int wordX;
        private int head;
        private int tail;
        private JButton slide;
     
        public DoubleCallToRepaintWithNimbusPLAFBizzareProblem() {
     
            words = new ArrayList<String>();
            initWordList();
            tail = words.size() - 1;
            stopSlide = true;
        }
     
        public void initWordList() {
     
            words.add("F I R S T          S L I D E");
            words.add("S E C O N D          S L I D E");
            words.add("T H I R D          S L I D E");
            words.add("F O U R T H          S L I D E");
        }
     
        public void showWindow() {
     
            Panel p = new Panel();
            JFrame f = new JFrame();
     
            slide = new JButton("Slide");
            slide.addActionListener(new ActionListener() {
     
                @Override
                public void actionPerformed(ActionEvent e) {
     
                    stopSlide = false;
                    slide.setEnabled(false);
                }
            });
            p.add(slide);
     
            p.setPreferredSize(new Dimension(700, 450));
     
            f.getContentPane().add(p);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setResizable(false);
            f.setVisible(true);
        }
     
        private class Panel extends JPanel implements Runnable {
     
            private Thread runner;
            private boolean stopThread;
     
            public Panel() {
     
                runner = new Thread(this);
                runner.start();
            }
     
            @Override
            public void paintComponent(Graphics g) {
     
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g;
     
                g2d.setFont(new Font("Monospaced", Font.BOLD, 35));
                g2d.drawString(words.get(head), wordX, 220);
                g2d.drawString(words.get(tail), wordX + 900, 220);
            }
     
            @Override
            public void run() {
     
                while (!stopThread) {
     
                    try {
     
                        Thread.sleep(5);
     
                        if (!stopSlide) {
     
                            if (wordX >= -900) {
     
                                wordX -= 5;
                            }
     
                            if (wordX < -900 && !stopSlide) {
     
                                wordX = 0;
                                head = tail;
                                tail--;
     
                                stopSlide = true;
     
                                // set enabled again, and i see in the API
                                // there is a call to repaint() inside of it
                                slide.setEnabled(true);
     
                                // when tail becomes negative 1, 
                                // make it the size() - 1 of the list 
                                // imediately before the repaint() call below
                                if (tail < 0) {
     
                                    tail = words.size() - 1;
                                }
                            }
                        }
     
                        repaint();
                    }
                    catch (InterruptedException e) {
     
                        Thread.currentThread().interrupt();
                        e.printStackTrace();
                    }
                }
            }
        }
     
        public static void main(String[] args) {
     
            try {
     
                for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
     
                    if ("Nimbus".equals(info.getName())) {
     
                        UIManager.setLookAndFeel(info.getClassName());
                        break;
                    }
                }
            }
            catch (UnsupportedLookAndFeelException e) {
     
                e.printStackTrace();
            }
            catch (ClassNotFoundException e) {
     
                e.printStackTrace();
            }
            catch (InstantiationException e) {
     
                e.printStackTrace();
            }
            catch (IllegalAccessException e) {
     
                e.printStackTrace();
            }
     
            new DoubleCallToRepaintWithNimbusPLAFBizzareProblem().showWindow();
        }
    }

    i tried to reproduce the thing i encoutered as small as possible , so this is a far as it goes.

    - when i do a slide, the int values(head and tail) that calls the values in the word lists, decrements from size() - 1 to 0,
    - when it reaches the critical point -1 (tail variable), inside the run method, i have an if part that turns the tail into a positive value that i want immediately before the call to repaint() below it, so i will be able to avoid a -1 out of bounds exception.
    - why do i get a -1 exception?
    - i tried to debug it for a couple of hours then i pin-point the problem(first assessment)

    FIRST ASSESSMENT:
    - every time I slide, I disable the slide button when a sliding is occuring, for every succesfull slide animations, i enable the slide button again, as you can see, i put that setEnabled(true) call inside the run() method, JUST BEFORE the if-part that turns the tail variable to something positive before a repainting again, repaint()

    - from there i manage to see that there is another repaint() call inside the JComponent setEnabled() method - I dig in

    - and from there i realize that when i have a -1 tail, that setEnabled() call calls a repaint() inside of it that repaints everything, and i thought that it might affect the other painting events(my sliding words), thats why i get a -1 outOfBounds(ONCE. only ONCE) it proceeds on the if-part that sets the tail a positive value(not a -1), then proceed to my own painting(the repaint() below of it) and good to go again.

    - what i did is i placed the call to .setEnabled() (slide.setEnabled(true)) below the if-part that sets the tail to something positive value, and everything works fine, thats why i am, somehow confident with my understanding that there is a 2 call to repaint() that affects everything. one is inside the setEnabled() of JComponent and the other one is that i have

    - now i tried to reproduce again the problem WITHOUT THE NIMBUS PLAF INSTALLATION, and everything i said above doesnt happen

    - now the second assesment goes

    SECOND ASSESSMENT:

    - lets go back to square 1, all those things i said above, removing the installed NIMBUS PLAF, no error has occured


    what is going on?, i might be wrong on something(maybe all) and i admit that Im doing a concurrency in an appropriate way. But please.. i need some assitance. Is using Nimbus plaf or installing another PLAF is risky? or calling a swing instance method with a repaint() inside of it in a run method with another repaint() is dangerous? , please ask me if my statements are hard to understand. ill try to explain as more clearly as possible. thank you in advance


  2. #2
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    why do i get a -1 exception?
    Please post the full text of the error message.

    Please explain how you get the error. When I execute the code there is no error. I pressed the SLide button many times and the text on the screen "slides".
    Last edited by Norm; August 9th, 2012 at 08:45 AM.
    If you don't understand my answer, don't ignore it, ask a question.

  3. #3
    Java kindergarten chronoz13's Avatar
    Join Date
    Mar 2009
    Location
    Philippines
    Posts
    659
    Thanks
    177
    Thanked 30 Times in 28 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
    at java.util.ArrayList.get(ArrayList.java:324)
    at xError_Samplesx.DoubleCallToRepaintWithNimbusPLAFB izzareProblem$Panel.paintComponent(DoubleCallToRep aintWithNimbusPLAFBizzareProblem.java:94)
    at javax.swing.JComponent.paint(JComponent.java:1029)
    at javax.swing.JComponent.paintToOffscreen(JComponent .java:5124)
    at javax.swing.RepaintManager$PaintManager.paintDoubl eBuffered(RepaintManager.java:1491)
    at javax.swing.RepaintManager$PaintManager.paint(Repa intManager.java:1422)
    at javax.swing.RepaintManager.paint(RepaintManager.ja va:1225)
    at javax.swing.JComponent._paintImmediately(JComponen t.java:5072)
    at javax.swing.JComponent.paintImmediately(JComponent .java:4882)
    at javax.swing.RepaintManager.paintDirtyRegions(Repai ntManager.java:786)
    at javax.swing.RepaintManager.paintDirtyRegions(Repai ntManager.java:714)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Re paintManager.java:694)
    at javax.swing.RepaintManager.access$700(RepaintManag er.java:41)
    at javax.swing.RepaintManager$ProcessingRunnable.run( RepaintManager.java:1636)
    at java.awt.event.InvocationEvent.dispatch(Invocation Event.java:209)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.j ava:646)
    at java.awt.EventQueue.access$000(EventQueue.java:84)
    at java.awt.EventQueue$1.run(EventQueue.java:607)
    at java.awt.EventQueue$1.run(EventQueue.java:605)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectio nPrivilege(AccessControlContext.java:87)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java: 616)
    at java.awt.EventDispatchThread.pumpOneEventForFilter s(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(E ventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarch y(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispa tchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispa tchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThre ad.java:122)
    BUILD STOPPED (total time: 11 seconds)
    oooh ok.. thank you for checking it.. hmmm.. i really dont have any more idea how did i get the error on my part.. thats the best thing i can do to reproduce it.. i got the exception thrown pointing at the paintComponent() body, when it is trying to access one of the strings inside the List

  4. #4
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    There must be a hole in your logic that allows the value of the arg to the get() method to be -1.
    Look at line 94 to see if the variable with the bad value is head or tail.
    Then look at the code to see how that variable can get a value of -1. Add some println statements that print out its value to see where/when it gets different values.
    If you don't understand my answer, don't ignore it, ask a question.

  5. #5
    Java kindergarten chronoz13's Avatar
    Join Date
    Mar 2009
    Location
    Philippines
    Posts
    659
    Thanks
    177
    Thanked 30 Times in 28 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    ok ok ill look into it even more, thank you... but does it also throw a -1 exception when you run it?

  6. #6
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    Yes, I get the Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
    some times.
    Have you added some println statements to the code? What is printed out just before the AIOOBE is thrown?
    Which variable has the -1 value? When does that variable have the value of -1?
    If you don't understand my answer, don't ignore it, ask a question.

  7. #7
    Java kindergarten chronoz13's Avatar
    Join Date
    Mar 2009
    Location
    Philippines
    Posts
    659
    Thanks
    177
    Thanked 30 Times in 28 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    if (wordX < -900 && !stopSlide) {
     
                                wordX = 0;
                                head = tail;
                                tail--;
                                stopSlide = true;
     
                                slide.setEnabled(true);
     
                                System.out.println("Before the If : " + tail);
     
                                if (tail < 0) {
     
                                    tail = words.size() - 1;
                                }
     
                                System.out.println("After the If but before repaint again: " + tail);
                            }
                        }
     
                        repaint(); // before calling this repaint make sure tail is positive

    yes this is what i did before concluding those things i said above, i always think that the tail will always be something positive(i.e 3) before calling that repaint() below, so i wont get a indexOutOfBounds pointing to the paintComponent() method, i really dont get why do i get that exception

    then i get this output

    i excluded the same printed exception
    Before the If : -1
    After the If but before repaint again: 3

  8. #8
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    What are the values of tail before the exception happens?
    Please copy all of the debug print out including the text of the error message here.

    Is the value of tail always the same when the exception happens?
    If you don't understand my answer, don't ignore it, ask a question.

  9. #9
    Java kindergarten chronoz13's Avatar
    Join Date
    Mar 2009
    Location
    Philippines
    Posts
    659
    Thanks
    177
    Thanked 30 Times in 28 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    What are the values of tail before the exception happens?
    the tail starts to the size of the list which is 3(4 - 1), and it decrements as the panel repaints(), tail--;

    Is the value of tail always the same when the exception happens?
    actually no, it only happens when it is negative 1, which i didnt expect will occur, because i have an if part that will change it from being negative just before the repaint


    i added another println() before the slide.setEnabled(true) statement
    if (wordX < -900 && !stopSlide) {
     
                                wordX = 0;
                                head = tail;
                                tail--;
                                System.out.println("Before enabling the button: " + tail);
                                stopSlide = true;
     
                                slide.setEnabled(true);
     
                                System.out.println("Before the If : " + tail);
     
                                if (tail < 0) {
     
                                    tail = words.size() - 1;
                                }
     
                                System.out.println("After the If but before repaint again: " + tail);
                                System.out.println("");
                            }
                        }
     
                        repaint(); // before calling this repaint make sure tail is positive
    Before enabling the button: 2
    Before the If : 2
    After the If but before repaint again: 2
     
    Before enabling the button: 1
    Before the If : 1
    After the If but before repaint again: 1
     
    Before enabling the button: 0
    Before the If : 0
    After the If but before repaint again: 0
     
    Before enabling the button: -1
    Before the If : -1
    After the If but before repaint again: 3
     
    Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
    	at java.util.ArrayList.get(ArrayList.java:324)
    	at textQuiz7Continents.TESTS.DoubleCallToRepaintWithNimbusPLAFBizzareProblem$Panel.paintComponent(DoubleCallToRepaintWithNimbusPLAFBizzareProblem.java:87)
    	at javax.swing.JComponent.paint(JComponent.java:1029)
    	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5124)
    	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1491)
    	at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1422)
    	at javax.swing.RepaintManager.paint(RepaintManager.java:1225)
    	at javax.swing.JComponent._paintImmediately(JComponent.java:5072)
    	at javax.swing.JComponent.paintImmediately(JComponent.java:4882)
    	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:786)
    	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
    	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:694)
    	at javax.swing.RepaintManager.access$700(RepaintManager.java:41)
    	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1636)
    	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:646)
    	at java.awt.EventQueue.access$000(EventQueue.java:84)
    	at java.awt.EventQueue$1.run(EventQueue.java:607)
    	at java.awt.EventQueue$1.run(EventQueue.java:605)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
    	at java.awt.EventQueue.dispatchEvent(EventQueue.java:616)
    	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
    BUILD STOPPED (total time: 10 seconds)

    im puzzled that when i remove the statement
    slide.setEnabled(true)
    everything seems to work fine..

  10. #10
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,139
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    It could be the call to setEnabled() lets the Swing thread call the paintComponent() method on another thread BEFORE the code corrects the value of trail away from -1. Move the setEnabled() call AFTER trail's value has been corrected.

    You don't need to call repaint if no values have changed. Check that repaint is called only if a change in the locations has been made.
    If you don't understand my answer, don't ignore it, ask a question.

  11. The Following User Says Thank You to Norm For This Useful Post:

    chronoz13 (August 10th, 2012)

  12. #11
    Java kindergarten chronoz13's Avatar
    Join Date
    Mar 2009
    Location
    Philippines
    Posts
    659
    Thanks
    177
    Thanked 30 Times in 28 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    It could be the call to setEnabled() lets the Swing thread call the paintComponent() method on another thread BEFORE the code corrects the value of trail away from -1
    thats it! thats also what i thought, im not just quite sure enough without having the same assesment, but.. how about the nimbus plaf? even if i dont move that setEnabled() else where, when i remove the nimbus plaf installation everything works fine.. i dont know if this is too much to ask..

  13. #12
    Java kindergarten chronoz13's Avatar
    Join Date
    Mar 2009
    Location
    Philippines
    Posts
    659
    Thanks
    177
    Thanked 30 Times in 28 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    something might be happening differently in the swing thread when a look-and-feel is installed. everything works fine if i just remove the plaf.

  14. #13
    Administrator copeg's Avatar
    Join Date
    Oct 2009
    Location
    US
    Posts
    5,318
    Thanks
    181
    Thanked 833 Times in 772 Posts
    Blog Entries
    5

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    Do not call Swing methods from a thread other than the EDT, unless the method is explicitly documented as being thread safe. Your call to setEnabled is done from a different thread. Dispatch this to the EDT using SwingUtilities. Some LAF's may be more tolerable of things such as this, others are not.

  15. The Following User Says Thank You to copeg For This Useful Post:

    chronoz13 (August 10th, 2012)

  16. #14
    Java kindergarten chronoz13's Avatar
    Join Date
    Mar 2009
    Location
    Philippines
    Posts
    659
    Thanks
    177
    Thanked 30 Times in 28 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    oh by the way, what do you mean by
    Dispatch this to the EDT using SwingUtilities
    ?

  17. #15
    Administrator copeg's Avatar
    Join Date
    Oct 2009
    Location
    US
    Posts
    5,318
    Thanks
    181
    Thanked 833 Times in 772 Posts
    Blog Entries
    5

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    Quote Originally Posted by chronoz13 View Post
    oh by the way, what do you mean by ?
    You can send a Runnable to the EDT using SwingUtilties

    public class Runner implements Runnable{
         public void run(){
              System.out.println("This is my thread");
              SwingUtilities.invokeLater(new Runnable(){//the content within the passed Runnable will be executed on the Event Dispatch Thread
                   public void run(){
                        myButton.setEnabled(false);
                        System.out.println("Is this on the EDT? " + SwingUtilities.isEventDispatchThread());
                  }
              }
         }
    }

    Based upon the code you posted, you could also use a javax.swing.Timer

  18. The Following User Says Thank You to copeg For This Useful Post:

    chronoz13 (August 11th, 2012)

  19. #16
    Java kindergarten chronoz13's Avatar
    Join Date
    Mar 2009
    Location
    Philippines
    Posts
    659
    Thanks
    177
    Thanked 30 Times in 28 Posts

    Default Re: Nimbus PLAF: and a double call to repaint() inside a runnable interface

    thank you again so much

Similar Threads

  1. Replies: 1
    Last Post: August 4th, 2012, 10:02 AM
  2. Replies: 0
    Last Post: November 16th, 2011, 08:29 AM
  3. How to make these beautiful JPanels for Nimbus look and feel ?
    By Sarabjeet Singh in forum AWT / Java Swing
    Replies: 1
    Last Post: June 10th, 2011, 05:13 PM
  4. Bold font in JTabbedpane in Nimbus L&F
    By sponarun in forum What's Wrong With My Code?
    Replies: 0
    Last Post: February 28th, 2011, 02:09 AM
  5. JTable gridlines not showing in a nimbus L&F
    By chronoz13 in forum AWT / Java Swing
    Replies: 0
    Last Post: February 22nd, 2010, 07:45 AM