getLocation NullPointerException JFrame

时间:2015-01-17 16:42:55

标签: java swing nullpointerexception toast

我遇到了问题,无法解决。我正在创建一个包含多个JFrame的程序,并希望弹出窗口显示为Android的Toast。我找到了一个可以帮助我做到这一点的课程。该类有一个方法,它采用JFrame的位置来创建Toast。问题是,当我单独运行JFrame时,Toast工作正常,但是当我运行完整程序时,JFrame调用另一个JFrame的按钮,获取JFrame位置以创建Toast的方法显示NullPointerException,如作为参数指定的JFrame为null。所以无法获得位置,但单独工作。怎么了?谁能帮助我?感谢。

Toast代码:

public class Toast extends JDialog {
private static final long serialVersionUID = -1602907470843951525L;

public enum Style {
    NORMAL, SUCCESS, ERROR
};

public static final int LENGTH_SHORT = 3000;
public static final int LENGTH_LONG = 6000;
public static final Color ERROR_RED = new Color(121, 0, 0);
public static final Color SUCCESS_GREEN = new Color(22, 127, 57);
public static final Color NORMAL_BLACK = new Color(0, 0, 0);

private final float MAX_OPACITY = 0.8f;
private final float OPACITY_INCREMENT = 0.05f;
private final int FADE_REFRESH_RATE = 20;
private final int WINDOW_RADIUS = 15;
private final int CHARACTER_LENGTH_MULTIPLIER = 7;
private final int DISTANCE_FROM_PARENT_TOP = 100;

private JFrame mOwner;
private String mText;
private int mDuration;
private Color mBackgroundColor = Color.BLACK;
private Color mForegroundColor = Color.WHITE;

public Toast(JFrame owner) {
    super(owner);
    mOwner = owner;
}

private void createGUI() {
    setLayout(new GridBagLayout());
    addComponentListener(new ComponentAdapter() {
        @Override
        public void componentResized(ComponentEvent e) {
            setShape(new RoundRectangle2D.Double(0, 0, getWidth(),
                    getHeight(), WINDOW_RADIUS, WINDOW_RADIUS));
        }
    });

    setAlwaysOnTop(true);
    setUndecorated(true);
    setFocusableWindowState(false);
    setModalityType(ModalityType.MODELESS);
    setSize(mText.length() * CHARACTER_LENGTH_MULTIPLIER, 25);
    getContentPane().setBackground(mBackgroundColor);

    JLabel label = new JLabel(mText);
    label.setForeground(mForegroundColor);
    add(label);
}

public void fadeIn() {
    final Timer timer = new Timer(FADE_REFRESH_RATE, null);
    timer.setRepeats(true);
    timer.addActionListener(new ActionListener() {
        private float opacity = 0;

        @Override
        public void actionPerformed(ActionEvent e) {
            opacity += OPACITY_INCREMENT;
            setOpacity(Math.min(opacity, MAX_OPACITY));
            if (opacity >= MAX_OPACITY) {
                timer.stop();
            }
        }
    });

    setOpacity(0);
    timer.start();

    setLocation(getToastLocation());
    setVisible(true);
}

public void fadeOut() {
    final Timer timer = new Timer(FADE_REFRESH_RATE, null);
    timer.setRepeats(true);
    timer.addActionListener(new ActionListener() {
        private float opacity = MAX_OPACITY;

        @Override
        public void actionPerformed(ActionEvent e) {
            opacity -= OPACITY_INCREMENT;
            setOpacity(Math.max(opacity, 0));
            if (opacity <= 0) {
                timer.stop();
                setVisible(false);
                dispose();
            }
        }
    });

    setOpacity(MAX_OPACITY);
    timer.start();
}

private Point getToastLocation() {
    System.out.println(mOwner);
    Point ownerLoc = mOwner.getLocation();
    int x = (int) (ownerLoc.getX() + ((mOwner.getWidth() - this.getWidth()) / 2));
    int y = (int) (ownerLoc.getY() + DISTANCE_FROM_PARENT_TOP);
    return new Point(x, y);
}

public void setText(String text) {
    mText = text;
}

public void setDuration(int duration) {
    mDuration = duration;
}

@Override
public void setBackground(Color backgroundColor) {
    mBackgroundColor = backgroundColor;
}

@Override
public void setForeground(Color foregroundColor) {
    mForegroundColor = foregroundColor;
}

public static Toast makeText(JFrame owner, String text) {
    return makeText(owner, text, LENGTH_SHORT);
}

public static Toast makeText(JFrame owner, String text, Style style) {
    return makeText(owner, text, LENGTH_SHORT, style);
}

public static Toast makeText(JFrame owner, String text, int duration) {
    return makeText(owner, text, duration, Style.NORMAL);
}

public static Toast makeText(JFrame owner, String text, int duration,
        Style style) {
    Toast toast = new Toast(owner);
    toast.mText = text;
    toast.mDuration = duration;

    if (style == Style.SUCCESS)
        toast.mBackgroundColor = SUCCESS_GREEN;
    if (style == Style.ERROR)
        toast.mBackgroundColor = ERROR_RED;
    if (style == Style.NORMAL)
        toast.mBackgroundColor = NORMAL_BLACK;

    return toast;
}

public void display() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                createGUI();
                fadeIn();
                Thread.sleep(mDuration);
                fadeOut();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }).start();
}

