java.awt.IllegalComponentStateException, когда я нажимаю на JComboBox в проблеме JTable - PullRequest
1 голос
/ 18 мая 2011

У меня странная проблема. У меня есть класс, который ведет себя аналогично выпадающему списку.

package test.view;

    import java.awt.Color;
    import java.awt.Component;
    import java.awt.event.FocusAdapter;
    import java.awt.event.FocusEvent;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.util.List;

    import javax.swing.ComboBoxModel;
    import javax.swing.JComboBox;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTable;
    import javax.swing.JTextField;
    import javax.swing.table.TableCellRenderer;
    import javax.swing.text.AttributeSet;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.Document;
    import javax.swing.text.JTextComponent;
    import javax.swing.text.PlainDocument;

    public class AutoCompleteJComboBoxer extends PlainDocument   {
        private JComboBox comboBox;
        private ComboBoxModel model;
        private JTextComponent editor;
        private boolean hidePopupOnFocusLoss;

        public AutoCompleteJComboBoxer(JComboBox comboBox) {
            this.comboBox = comboBox;
            comboBox.setEditable(true);
            model = comboBox.getModel();
            editor = (JTextComponent)comboBox.getEditor().getEditorComponent();
            editor.setDocument(this);
            // Bug 5100422 on Java 1.5: Editable JComboBox won't hide popup when tabbing out
            hidePopupOnFocusLoss = System.getProperty("java.version").startsWith("1.5");
            // Highlight whole text when focus gets lost
            editor.addFocusListener(new FocusAdapter() {
                @Override
                public void focusLost(FocusEvent e) {
                    highlightCompletedText(0);
                    // Workaround for Bug 5100422 - Hide Popup on focus loss
                    if (hidePopupOnFocusLoss) AutoCompleteJComboBoxer.this.comboBox.setPopupVisible(false);
                }
            });
            // Highlight whole text when user hits enter
            editor.addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(java.awt.event.KeyEvent e) {
                    if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                        highlightCompletedText(0);
                    } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                        AutoCompleteJComboBoxer.this.comboBox.setSelectedIndex(0);
                        AutoCompleteJComboBoxer.this.editor.setText(AutoCompleteJComboBoxer.this.comboBox.getSelectedItem().toString());
                        highlightCompletedText(0);
                    }
                }
            });


            // Handle initially selected object
            Object selected = comboBox.getSelectedItem();
            if (selected != null) editor.setText(selected.toString());
        }


        public AutoCompleteJComboBoxer(List<String> list){
             comboBox = new JComboBox(list.toArray());
             comboBox.setEditable(true);
             comboBox.setMaximumRowCount(8);
             comboBox.setSelectedIndex(-1);

             model = comboBox.getModel();
             editor = (JTextComponent)comboBox.getEditor().getEditorComponent();
             editor.setDocument(this);
             hidePopupOnFocusLoss = System.getProperty("java.version").startsWith("1.5");
             editor.addFocusListener(new FocusAdapter() {
                 @Override
                 public void focusLost(FocusEvent e) {
                     highlightCompletedText(0);
                     if (hidePopupOnFocusLoss) AutoCompleteJComboBoxer.this.comboBox.setPopupVisible(false);
                 }
             });

             editor.addKeyListener(new KeyAdapter() {
                 @Override
                 public void keyPressed(java.awt.event.KeyEvent e) {
                     if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                         highlightCompletedText(0);
                     } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                         AutoCompleteJComboBoxer.this.comboBox.setSelectedIndex(0);
                         AutoCompleteJComboBoxer.this.editor.setText(AutoCompleteJComboBoxer.this.comboBox.getSelectedItem().toString());
                         highlightCompletedText(0);
                     }
                 }
             });

             // Handle initially selected object
             Object selected = comboBox.getSelectedItem();
             if (selected != null) editor.setText(selected.toString());

             editor = (JTextComponent)comboBox.getEditor().getEditorComponent();
             editor.setDocument(this);
             editor.setBackground(Color.WHITE);
        }

        @Override
        public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
            // construct the resulting string
            String currentText = getText(0, getLength());
            String beforeOffset = currentText.substring(0, offs);
            String afterOffset = currentText.substring(offs, currentText.length());
            String futureText = beforeOffset + str + afterOffset;

            // lookup and select a matching item
            Object item = lookupItem(futureText);
            if (item != null) {

                    comboBox.setSelectedItem(item);

            } else {
                // keep old item selected if there is no match
                item = comboBox.getSelectedItem();
                // imitate no insert (later on offs will be incremented by str.length(): selection won't move forward)
                offs = offs-str.length();
                // provide feedback to the user that his input has been received but can not be accepted
                comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
            }

            // remove all text and insert the completed string
            super.remove(0, getLength());
            super.insertString(0, item.toString(), a);

            // if the user selects an item via mouse the the whole string will be inserted.
            // highlight the entire text if this happens.
            if (item.toString().equals(str) && offs==0) {
                highlightCompletedText(0);
            } else {
                highlightCompletedText(offs+str.length());
                // show popup when the user type
                comboBox.setPopupVisible(true); // THERE PROGRAM CRASHES



            }
        }

        private void highlightCompletedText(int start) {
            editor.setCaretPosition(getLength());
            editor.moveCaretPosition(start);
        }

        private Object lookupItem(String pattern) {
            Object selectedItem = model.getSelectedItem();
            // only search for a different item if the currently selected does not match
            if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) {
                return selectedItem;
            } else {
                // iterate over all items
                for (int i=0, n=model.getSize(); i < n; i++) {
                    Object currentItem = model.getElementAt(i);
                    // current item starts with the pattern?
                    if (startsWithIgnoreCase(currentItem.toString(), pattern)) {
                        return currentItem;
                    }
                }
            }
            // no item starts with the pattern =&gt; return null
            return null;
        }

        // checks if str1 starts with str2 - ignores case
        private boolean startsWithIgnoreCase(String str1, String str2) {
            return str1.toUpperCase().startsWith(str2.toUpperCase());
        }

        public void resetColor(){
            this.editor.setBackground(Color.WHITE);
        }
        public void setSuccessfulColor(){
            this.editor.setBackground(Color.GREEN);
        }
        public void setUnsuccessfulColor(){
            this.editor.setBackground(Color.RED);
        }
        public void setColor(Color color){
            this.editor.setBackground(color);
        }
        public JTextComponent getEditor(){
            return this.editor;
        }
        public JComboBox getComboBox(){
            return this.comboBox;
        }
        public void setComboBox(JComboBox comboBox){
            this.comboBox=comboBox;
        }


        private static void createAndShowGUI() {

            JComboBox comboBox = new JComboBox(new Object[] { "clear","delete", "read", "read_all", "write","write_all","a","b","c"});
            comboBox.setEditable(true);
            comboBox.setMaximumRowCount(8);
            comboBox.setSelectedIndex(-1);
            JTextComponent editor = (JTextComponent)comboBox.getEditor().getEditorComponent();
            editor.setDocument(new AutoCompleteJComboBoxer(comboBox));
            editor.setBackground(Color.WHITE);

            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(comboBox);
            frame.pack(); frame.setVisible(true);
        }


        public static void main(String[] args) {
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
        }



    }

