点击JTree时出现异常(空指针异常)

Exception when clicking JTree (null pointer exception)

所以当我单击包含 JtreeMessages tabPane 时,这是我的 java swing 中的预览,看起来不错。

pict 1 (loading the message)

pict 2. (done)

当我单击 JTree 中的任何 checkboxes 它应该是 加载(检查)或卸载(取消选中)消息列表中的消息swingworker 运行 查看进度。但是在我点击复选框(任何条件)之后发生了什么,是的 swingworker 运行 并给出了 loading/unloading 进度,但在那之后,我得到了这个:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "model.Message.getContents()" because "message" is null

并使 message lists 不可点击,在我尝试点击 JTree 中的复选框之前它是可点击的。

目前我不需要 JTree 来学习 swing,所以我并没有真正考虑这个 JTree 课程,但我需要修复它以便我可以继续学习教程。这就是为什么我不太确定哪些代码有问题并且需要放入此线程中。所以如果我的问题不清楚,我很抱歉。如果我还有什么要放在这个线程上的,请问我,我很乐意把它放在这里。

这是异常中提到的class

public class MessagePanel extends JPanel implements ProgressDialogListener{
 public MessagePanel(JFrame parent) {
    messageListModel = new DefaultListModel();
    messageList = new JList(messageListModel);
    messageList.setCellRenderer(new MessageListRenderer());
        
    messageList.addListSelectionListener(new ListSelectionListener() {
        @Override
        public void valueChanged(ListSelectionEvent e) {
            Message message = (Message)messageList.getSelectedValue();
            textPanel.setText(message.getContents());
        }
    });
 }

这是class与上面class

相关的方法
public class MessageListRenderer implements ListCellRenderer {
    private JPanel panel;
    private JLabel label;
    private Color selectedColor,normalColor;

    public MessageListRenderer() {
     //some ui settings
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
                    int index, boolean isSelected, boolean cellHasFocus) {

        Message message = (Message)value;
        label.setText(message.getTitle());
        panel.setBackground(cellHasFocus ? selectedColor: normalColor);
        return panel;
    }
}

===================

public class TextPanel extends JPanel{
    public void setText(String text) {
        textArea.setText(text);
    }
}

===================

public class Message {
    private String title,contents;

    public Message(String title, String contents) {
        super();
        this.title = title;
        this.contents = contents;
    }

    public String getTitle() {return title;}
    public void setTitle(String title) {this.title = title;}
    public String getContents() {return contents;}
    public void setContents(String contents) {this.contents = contents;}
}

您的 Message class constructor 需要两个参数(属于:String,String) 以创建 Message 的实例。我不知道您当前使用什么来创建 Message 实例,也不知道存储这些实例的是什么。您确实需要跟踪它们,否则您会将它们丢给 JVM 垃圾收集器。

我想也许您可能想要稍微修改一下 Message Class 以便您可以在内部(或外部)存储 Message 实例并在需要时轻松访问这些实例中的任何一个,例如:

public class Message {

    // A List Interface object to hold Message instances.
    private static java.util.List<Message> messageInstances = new java.util.ArrayList<>();
    // The OS System's New-Line character to use for console writing. 
    private final static String ls = System.lineSeparator();

    // Instance member variables
    private String title;
    private String contents;


    /**
     * Constructor #1
     * Does Nothing but adds the instance to the messageInstances List!
     * Relies on Setters to fill instance member variables.
     */
    public Message() {  
        messageInstances.add((this));
    }

    /**
     * Constructor #2
     * Contains parameters of which the arguments will fill instance member 
     * variables listed within the Parameters list below.
     * 
     * @param title (String) The Message Title.<br>
     * 
     * @param contents (String) The message content related to the above title.
     */
    public Message(String title, String contents) {
        super();
        this.title = title;
        this.contents = contents;
        messageInstances.add((this));
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContents() {
        return contents;
    }

    public void setContents(String contents) {
        this.contents = contents;
    }

    public static java.util.List<Message> getMessageInstances() {
        return messageInstances;
    }

    /**
     * Removes one (or more) Message instances from the messageInstances List. 
     * This method must be supplied at least one integer index value of the 
     * Message instance to remove otherwise a Warning is displayed within the 
     * console window. Several index values can be supplied providing they are 
     * delimited with a comma or all desired Message Instance index values to 
     * remove are supplied within a Single Dimensional int[] Array.<br><br>
     * 
     * <b>Valid uses of this class method:</b><pre>
     * 
     *     removeMessageInstance(0, 4, 2, 16);
     * 
     *     OR
     * 
     *     int[] indexes = {0, 4, 2, 16};
     *     removeMessageInstance(indexes);</pre>
     * 
     * @param instanceIndexes
     */
    public static void removeMessageInstance(int... instanceIndexes) {
        int[] iIndex = null;
        if (instanceIndexes.length == 0) {
            System.err.println("Message.removeMessageInstance() method Warning!" + ls
                    + "Require an index value of the Message Instance to remove!" + ls
                    + "Ignoring Removal call!" );
            return;
        }
    
        iIndex = new int[instanceIndexes.length];
        System.arraycopy(instanceIndexes, 0, iIndex, 0, instanceIndexes.length);
    
        for (int i = 0; i < iIndex.length; i++) {
            if(iIndex[i] < 0 || iIndex[i] > messageInstances.size()) {
                System.err.println("Message.removeMessageInstance() method Warning!" + ls 
                        + "The supplied Message Instance index value (" + iIndex[i] + ") is invalid!" + ls
                        + "Ignoring Removal call for Message Instance at Index " + iIndex[i] + "!");
                continue;
            }
            messageInstances.remove(iIndex[i]);
        }
    }

    @Override
    public String toString() {
        return new StringBuilder("").append(title).append(" | ")
                                    .append(contents).toString();
    }
}

尽你所能创建 Message 实例。

现在,在你的 MessagePanel class 内 ListSelectionListener:

public void valueChanged(ListSelectionEvent e) {
    String title = messageList.getSelectedValue().toString(); // toString() may not be required.
    List<Message> messages = Message.getMessageInstances();
    for (Message msg : messages) {
        if (msg.getTitle().equalsIgnoreCase(title)) {
            textPanel.setText(msg.getContents());
            break;
        }
    }
}