JFrame代码:

public class MenuAtendente extends JFrame {

private JPanel contentPane;
private static JLabel lblInfo;
static MenuAtendente frame;

/**
 * Launch the application.
 */

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                frame = new MenuAtendente();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public MenuAtendente() {
    setTitle("SGTA - <Nome da Academia>");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JFrame teste = frame;
    setBounds(100, 100, 663, 449);
    setLocationRelativeTo(null);
    setResizable(false);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);

    JLabel lblMenuAtendente = new JLabel("Menu Atendente");
    lblMenuAtendente.setFont(new Font("Tahoma", Font.PLAIN, 17));
    lblMenuAtendente.setBounds(22, 11, 165, 28);
    contentPane.add(lblMenuAtendente);

    JButton btnCadastrarAluno = new JButton("Cadastrar Novo Aluno");
    btnCadastrarAluno.setBounds(10, 75, 213, 84);
    contentPane.add(btnCadastrarAluno);
    btnCadastrarAluno.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            CadastroAlunosForm tela;
            try {
                tela = new CadastroAlunosForm();
                tela.setVisible(true);
                setVisible(false);
            } catch (ParseException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }
    });

    JButton btnPerfilDeAlunos = new JButton("Perfil de Alunos");
    btnPerfilDeAlunos.setBounds(10, 172, 170, 84);
    contentPane.add(btnPerfilDeAlunos);
    btnPerfilDeAlunos.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            try {
                PerfilUsuario tela = new PerfilUsuario();
                tela.setVisible(true);
                setVisible(false);
            } catch (ParseException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        }
    });

    JButton btnRelatoriosDeAluno = new JButton("Relat\u00F3rios de Alunos");
    btnRelatoriosDeAluno.setBounds(10, 277, 225, 84);
    contentPane.add(btnRelatoriosDeAluno);
    btnRelatoriosDeAluno.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println(frame);
            Toast.makeText(frame, "Olá", Style.SUCCESS).display();

        }
    });

    JButton btnLogout = new JButton("Logout");
    btnLogout.setBounds(419, 17, 89, 23);
    contentPane.add(btnLogout);
    btnLogout.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            SessaoUsuario.getInstancia().setUsuarioLogado(null);
            Login tela = new Login();
            tela.setVisible(true);
            dispose();
        }
    });

    lblInfo = new JLabel("");
    lblInfo.setBounds(10, 386, 581, 14);
    contentPane.add(lblInfo);

    JButton button = new JButton("Alterar Cadastro Aluno");
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            AlterarCadastroAlunosForm tela;
            try {
                tela = new AlterarCadastroAlunosForm();
                tela.setVisible(true);
                dispose();
            } catch (ParseException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        }
    });
    button.setBounds(267, 75, 177, 84);
    contentPane.add(button);
}

