JDialog repaint after JList modification

2019-07-23 18:17发布

问题:

I have a JDialog dlg, created by a JFrame frm, that contains a JList list. When I modify the list (through the ListModel), the list itself is repainted but not the JDialog. This means that, if I delete a line, the list remains with an empty line while if I add a line, this new line won't be shown (because there is no space in the dialog) until I manually force repainting of dlg (doubleclicking in frm).

Following advices in this post : How to make repaint for JDialog in Swing?

and in this post: Force repaint after button click

I tried to call, from my controller class (which is where updates to list are made), the following line:

SwingUtilities.getWindowAncestor(dlg).repaint();

but it didn't work. I also tried:

dlg.repaint();

No luck either...

Any clue? Thank you very much.

EDIT: The organization of my classes is as follows: a controller class that contains a reference to the main JFrame, frm. I also extended JDialog into MyDialog, which contains a JList. When a doubleclick on frm is detected, I show the instance of MyDialog (or create, if it is the first time I show it) and the JList is filled with the data passed to the DefaultListModel. MyDialog is painted so that the list has only the space that it needs. Now, when a specific event is detected by the controller, I get the specific MyDialog, get the ListModel from JList and update it. Here the JList is indeed updated, but Dialog remains the same. I use a code like this:

MyDialog dlg = group.getDlg();
if(dlg != null){
    DefaultListModel listModel = ((DefaultListModel) dlg.getMyJList().getModel());
    listModel.addElement(idStock);
    SwingUtilities.getWindowAncestor(dlg).repaint();
}

This doesn't repaint dlg. I also tried:

SwingUtilities.getWindowAncestor(dlg.getMyJList()).repaint();

but it doesn't work.

I checked with the debugger that the lines are actually executed.

I don't have much more code to show, really.....

回答1:

I think that you going wrong way, define DefaultListModel that accesible throught all Java methods and Classes, this Model would holds your Objects, then put JList to the JDialog or JOptionPane, for example

import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;

// based on @trashgod code
/** @see http://stackoverflow.com/questions/5759131 */
// http://stackoverflow.com/questions/8667719/jdialog-repaint-after-jlist-modification

public class ListDialog {

    private static final int N = 12;
    private JDialog dlg = new JDialog();
    private DefaultListModel model = new DefaultListModel();
    private JList list = new JList(model);
    private JScrollPane sp = new JScrollPane(list);
    private int count;

    public ListDialog() {
        list.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        JPanel panel = new JPanel();
        panel.add(new JButton(new AbstractAction("Add") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                append();
                if (count <= N) {
                    list.setVisibleRowCount(count);
                    dlg.pack();
                }
            }
        }));
        panel.add(new JButton(new AbstractAction("Remove") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                int itemNo = list.getSelectedIndex();
                if (itemNo > -1) {
                    removeActionPerformed(e, itemNo);
                }
            }
        }));
        for (int i = 0; i < N - 2; i++) {
            this.append();
        }
        list.setVisibleRowCount(N - 2);
        dlg.add(sp, BorderLayout.CENTER);
        dlg.add(panel, BorderLayout.SOUTH);
        dlg.pack();
        dlg.setLocationRelativeTo(null);
        dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dlg.setVisible(true);
    }

    private void removeActionPerformed(ActionEvent e, int itemNo) {
        System.out.println("made_list's model: " + list.getModel());
        System.out.println("Model from a fresh JList: " + new JList().getModel());
        model = (DefaultListModel) list.getModel();
        if (model.size() > 0) {
            if (itemNo > -1) {
                model.remove(itemNo);
            }
        }
    }

    private void append() {
        model.addElement("String " + String.valueOf(++count));
        list.ensureIndexIsVisible(count - 1);
    }

    public static void main(String[] a_args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ListDialog pd = new ListDialog();
            }
        });
    }
}