Java托盘图标NPE



我实例化了一个Java trayIcon,并想用下面的代码在它上面显示一个displayMessage:

trayIcon.displayMessage(_titel, _msg, TrayIcon.MessageType.INFO);

但是,而不是消息,我得到一个NullpointerException,我现在不知道为什么?

这肺水肿:

Exception in thread "main" java.lang.NullPointerException
    at myPckg.Tray.showMsg(Tray.java:165)
    at myPckg.Main.main(Main.java:65)

在第65行中,我通过构造函数实例化了这个类,在第155行中,我调用了这个对象。

谢谢你的帮助!

编辑-代码:

import java.awt.AWTException;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
public class Tray {
//http://www.oracle.com/technetwork/articles/javase/index-136970.html   
public static MenuItem itmSpeicher = new MenuItem("0% von 0MB belegt");
public static MenuItem itmSyncStatus = new MenuItem("Synchronisation starten");
public static PopupMenu popup = new PopupMenu();
public static TrayIcon trayIcon = null;
public Tray(){
final TrayIcon trayIcon;

if (SystemTray.isSupported()) {
    SystemTray tray = SystemTray.getSystemTray();
    Image image = null;
    try {
        image = ImageIO.read(getClass().getResource("sync.gif"));
    } catch (IOException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
        new Thread(){ public void run(){ Main.syncProzess.reset();}}.start();
    }
    MouseListener mouseListener = new MouseListener() {
        public void mouseClicked(MouseEvent e) {
              Main.MainWindow.setVisible(true);
        }
        @Override
        public void mousePressed(MouseEvent e) {
            // TODO Auto-generated method stub
        }
        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub
        }
        @Override
        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub
        }
        @Override
        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub
        }

    };
    ActionListener exitListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            int x = JOptionPane.showConfirmDialog(null, "Synchronisation wirklich beenden?");
            if(x==0){
                System.out.println("Beende... "+x);
                System.exit(0);
            }
        }
    };
    ActionListener itmSyncStatusListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Main.syncProzess.starte();
        }
    };
    ActionListener itmFolderListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            try {
                Runtime.getRuntime().exec("explorer.exe "+ Main.syncDir );
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
                new Thread(){ public void run(){ Main.syncProzess.reset();}}.start();
            }
        }
    };
    ActionListener itmSettingListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Main.MainWindow.setVisible(true);
        }
    };

    MenuItem defaultItem = new MenuItem("Programm beenden");
    defaultItem.addActionListener(exitListener);
    itmSyncStatus.addActionListener(itmSyncStatusListener);
    MenuItem itmFolder = new MenuItem(Main.programmName + " Ordner öffnen");
    itmFolder.addActionListener(itmFolderListener);
    MenuItem itmSettings = new MenuItem("Einstellungen");
    itmFolder.addActionListener(itmSettingListener);
    popup.add(itmFolder);
    popup.add(itmSpeicher);
    popup.add(itmSettings);
    popup.add(itmSyncStatus);
    popup.add(defaultItem);

    trayIcon = new TrayIcon(image, Main.programmName, popup);
    ActionListener doubleClick = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            try {
                Runtime.getRuntime().exec("explorer.exe "+ Main.syncDir );
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
                new Thread(){ public void run(){ Main.syncProzess.reset();}}.start();
            }
        }
    };

    trayIcon.setImageAutoSize(true);
    trayIcon.addActionListener(doubleClick);
    trayIcon.addMouseListener(mouseListener);
    try {
        tray.add(trayIcon);
    } catch (AWTException e) {
        System.err.println("TrayIcon konnte nicht erstellt werden!");
        new Thread(){ public void run(){ Main.syncProzess.reset();}}.start();
    }
    showMsg("Hello", "It's working");
} else {
    //Not supportet
}

}
public void showMsg(String _titel, String _msg){
    trayIcon.displayMessage(_titel, _msg, TrayIcon.MessageType.INFO);
}

}

问题是您在构造函数中重新定义了相同的trayIcon变量。

final TrayIcon trayIcon;

因此,当您通过调用trayIcon = new TrayIcon(image, Main.programmName, popup);初始化变量时,方法的局部变量被初始化,而不是全局变量。所以当你在全局变量上调用displayMessage时你得到了NPE。

解决方法是从构造函数中删除这一行。你应该在showMessage方法中放入null检查,因为如果你的条件(SystemTray.isSupported())为假,你的trayIcon变量仍然可以为null。

MadProgrammer在评论中说的另一件好事:

在这种情况下使用静态变量可能不是一个好主意。因为开发人员有可能实例化多个实例,在这种情况下,您可能会得到到处都是错误的引用。相反,尝试将Tray类设置为单例或从变量声明中删除static关键字。

您的静态trayIconnull。您在Tray的构造函数中创建了新的第二个trayIcon,但是您的showMsg -Method使用静态trayIcon而不是本地构造函数。

删除Tray -构造函数中的第一行:

final TrayIcon trayIcon;

,现在初始化静态引用

TrayIcon.displayMessage 如果captiontext都是null,则抛出NullPointerException

captiontext依次为方法的前两个参数。

那么,这就是你应该在代码中检查的内容:

  • trayIcon应该在方法调用
  • 之前实例化
  • _titel_msg不能同时为null

最新更新