public static void getLblInfo(String mensagem) {
    lblInfo.setText(mensagem);
}

}

1 个答案:

答案 0 :(得分:0)

您始终可以使用SwingUtilities.getWindowAncestor(component)获取所显示组件的父级顶级窗口。例如

Window win = SwingUtilities.getWindowAncestor(someComponent);
Point ownerLoc = win.getLocation();

顺便说一下,

  • 您可能不希望在此程序中有多个JFrame,也许第二个窗口应该是JDialog或考虑通过CardLayout交换JPanel视图。如果你需要展示一个没有装饰的窗户,我想知道JWindow会不会更好 - 我不确定。
  • 您使用null布局和setBounds(...)是危险的代码,最终可能会咬你。您最好使用布局管理器来帮助您组织组件的位置和大小。
  • 当您在后台线程上的createGUI,fadeIn和fadeOut方法中进行Swing调用时,您的显示方法不是Swing线程安全的。最好使用Swing Timer。

修改 到目前为止,我尝试使用您的代码制作一个最小的示例程序:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.*;
import java.awt.geom.RoundRectangle2D;

import javax.swing.*;
import javax.swing.border.*;

public class FooGui {
   public static void main(String[] args) {
      MenuAtendente.main(args);
   }
}

@SuppressWarnings("serial")
class MenuAtendente extends JFrame {

   private JPanel contentPane;
   private static JLabel lblInfo;
   static MenuAtendente frame;

   /**
    * Launch the application.
    */

   public static void main(String[] args) {
      EventQueue.invokeLater(new Runnable() {
         public void run() {
            try {
               frame = new MenuAtendente();
               frame.setVisible(true);
            } catch (Exception e) {
               e.printStackTrace();
            }
         }
      });
   }

   /**
    * Create the frame.
    */
   public MenuAtendente() {
      setTitle("SGTA - <Nome da Academia>");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setBounds(100, 100, 663, 449);
      setLocationRelativeTo(null);
      setResizable(false);
      contentPane = new JPanel();
      contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
      setContentPane(contentPane);
      contentPane.setLayout(null); // *** ugh, don't do this.

      JButton btnRelatoriosDeAluno = new JButton("Relat\u00F3rios de Alunos");
      btnRelatoriosDeAluno.setBounds(10, 277, 225, 84);
      contentPane.add(btnRelatoriosDeAluno);
      btnRelatoriosDeAluno.addActionListener(new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            //!! 
            System.out.println(frame);
            Toast.makeText(frame, "Olá", Toast.Style.SUCCESS).display();
         }
      });

   }

   public static void getLblInfo(String mensagem) {
      lblInfo.setText(mensagem);
   }

}

class Toast extends JDialog {
   private static final long serialVersionUID = -1602907470843951525L;

   public enum Style {
      NORMAL, SUCCESS, ERROR
   };

   public static final int LENGTH_SHORT = 3000;
   public static final int LENGTH_LONG = 6000;
   public static final Color ERROR_RED = new Color(121, 0, 0);
   public static final Color SUCCESS_GREEN = new Color(22, 127, 57);
   public static final Color NORMAL_BLACK = new Color(0, 0, 0);

   private final float MAX_OPACITY = 0.8f;
   private final float OPACITY_INCREMENT = 0.05f;
   private final int FADE_REFRESH_RATE = 20;
   private final int WINDOW_RADIUS = 15;
   private final int CHARACTER_LENGTH_MULTIPLIER = 7;
   private final int DISTANCE_FROM_PARENT_TOP = 100;

   private JFrame mOwner;
   private String mText;
   private int mDuration;
   private Color mBackgroundColor = Color.BLACK;
   private Color mForegroundColor = Color.WHITE;

   public Toast(JFrame owner) {
      super(owner);
      mOwner = owner;
   }

