Results 1 to 8 of 8
  1. #1
    TimHuey is offline Member
    Join Date
    Aug 2009
    Posts
    50
    Rep Power
    0

    Default JDialog isn't Showing till return from eventListener

    I used the GUI app template of Netbeans and I'm having some strange behavior with a calendar object that isn't showing up right away.

    Java Code:
    private void bidLinesContainValueChanged(javax.swing.event.ListSelectionEvent evt) {                                             
        displayaline((String) ((JList) evt.getSource()).getSelectedValue());
    Java Code:
       private void displayaline(String lineselected) {
                        
                    .....
           
                    // *** Calendar
                    if(viewCalendar){
                        Point rv = new Point(calDialog.getLocation());
                        
                        if(calDialog.isShowing()){
                            calDialog.dispose();
                        }
                        calDialog = new JDialog(mainFrame,"test");
                        MonthlyCalendar ch = new MonthlyCalendar(((LineObject)lines.get(i)).getWorkSched(), dayToStart); //firstDayOfLine);
                        GregorianCalendar gc1 = new GregorianCalendar(2009, Calendar.MAY, 1, 0, 0,0);
                        Date d1 = gc1.getTime();
                        ch.setDate(d1);//new Date(d1));
                        calDialog.getContentPane().add(ch);
                        calDialog.setUndecorated(true);
    
                        MoveMouseListener mml = new MoveMouseListener(ch);
                        ch.addMouseListener(mml);
                        ch.addMouseMotionListener(mml);
    
                        calDialog.pack();
                        calDialog.setAlwaysOnTop(true);
                        calDialog.setLocation(rv);
                        calDialog.setVisible(true);
                    }
                }
            }
             bidLinesContain.requestFocus();
        }

    Java Code:
    public class MonthlyCalendar extends JPanel {
    
        protected String[] dutyCalendar;
        protected Image background = new ImageIcon(System.getProperty("user.home") + System.getProperty("file.separator") + "background.png").getImage();
        protected Image highlight = new ImageIcon(System.getProperty("user.home") + System.getProperty("file.separator") + "highlightYellow.png").getImage();
        protected Image day_img = new ImageIcon(System.getProperty("user.home") + System.getProperty("file.separator") + "day.png").getImage();
        Image greenDay = new ImageIcon(System.getProperty("user.home") + System.getProperty("file.separator") + "greenday.png").getImage();
        protected SimpleDateFormat month = new SimpleDateFormat("MMMM");
        protected SimpleDateFormat year = new SimpleDateFormat("yyyy");
        protected SimpleDateFormat day = new SimpleDateFormat("d");
        protected Date date = new Date();
        protected int startDayOfWeek;
    
        public void setDate(Date date) {
            this.date = date;
        }
    
        public MonthlyCalendar(String[] workSched, int firstDay) {
            this.dutyCalendar = workSched;
            this.startDayOfWeek = firstDay;
            this.setPreferredSize(new Dimension(210, 200));
        }
    
        @Override
        public void paintComponent(Graphics g) {
            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g.drawImage(background, 0, 0, null);
            g.setColor(Color.blue);
            g.setFont(new Font("SansSerif", Font.PLAIN, 10));
            g.drawString(month.format(date), 10, 18);
            g.setColor(Color.blue);
            g.drawString(year.format(date), 170, 18);
    
            Calendar today = Calendar.getInstance();
            today.setTime(date);
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.set(Calendar.DATE, 0);
            
            boolean isACity = false;
            for (int week = 0; week < 6; week++) {
                for (int d = 0; d < 7; d++) {
                    if ((week == 0) && (d < startDayOfWeek)) {d = startDayOfWeek;}  //this is the shift of the first start day to match with day of week, think of d as x (graphing x,y)
                    Image img = day_img;
                    g.drawImage(img, d * 30 + 4, week * 29 + 29, null);
                    try {
                        Integer.parseInt(dutyCalendar[count]);
                    } catch (NumberFormatException e) {
                        isACity = true;
                    }
                    if (isACity && dutyCalendar[count] != null) {
                        g.drawImage(highlight, d * 30 + 0 + 3, week * 29 + 35, null);
                        isACity = false;
                    }
                    if (dutyCalendar[count] != null) {
                        g.drawString(dutyCalendar[count], d * 30 + 4 + 1, week * 29 + 29 + 20);
                    }
                    g.setColor(Color.blue);
                    g.setFont(new Font("SansSerif", Font.PLAIN, 9));
                    count++;
                }
    
                cal.add(Calendar.DATE, +1);
            }
        }
    }
    
    ...
    The firing event is when the user clicks on a value in a list and it fires "BidLinesContainsValueChange." Funny thing is, the calendar isn't displayed until that event is done and returns. I even did this:

    Java Code:
    private void bidLinesContainValueChanged(javax.swing.event.ListSelectionEvent evt) {                                             
        displayaline((String) ((JList) evt.getSource()).getSelectedValue());
         for(int pause =0; pause < 50000; pause++){System.out.println("waiting");}
    }

    And WOW, it prints out "waiting" 50000 times and then after that completes it shows the calendar even though it was done way before then in the chain of events. So this leads me to conclude that there is some kinda thread issue or other issue causing the delay. I rate this problem as "Annoying" not "Life Threatening". It causes a slight flicker in the image as it updates the calendar from value to value. I've tried double buffering but can't figure out how to make it work with this design.

    And now to my question. Is there a command I can place in "displayaLine" that will force the calendar to show up prior to returning?
    Last edited by TimHuey; 09-10-2009 at 04:02 PM.

  2. #2
    TimHuey is offline Member
    Join Date
    Aug 2009
    Posts
    50
    Rep Power
    0

    Default

    Not to be one that just says: "Fix my code," I do have a solution. It's low tech and I'm a bit embarrassed but my knowledge of Java is so infantile right now that I can only work with what I got. I will post the code fix later, but I was hoping to be pointed in the correct direction, not just a bandaid.

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

    Default

    Funny thing is, the calendar isn't displayed until that event is done and returns.
    What exactly do you mean by this?

    And WOW, it prints out "waiting" 50000 times and then after that completes it shows the calendar even though it was done way before then in the chain of events.
    this behavior is expected any time you step on the Swing Event Dispatch Thread (EDT) as your loop is doing. I believe that this has nothing to do with your problem.

  4. #4
    TimHuey is offline Member
    Join Date
    Aug 2009
    Posts
    50
    Rep Power
    0

    Default

    It won't show the calendar until it is done with the "event listener". As a matter of fact, most changes in graphics states won't show until returning from whatever process they were created in. I've even tried the .show and .update calls. I can't force them to update until the mainFrame gets control again.

    I get a big lag in the graphic changes between differing calendars. Something that is supposed to be smooth isn't. It flickers more than just what would be expected without double buffering. I've tried not disposing of the calendar before redrawing on the JDialog but couldn't get that method to work.

    I found that if I just let one JDialog box open over the old one it never disappears and the flicker is gone. Unfortunately, there are now 2 calendars open on top of each other. The appropriate one is showing but if it's moved you see the old one. And if the user keeps opening new calendars you get a bunch of old calendars on the desktop. What I did was in the moveMouseListener I modified it to send a reference to the old Calendar. So if the user closed or moved the new calendar it would remove the old one. Obviously, if the user had clicked on the new calendar it was by definition now visible and no flicker would occur if the old one was disposed. Not very hightech, it doesn't really solve the thread issue I'm having or not being able to figure out how to implement double buffering on this design but it worked. I get absolutely no flicker this way.

    Java Code:
     MoveMouseListener mml = new MoveMouseListener(ch, hiddenCalendar);
                        ch.addMouseListener(mml);
                        ch.addMouseMotionListener(mml);
    Don't laugh, but if you see the PROPER way of fixing this flicker could you show me? If it is a line or two of code. If its a major rework then don't worry. I learn alot by seeing. More by doing. But I can't seem to understand the double buffering examples on the net or some of the thread discussions. I think the biggest issue is that NetBeans has designed my Application structure and I don't have enough of a grasp of threads or java to change the examples to fit the NetBeans structure. I'm not complaining about NetBeans, my project would never have been possible without it.
    Last edited by TimHuey; 09-11-2009 at 04:58 AM.

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

    Default

    It may be a threading issue, but without seeing a small program that can reproduce your problem, it would be hard for me to tell.

    Is your event listener in any way performing any time or CPU-intensive processing? Is it accessing a database or retrieving anything over the internet or over a network? If so, then you may want to use background threads such as can be obtained by using a SwingWorker object.

    Edit: you're uploading images in that event code when the calendar class is initialized. I recommend either doing this in a SwingWorker's doInBackground method or else if you could load the images into your app earlier, before the event occurs your problem wouldn't occur.

    Edit 2: look here: Concurrency In Swing
    Last edited by Fubarable; 09-11-2009 at 07:55 PM.

  6. #6
    TimHuey is offline Member
    Join Date
    Aug 2009
    Posts
    50
    Rep Power
    0

    Default

    Ugh, I've read that section Threads at least 3 times. I keep coming back to it as I learn more about Java, but it is still above my understanding. Thanks for the help Fubarable but I'm gonna have to put off working on this small issue for a while. Since I have it working "enough" now. It's not perfect and that bothers me but I have to move on or I will get stuck here.

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

    Default

    Here's an example of what I meant. Not sure if it will help you, but hopefully it will.
    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class SlowAction {
      private static final String LOADING = "Loading...";
      private static final String OPEN_FAST = "Open Fast";
      private static final String OPEN_SLOW = "Open Slow";
      private JPanel mainPanel = new JPanel();
      private PicPanel fastPanel = new PicPanel();
      private JFrame frame;
    
      public SlowAction(JFrame frame) {
        this.frame = frame;
        final JButton openFast = new JButton(LOADING);
        openFast.setActionCommand(OPEN_FAST);
        final JButton openSlow = new JButton(OPEN_SLOW);
        
        BtnListener btnlistener = new BtnListener();
        openFast.addActionListener(btnlistener);
        openSlow.addActionListener(btnlistener);
        openFast.setEnabled(false);
        
        mainPanel.add(openFast);
        mainPanel.add(openSlow);
        mainPanel.setPreferredSize(new Dimension(300, 100));
        
        new SwingWorker<Void, Void>(){
    
          protected Void doInBackground() throws Exception {
            fastPanel.loadImage();
            return null;
          }
          
          protected void done() {
            openFast.setText(OPEN_FAST);
            openFast.setEnabled(true);
          }
          
        }.execute();
      }
    
      public JComponent getComponent() {
        return mainPanel;
      }
      
      private class BtnListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
          String actionCommand = e.getActionCommand();
          if (actionCommand.equals(OPEN_FAST)) {
            JDialog dialog = new JDialog(frame, "Fast Dialog", true);
            dialog.getContentPane().add(fastPanel);
            dialog.pack();
            dialog.setLocationRelativeTo(null);
            dialog.setVisible(true);
            
          } else if (actionCommand.equals(OPEN_SLOW)) {
            PicPanel slowPanel = new PicPanel();
            slowPanel.loadImage();
            
            JDialog dialog = new JDialog(frame, "Slow Dialog", true);
            dialog.getContentPane().add(slowPanel);
            dialog.pack();
            dialog.setLocationRelativeTo(null);
            dialog.setVisible(true);
            dialog.dispose();
          }
        }
      }
    
      private static void createAndShowUI() {
        JFrame frame = new JFrame("Slow Fast Action");
        frame.getContentPane().add(new SlowAction(frame).getComponent());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
          public void run() {
            createAndShowUI();
          }
        });
      }
    }
    
    @SuppressWarnings("serial")
    class PicPanel extends JPanel {
      private static final String IMAGE_URL = "http://upload.wikimedia.org/wikipedia/"
          + "commons/9/94/F-16_Fighting_Falcon_%282152048406%29.jpg";
      private static final int PP_WIDTH = 800;
      private BufferedImage bigImage;
    
      public void loadImage() {
        URL imageURL;
        try {
          imageURL = new URL(IMAGE_URL);
          bigImage = ImageIO.read(imageURL);
        } catch (MalformedURLException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        }
        if (bigImage != null) {
          int iWidth = bigImage.getWidth();
          int iHeight = bigImage.getHeight();
          int w = PP_WIDTH;
          int h = (iHeight * w) / iWidth;
          setPreferredSize(new Dimension(w, h));
        }
      }
      
      protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (bigImage != null) {
          g.drawImage(bigImage, 0, 0, getWidth(), getHeight(), this);
        }
      }
    }
    The actionlistener for OPEN_FAST loads a JPanel with image that was loaded on program start-up. The OPEN_SLOW loads the image at the time that the button was pressed.

    Note that since images take up a fair amount of memory, your program can only hold so many without running out of memory.
    Last edited by Fubarable; 09-12-2009 at 06:58 PM.

  8. #8
    TimHuey is offline Member
    Join Date
    Aug 2009
    Posts
    50
    Rep Power
    0

    Default

    I learn from all code examples. It's nice when you are so new. Everything is a learning experience. Thanks Furarable.

Similar Threads

  1. Java voucher available in Hyderabad valid till 24th Jan
    By qcsurya in forum Java Certification
    Replies: 2
    Last Post: 09-25-2011, 10:54 PM
  2. [SOLVED] imput data from HTML till an Applet?
    By AlejandroPe in forum New To Java
    Replies: 0
    Last Post: 03-31-2009, 09:47 AM
  3. have an eventlistener change values
    By klmdb in forum New To Java
    Replies: 1
    Last Post: 03-20-2009, 12:42 AM
  4. setLocation on a JDialog is ignored
    By ScottVal in forum AWT / Swing
    Replies: 7
    Last Post: 01-13-2009, 07:35 AM
  5. help with jdialog
    By leonard in forum AWT / Swing
    Replies: 1
    Last Post: 08-05-2007, 05:37 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
  •