Search code examples
javaswingpaintcomponentevent-dispatch-thread

Any way to delay PaintComponent?


I've read through lots of the threads on paintComponent here, most of which making the point that it either is never or almost never necessary (or possible) to choose when paintComponent is called.

In my program, however, sometimes (only sometimes) paintComponent gets called before some of the objects it needs to paint have finished initializing or even sometimes before they've been created, triggering warnings- JOptionPane pop-ups, which surprisingly do not show any of the text they were hard-coded to display in their "message" area. I've read in other places that it's something to do with the EDT, and I've looked into some parts of that but I'm just getting confused. If the main purpose of the EDT is to update the gui, and by default pretty much everything will run in the EDT, then could I tell the program to run all the initialization and update functions in a different thread(s), which I somehow forcibly make run before the EDT runs?

What I'd ideally like to have happen is for paintComponent to wait until a certain point in my code to be run (after a bunch of update functions, regardless of what happens to the screen. After it does get called, it is followed by a pause in which relatively little is going on ( I had been using Thread.sleep() inside a while loop ) and which lasts until the user clicks something - at which point all the necessary functions are run again, followed by paintComponent afterwards, then the sleep() while loop, etc.

From what I understand, I think what I want isn't really possible, so my question is: Do you guys have any ideas of how to get around this?

EDIT: So essentially the program is a college course planner, intended to make it easier for someone to plan out by semester all the courses they have to take before graduation, move those courses around (if possible), and see how all the courses are connected (prerequisites and such). When the program starts, it loads the list of necessary courses from a text file, then loads info about each course from a bunch of individual text files, and arranges them according to their prerequisites. Courses with no prerequisites go in the first semester, courses whose prerequisites have all been added to the first semester get added to the second, and so on until all the courses have been added. When paintComponent runs, it calls a function that assume all of each course's prerequisites exist on the schedule, and if it finds otherwise, it throws an error and displays a JOptionPane message box. When this happens during a normal run of the program (like if I manually add a course before adding its prerequisites), that all works and displays correctly. But sometimes that message box pops up when only some of the courses have been loaded (meaning control is still in the main constructor) and when it does so, the actual string message doesn't show up - only the actual pane, title and ok button do. Heres the line where I display the error box, so you can know that I'm not trying to display a string variable which has the potential of being empty.

JOptionPane.showMessageDialog(this, "Course couldn't be loaded, partially >loaded\ncourses have been removed.", "Error", JOptionPane.OK_OPTION);

It is the "Course couldn't...been removed." part that doesn't get displayed. This is the only JOptionPane I display with the title "Error". This post mentioned what sounds like the same thing happening, except I'm not using any of the things that poster had to fix. So possibly it's irrelevant but I'll add it just in case. JOptionPane.showMessageDialog() shows but without any message?

But to step back a bit, because that box popped up before all the courses had been added, it means that paintComponent was somehow called in the middle of the relevant JPanel's constructor, before a bunch of things had been initialized. I added a bunch of println() statements to make sure that that is true. Is it normal for that to happen, and if so, is there a way to fix it without simply using Andrew Thompson's advice?

After thinking though it a bit, I think that because the project is 3200 lines long and relies to a huge extent on text files, I'm really not sure how to ( or if I can) make a SSCCE for it..

If any specific pieces would be helpful I'll gladly add those but if this problem isn't clearly some standard issue I'm getting wrong, then I'll just add that flag and keep looking for bugs.

Thanks for your help


Solution

  • Declare a flag as a class attribute. Check it in the paint method. Change it at the end of the initialization.

    class XandYandZ extends JComponent {
    
      boolean initializationFinished = false;
    
      public XandYandZ() {
        // long initialisation..
        initializationFinished = true;
      }
    
      public void paintComponent(Graphics g) {
        if (!initializationFinished) return;
        // .. paint ..