简体   繁体   中英

Java JList Model addElement() breaks visual representation of the list

There is just weird behavior then adding elements to JList model. On calling the addElement() method, the list turns blank, adds huge empty element instead or shifts new element few lines down. Another call for the methods turns it back with all elements before and after the issue in place, including item added by "unstable" call. First it seemed as painting issue, just repaint call doesn't help, only adding new element corrects the issue.

The issue take place then adding part of elements, same indexes involved on different launches. Never seen it fails on first index soon.

package r;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;


public class R extends javax.swing.JFrame {

    ServerSocket serverport;

    /**
     * Creates new form R
     */
    public R() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        scrollDebug = new javax.swing.JScrollPane();
        debugList = new javax.swing.JList();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Debug");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowOpened(java.awt.event.WindowEvent evt) {
                formWindowOpened(evt);
            }
        });

        scrollDebug.setAutoscrolls(true);

        debugList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        scrollDebug.setViewportView(debugList);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(scrollDebug, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 682, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(scrollDebug, javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
        );

        pack();
        setLocationRelativeTo(null);
    }// </editor-fold>                        

    private void formWindowOpened(java.awt.event.WindowEvent evt) {                                  
        new Thread() {

            @Override
            public void run() {

                try {
                    serverport = new ServerSocket(33002, 0, InetAddress.getLoopbackAddress());

                    debugList.setModel(new DefaultListModel());

                    while (R.this.isVisible()) {
                        new ClientConnection(serverport.accept()).start();

                    }

                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(null, "Error opening server port", "Debug", JOptionPane.ERROR_MESSAGE);
                }
            }

        }.start();


    }                                 

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(R.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(R.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(R.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(R.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new R().setVisible(true);
            }
        });
    }

    class ClientConnection extends Thread {
        Socket connection;
        public ClientConnection(Socket connection){
            this.connection=connection;
        }


        @Override
        public void run() {
            try {


                connection.getOutputStream().write(String.format("debug>").getBytes());
                connection.getOutputStream().flush();

                String response = "";
                do {
                    response += (char) connection.getInputStream().read();
                } while (!response.endsWith(System.lineSeparator()));
                response = response.replace(System.lineSeparator(), "");

                ((DefaultListModel) debugList.getModel()).addElement(response);

                if (((DefaultListModel) debugList.getModel()).getSize() > 0) {
                    //debugList.ensureIndexIsVisible(((DefaultListModel) debugList.getModel()).getSize() - 1);
                    debugList.setSelectedIndex(((DefaultListModel) debugList.getModel()).getSize() - 1);
                    scrollDebug.getVerticalScrollBar().setValue(scrollDebug.getVerticalScrollBar().getMaximum());

                }

                connection.close();
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, "Error receiving connection", "Debug", JOptionPane.ERROR_MESSAGE);
            }
        }

    }
    // Variables declaration - do not modify                     
    private javax.swing.JList debugList;
    private javax.swing.JScrollPane scrollDebug;
    // End of variables declaration                   
}

Complete sample code added now. Sorry for inconvenience!

This one is inner class of the frame used to create new threads receiving data and adding string to JList.

Swing components need to be updated on the Event Dispatch Thread so you can't update the component directly in your Thread.

So you can wrap the code updating the model in a SwingUtilities.invokeLater(...)

Or instead of using a separate Thread you could use a SwingWorker and "publish" results as they become available.

Read the section from the Swing tutorial on Concurrency for more information on these concepts and for working examples.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM