-1

I'm writing my own class for notifications (don't mind the code, it was generated by IntelliJ GUI Designer)

public class NotificationWindow extends JWindow {

private JLabel icon;
private JTextArea message;
private JLabel title;
private JPanel mainPanel;
private Spacer spacer1;
private Spacer spacer2;

public NotificationWindow(String ttl, String msg) {

    mainPanel = new JPanel();
    mainPanel.setLayout(new GridLayoutManager(3, 3, new Insets(5, 5, 5, 5), -1, -1));

    icon = new JLabel();
    icon.setIcon(new ImageIcon(getClass().getResource("/resources/employee 64.png")));

    title = new JLabel(ttl);
    title.setFont(
            new Font(title.getFont().getName(), Font.BOLD, title.getFont().getSize()));


    message = new JTextArea(3, 44);
    message.setText(msg);
    message.setOpaque(false);
    message.setFont(message.getFont().deriveFont(12f));
    message.setLineWrap(true);
    message.setWrapStyleWord(true);

    spacer1 = new Spacer();
    spacer2 = new Spacer();

    this.pack();
    this.setSize(400, 80);
    this.setAlwaysOnTop(true);
    this.setVisible(true);

    this.getRootPane().setBorder(
            BorderFactory.createMatteBorder(1, 1, 1, 1, Color.DARK_GRAY));

    Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();

    Insets toolHeight = Toolkit.getDefaultToolkit()
            .getScreenInsets(this.getGraphicsConfiguration());

    this.setLocation(
        scrSize.width - this.getWidth() - 20, 
        scrSize.height - toolHeight.bottom - this.getHeight() - 20);

    this.initUI();
}

private void initUI() {

    mainPanel.add(icon, 
        new GridConstraints(0, 0, 3, 1,
                GridConstraints.ANCHOR_CENTER, 
                GridConstraints.FILL_NONE, 
                GridConstraints.SIZEPOLICY_FIXED,
                GridConstraints.SIZEPOLICY_FIXED,
                null, null, null, 0, false));

    mainPanel.add(title,
        new GridConstraints(0, 1, 1, 2,
                GridConstraints.ANCHOR_WEST, 
                GridConstraints.FILL_NONE, 
                GridConstraints.SIZEPOLICY_FIXED,
                GridConstraints.SIZEPOLICY_FIXED,
                null, null, null, 0, false));

    mainPanel.add(message, 
        new GridConstraints(1, 1, 1, 2,
                GridConstraints.ANCHOR_WEST, 
                GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_FIXED,
                GridConstraints.SIZEPOLICY_FIXED,
                null, null, null, 0, false));

    mainPanel.add(spacer1, 
        new GridConstraints(2, 1, 1, 1,
                GridConstraints.ANCHOR_CENTER,
                GridConstraints.FILL_VERTICAL,
                1,
                GridConstraints.SIZEPOLICY_WANT_GROW,
                null, null, null, 0, false));

    mainPanel.add(spacer2, 
        new GridConstraints(2, 2, 1, 1,
                GridConstraints.ANCHOR_CENTER,
                GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_WANT_GROW,
                1, null, null, null, 0, false));


    this.setContentPane(mainPanel);
    this.repaint();

    // time after which notification will be disappeared
    new Thread(() -> {
        try {
            Thread.sleep(6000);
            dispose();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
}
    }

The idea is that the program will show notification every hour as a reminder to users. For this purposes, I am using ScheduledExecutorService class. I am calling Notification this way (for testing notification called every 20 seconds):

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
        ses.scheduleAtFixedRate(new Runnable() {
            private int i = 1;
            @Override
            public void run() {
                NotificationWindow notificationWindow = 
                    new NotificationWindow(
                        "blah blah", 
                        "Please, " + 
                        "specify the details of the task you're currently working on.");
            }
        }, 10, 20, TimeUnit.SECONDS);

The problem is that notification window sometimes does not render properly. Sometimes it's just frame the same size as notification window should be only with white background without any elements. Where is my mistake?

Leonardo Pina
  • 458
  • 1
  • 7
  • 17
whyiamhere
  • 35
  • 1
  • 4
  • Where does GridLayoutManager come from? That is an Android layout manager not Swing. Are you using another library? I personally only ever use Swing layout managers and never have an issue with them. – markbernard Jun 12 '17 at 13:56
  • @markbernard, GridLayoutManager is the default IntelliJ IDEA GUI Designer layout. I didn't change anything. – whyiamhere Jun 12 '17 at 13:58
  • That means it relies on a library external from Swing. This is not a standard LayoutManager. I am personally hesitant to use non-standard layouts, since there are so many to choose from. – markbernard Jun 12 '17 at 14:55

1 Answers1

2

Sometimes it's just frame the same size as notification window should be only with white background without any elements

Random problems can result when code is not executed on the Event Dispatch Thread (EDT).

I am using ScheduledExecutorService class.

Swing components should be created on the EDT. Code invoked from the ScheduledExecutorService does not run on the EDT.

Instead you should be using a Swing Timer to schedule the event.

Read the Swing tutorial. There are sections on:

  1. Concurrency in Swing - to explain more about the EDT
  2. How to Use Swing Timers
camickr
  • 321,443
  • 19
  • 166
  • 288
  • That is not entirely accurate. You do not have to create your GUI on the EDT. Their activities subsequently are controlled by the EDT (painting, event dispatch, etc). – markbernard Jun 12 '17 at 13:57
  • @markbernard That was the case at one time, but no longer. See https://stackoverflow.com/questions/491323/is-it-safe-to-construct-swing-awt-widgets-not-on-the-event-dispatch-thread. – VGR Jun 12 '17 at 14:31
  • @VGR Thanks for that. I was not aware of this change. – markbernard Jun 12 '17 at 14:51
  • @camickr I tried to remove my down vote but the system won't let me. Sorry. – markbernard Jun 12 '17 at 14:52