4

So i have text that is quite a bit longer than some of the components they occupy. I have come up with reasonable solutions for most of the problems, but i don't know what to do with very long text items in combo boxes. If the user can not see the text, he can not make the right decision - especially if the first part of the text matches. See my SSCCE below.

I have used a JScrollpane to resolve the issue of long text in a JTextfield and i have used a tooltip to resolve long text in a JXhyperlink field. Also, i ahve a tooltip for the combo box that can display a long item AFTER it has been selected, but ideally i would like to give that option to the user BEFORE he makes his choice. This code example was put together using Netbeans' GUI designer (great for RAD purposes) and the layout is the GroupLayout that the GUI designer uses.

package longtextsexample;

import javax.swing.JFileChooser;

public class MainFrame extends javax.swing.JFrame {

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

    /**
     * This method is called from within the constructor to initialize the form.
     */
    @SuppressWarnings("unchecked")
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTextField1 = new javax.swing.JTextField();
        jComboBox1 = new javax.swing.JComboBox();
        jXHyperlink1 = new org.jdesktop.swingx.JXHyperlink();
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        jScrollPane1.setViewportView(jTextField1);

        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 222222222222222222222222", "Item 333333333333333333333333", "Item 333333333333333333333333444444444444" }));
        jComboBox1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBox1ActionPerformed(evt);
            }
        });

        jXHyperlink1.setText("Path");

        jButton1.setText("Browse");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 164, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 164, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(6, 6, 6)
                        .addComponent(jXHyperlink1, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE))))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(11, 11, 11)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jButton1)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(4, 4, 4)
                        .addComponent(jXHyperlink1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
        );

        pack();
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        JFileChooser jfc = new JFileChooser();
        String path;

        if (jfc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            path = jfc.getSelectedFile().getAbsolutePath();
        } else {
            path = "";
        }
        jXHyperlink1.setText(path);
        jXHyperlink1.setToolTipText(path);
    }

    private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {
        jComboBox1.setToolTipText(jComboBox1.getSelectedItem().toString());
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */

        /*
         * 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(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }


        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new MainFrame().setVisible(true);
            }
        });
    }
    // Variables declaration
    private javax.swing.JButton jButton1;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextField jTextField1;
    private org.jdesktop.swingx.JXHyperlink jXHyperlink1;
    // End of variables declaration
}
wmdvanzyl
  • 352
  • 2
  • 5
  • 17

1 Answers1

6
How to deal with very long text items in comboboxes

1) you can put JTextArea or better could be JTextPane to the derived JList from JComboBox

anyhow above point could be simple, but why do that, because there is

2) Combo Box Popup, I'd suggest to set setMaximumWidth

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I will mark as answer as soon as i get it to work, but i upvoted it already. – wmdvanzyl Apr 22 '12 at 09:22
  • if i should rather contact the author of that class, please say so, but i was wondering if you have ever gotten your suggestion working? When using that code i generate a nullpointerexception on this line: 'JComboBox comboBox = (JComboBox)popup.getInvoker();' You should be able to find that close to line 175. – wmdvanzyl Apr 22 '12 at 09:37
  • i made some changes to my file to try and get it working, but i am not achieving success. I am searching in the blind here - i don't know enough about this to really know what is going wrong. I added the following lines: `javax.swing.plaf.basic.BasicComboPopup popup = new javax.swing.plaf.basic.BasicComboPopup(jComboBox1); popup.setInvoker(jComboBox1); jComboBox1.setComponentPopupMenu(popup);` and also `BoundsPopupMenuListener listener = new BoundsPopupMenuListener(true, false); jComboBox1.addPopupMenuListener( listener );` This requires the BoundPopupMenuListener.java file. – wmdvanzyl Apr 22 '12 at 10:55
  • @wmdvanzyl please [look at this thread](http://stackoverflow.com/questions/10267032/jscrolpane-on-jcompobox), this code talking about MetalXxxXxx then is Look and Feels very sensitive, BasicComboBoxXxx is correct way :-), but you have to accepting that Swing Framework that you use overrive basic Swing mathod and nothing special that you cann't returns back to the basic Swing methods, those disadvantages become from all Frameworks, sure in this case I don't know :-) – mKorbel Apr 22 '12 at 13:07
  • FROM: http://tips4java.wordpress.com/2010/11/28/combo-box-popup/ `At row 303 of BoundsPopupMenuListener replace JComboBox comboBox = (JComboBox)popup.getInvoker(); with JComboBox comboBox = (JComboBox) popup.getAccessibleContext().getAccessibleParent();` – wmdvanzyl Jun 01 '14 at 14:40