Я поместил JComboBox из этого класса (члена) в

DefaultCellEditor dceName=new DefaultCellEditor(cmbName);

и поместите это в JTable, но когда я нажимаю, я получаю ошибку

Exception in thread "AWT-EventQueue-0" java.awt.IllegalComponentStateException: component must be showing on the screen to determine its location
    at java.awt.Component.getLocationOnScreen_NoTreeLock(Unknown Source)
    at java.awt.Component.getLocationOnScreen(Unknown Source)
    at javax.swing.JPopupMenu.show(Unknown Source)
    at javax.swing.plaf.basic.BasicComboPopup.show(Unknown Source)
    at javax.swing.plaf.basic.BasicComboBoxUI.setPopupVisible(Unknown Source)
    at javax.swing.JComboBox.setPopupVisible(Unknown Source)
    at bacnet_debug_tool.view.AutoCompleteJComboBoxer.insertString(AutoCompleteJComboBoxer.java:142)

У кого-нибудь есть идея, что не так? У меня есть обычный JComboBox в JTable, и он работает.

1 Ответ

1 голос
/ 18 мая 2011

ничего сложного, просто

1 / take TableRenderDemo.java по ссылке, которую я разместил в вашей предыдущей теме 2 / загрузка Автозаполнение ComboBox (есть два отдельных предложения), и оба класса сохраняются в вашем проекте

, затем просто измените / измените всю пустоту public void setUpSportColumn(JTable table, TableColumn sportColumn) {...} из TableRenderDemo.java и замените этим кодом

public void setUpSportColumn(JTable table, TableColumn sportColumn) {
    //Set up the editor for the sport cells.
    ArrayList<String> listSomeString = new ArrayList<String>();        
    listSomeString.add("Snowboarding");
    listSomeString.add("Rowing");
    listSomeString.add("Knitting");
    listSomeString.add("Speed reading");
    listSomeString.add("Pool");
    listSomeString.add("None of the above");
    Java2sAutoComboBox comboBox = new Java2sAutoComboBox(listSomeString);
    comboBox.setDataList(listSomeString);
    sportColumn.setCellEditor(new DefaultCellEditor(comboBox));
    //Set up tool tips for the sport cells.
    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
    renderer.setToolTipText("Click for combo box");
    sportColumn.setCellRenderer(renderer);
}

РЕДАКТИРОВАТЬ: возможно, лучше было бы использовать для JTable второго класса Java2sAutoTextField.class, выглядит намного лучше в TableCell, чем JComboBox ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...