   private void createGUI() {
      setLayout(new GridBagLayout());
      addComponentListener(new ComponentAdapter() {
         @Override
         public void componentResized(ComponentEvent e) {
            setShape(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(),
                  WINDOW_RADIUS, WINDOW_RADIUS));
         }
      });

      setAlwaysOnTop(true);
      setUndecorated(true);
      setFocusableWindowState(false);
      setModalityType(ModalityType.MODELESS);
      setSize(mText.length() * CHARACTER_LENGTH_MULTIPLIER, 25);
      getContentPane().setBackground(mBackgroundColor);

      JLabel label = new JLabel(mText);
      label.setForeground(mForegroundColor);
      add(label);
   }

   public void fadeIn() {
      final Timer timer = new Timer(FADE_REFRESH_RATE, null);
      timer.setRepeats(true);
      timer.addActionListener(new ActionListener() {
         private float opacity = 0;

         @Override
         public void actionPerformed(ActionEvent e) {
            opacity += OPACITY_INCREMENT;
            setOpacity(Math.min(opacity, MAX_OPACITY));
            if (opacity >= MAX_OPACITY) {
               timer.stop();
            }
         }
      });

      setOpacity(0);
      timer.start();

      setLocation(getToastLocation());
      setVisible(true);
   }

   public void fadeOut() {
      final Timer timer = new Timer(FADE_REFRESH_RATE, null);
      timer.setRepeats(true);
      timer.addActionListener(new ActionListener() {
         private float opacity = MAX_OPACITY;

         @Override
         public void actionPerformed(ActionEvent e) {
            opacity -= OPACITY_INCREMENT;
            setOpacity(Math.max(opacity, 0));
            if (opacity <= 0) {
               timer.stop();
               setVisible(false);
               dispose();
            }
         }
      });

      setOpacity(MAX_OPACITY);
      timer.start();
   }

   private Point getToastLocation() {
      System.out.println("Here!");
      System.out.println(mOwner);
      Point ownerLoc = mOwner.getLocation();
      // !! Window win = SwingUtilities.getWindowAncestor(someComponent);
      // Point ownerLoc = win.getLocation();
      int x = (int) (ownerLoc.getX() + ((mOwner.getWidth() - this.getWidth()) / 2));
      int y = (int) (ownerLoc.getY() + DISTANCE_FROM_PARENT_TOP);
      return new Point(x, y);
   }

   public void setText(String text) {
      mText = text;
   }

   public void setDuration(int duration) {
      mDuration = duration;
   }

   @Override
   public void setBackground(Color backgroundColor) {
      mBackgroundColor = backgroundColor;
   }

   @Override
   public void setForeground(Color foregroundColor) {
      mForegroundColor = foregroundColor;
   }

   public static Toast makeText(JFrame owner, String text) {
      return makeText(owner, text, LENGTH_SHORT);
   }

   public static Toast makeText(JFrame owner, String text, Style style) {
      return makeText(owner, text, LENGTH_SHORT, style);
   }

   public static Toast makeText(JFrame owner, String text, int duration) {
      return makeText(owner, text, duration, Style.NORMAL);
   }

   public static Toast makeText(JFrame owner, String text, int duration,
         Style style) {
      Toast toast = new Toast(owner);
      toast.mText = text;
      toast.mDuration = duration;

      if (style == Style.SUCCESS)
         toast.mBackgroundColor = SUCCESS_GREEN;
      if (style == Style.ERROR)
         toast.mBackgroundColor = ERROR_RED;
      if (style == Style.NORMAL)
         toast.mBackgroundColor = NORMAL_BLACK;

      return toast;
   }

   public void display() {
      new Thread(new Runnable() {
         @Override
         public void run() {
            try {
               createGUI();
               fadeIn();
               Thread.sleep(mDuration);
               fadeOut();
            } catch (Exception ex) {
               ex.printStackTrace();
            }
         }
      }).start();
   }
}

修改 一种更好的,更加线程安全的display()方法:

public void display() {
   final Timer timer = new Timer(mDuration, new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
         fadeOut();
      }
   });
   timer.setRepeats(false);
   createGUI();
   fadeIn();
   timer.start();
}