Клавиши со стрелками не работают в компоненте пользовательского поиска

Я разрабатываю пользовательский компонент поиска. При нажатии на кнопку (значок поиска изображения) внутри текстового поля отображается таблица. Код находится в очень зачаточном состоянии, поэтому многих вещей там нет.

На данный момент я застрял, потому что не могу перемещаться по таблице с помощью клавиш со стрелками. Я также не могу перейти к следующему текстовому полю с помощью клавиши «tab», как только я выбираю строку в таблице.

Цель компонента состоит в том, чтобы выбрать строку из таблицы, а затем с помощью вспомогательных методов (еще не написанных) значения из других меток и текстовых полей будут установлены по умолчанию, а значение по умолчанию 1-го столбца в текстовом поле это прикреплен к.

Был бы очень признателен за вашу помощь. Спасибо !!

    package myTableCombo;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.ListSelectionModel;
import javax.swing.RowFilter;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

public class SearchBox extends JPanel {

        private static final long serialVersionUID = 1L;
        private JTextField editor;
        private JButton arrowButton;
        private JWindow jWindow;
        private Component userComponent;

        public SearchBox() {
                super(new FlowLayout(FlowLayout.LEFT, 0, 0));
                editor = new JTextField();
                editor.setPreferredSize(new Dimension(250, 25));
                initialize();
                addListeners();
                setBorders();
        }

        private void addListeners() {
                arrowButton.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                                showWindow();
                        }
                });
        }

        protected void showWindow() {
                if (null != getWindowComponent()) {
                        jWindow = new JWindow();
                        jWindow.getContentPane().add(getWindowComponent());
                        jWindow.setLocation(new Point(SearchBox.this.getLocationOnScreen().x, SearchBox.this.getLocationOnScreen().y + 25));
                        jWindow.pack();
                        jWindow.setVisible(true);
                }
        }

        private Component getWindowComponent() {
                return userComponent;
        }

        public void setWindowComponent(Component component) {
                userComponent = component;
        }

        private void initialize() {
                arrowButton = new BasicArrowButton(SwingConstants.SOUTH);//In my code there is an icon here
                arrowButton.setBorder(null);
                arrowButton.setContentAreaFilled(false);
        }

        private void setBorders() {
                add(editor);
                add(arrowButton);
                setBackground(editor.getBackground());
                setBorder(editor.getBorder());
                editor.setBorder(null);
        }

        public JTextField getTextComponent() {
                return editor;
        }

        public JButton getActionButton() {
                return arrowButton;
        }

        public static void main(String args[]) {
                EventQueue.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                                createAndShowGUI();
                        }
                });
        }

        protected static void createAndShowGUI() {
                JFrame frame = new JFrame();
                JPanel panel = new JPanel();

                frame.setPreferredSize(new Dimension(500, 400));
                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

                panel.add(new JLabel("Test Table Combo"));
                SearchBox searchBox = new SearchBox();
                searchBox.userComponent = searchBox.new SearchBoxTable();
                panel.add(searchBox);

                frame.getContentPane().add(panel);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
        }

        private class SearchBoxTable extends JScrollPane implements DocumentListener {

                private static final long serialVersionUID = 1L;
                private JTable table;
                private Object[] columnNames;
                private DefaultTableModel tableModel;
                private Object[][] sheetDataInString;
                private TableRowSorter<DefaultTableModel> rowSorter;

                public SearchBoxTable() {
                        columnNames = new Object[]{"Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6"};
                        sheetDataInString = new Object[21][6];
                        for(int i =0; i < sheetDataInString.length; i++) {
                                for(int j = 0; j< 6; j++) {
                                        sheetDataInString[i][j] = "Row Value : " + i + ", Column Value : " + j;
                                }
                        }

                        tableModel = new DefaultTableModel(sheetDataInString, columnNames) {
                                private static final long serialVersionUID = 1L;

                                @Override
                                public boolean isCellEditable(int row, int column) {
                                        return false;
                                }
                        };
                        rowSorter = new TableRowSorter<DefaultTableModel>(tableModel);

                        table = new JTable(tableModel);
                        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
                        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                        table.setAutoCreateRowSorter(true);
                        table.setFillsViewportHeight(true);
                        table.getTableHeader().setFont(new Font(null, Font.PLAIN, 13));

                        setPreferredSize(new Dimension(500, 225));
                        setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
                        setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
                        getViewport().add(table);
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                        newFilter(e);
                }

                @Override
                public void insertUpdate(DocumentEvent e) {
                        newFilter(e);
                }

                @Override
                public void removeUpdate(DocumentEvent e) {
                        newFilter(e);
                }

                /**
                 * Update the row filter regular expression from the expression/string/data in the text box.
                 * 
                 * @param documentEvent
                 */
                private void newFilter(DocumentEvent documentEvent) {
                        RowFilter<DefaultTableModel, Object> rowFilter = null;
                        Document document = documentEvent.getDocument();
                        String filterText;

                        try {
                                filterText = document.getText(0, document.getLength()).trim();
                                rowFilter = RowFilter.regexFilter("(?i)" + filterText);
                        } catch (java.util.regex.PatternSyntaxException e) {
                                return;
                        } catch (BadLocationException badLocationException) {
                                return;
                        }
                        rowSorter.setRowFilter(rowFilter);
                        table.setRowSorter(rowSorter);

                }

        }

}

person dareurdream    schedule 31.12.2012    source источник
comment
@AndrewThompson - Он там..   -  person dareurdream    schedule 31.12.2012
comment
извините (flamewar) ваш рейтинг защитите меня от всего, удачи и счастливого нового года   -  person mKorbel    schedule 31.12.2012
comment
@HovercraftFullOfEels - Нужно ли мне писать ключевой выпущенный код для JTable. JTable имеет это по умолчанию в BasicTableUI.   -  person dareurdream    schedule 31.12.2012
comment
Все ваши ответы я принял и ранее. Просто я давно отсутствовал из-за личных проблем. Так что не проверял предыдущие сообщения и ответы. Помогите ребята плз!!   -  person dareurdream    schedule 31.12.2012
comment
Поэтому не проверял предыдущие сообщения и ответы. Самое время просмотреть прошлые вопросы., прямо сейчас. :)   -  person Andrew Thompson    schedule 31.12.2012
comment
Ребята, двух файлов достаточно, чтобы показать проблемы. Поскольку я разрабатываю фреймворк, мне приходится много чего выносить и просто в двух файлах. Вы можете скопировать и запустить их, чтобы увидеть проблему. Большое спасибо   -  person dareurdream    schedule 31.12.2012
comment
вы слышали о ColumnClass   -  person mKorbel    schedule 31.12.2012
comment
Вы можете скопировать и запустить их Вы можете объединить их в один. Почему 2 или более человек должны делать 2 копирования/вставки, когда один (тот, кто задает вопрос) может выполнить слияние?   -  person Andrew Thompson    schedule 31.12.2012
comment
@AndrewThompson, HovercraftFullOfEels, я думаю, вы ясно изложили свою точку зрения, нет необходимости настаивать на этом дальше.   -  person Olaf Dietsche    schedule 31.12.2012
comment
Вопрос заключается в том, чтобы удерживать порядки сортировки после фильтрации или нет   -  person mKorbel    schedule 31.12.2012
comment
Вы правы, стандартно отображаемый JTable уже должен иметь функциональные возможности клавиш со стрелками. Если это не работает для вас, рассмотрите возможность упрощения/уменьшения кода, пока не изолируете проблему. Я думаю, что это основная мотивация для создания sscce — она заставляет вас изолировать проблему, облегчая обнаружение ее источника и ее решение. Если нет, то вы все равно можете опубликовать меньший объем кода, который воспроизводит проблему.   -  person Hovercraft Full Of Eels    schedule 31.12.2012
comment
Ребята, я просмотрел предыдущие решения и принял решения, которые я реализовал в рамках. И еще прошу извинить за задержку с приемом, но я не был в состоянии принять их раньше. Я рассчитываю на вашу постоянную поддержку. Спасибо всем   -  person dareurdream    schedule 31.12.2012
comment
@mKorbel - Нет, я не знаю о ColumnClass. Сейчас посмотрю ссылку..   -  person dareurdream    schedule 31.12.2012
comment
@mKorbel - Вы говорите о методе getColumnClass. Поскольку я использую DefaultTableModel, не будет ли он обрабатывать ячейки как строку. В этом конкретном случае я хочу, чтобы все обрабатывалось как String, поэтому я не переопределял метод, полагая, что он автоматически отправит все как String.   -  person dareurdream    schedule 31.12.2012
comment
@HovercraftFullOfEels - Да, вы правы, я пытался изолировать и решить проблему, но мои очень ограниченные знания Swing мне не помогают.   -  person dareurdream    schedule 31.12.2012
comment
Мне интересно, является ли это проблемой фокуса, поскольку фокус никогда не покидает JTextField, когда отображается JWindow с JTable. На это указывает поведение, и я доказал это с помощью FocusListener. Таким образом, все нажатия клавиш, включая клавиши со стрелками, будут направляться в JTextField, а не в JTable.   -  person Hovercraft Full Of Eels    schedule 31.12.2012
comment
@HovercraftFullOfEels - Да, вы правы. Что мне делать тогда?   -  person dareurdream    schedule 31.12.2012
comment
Я не уверен, так как ты делаешь то, чего я никогда не делал. Клуджем было бы использовать привязки клавиш к текстовому полю, чего я не рекомендую. Я бы поэкспериментировал, чтобы получить фокус на JTable или попробовать привязки клавиш на jtable.   -  person Hovercraft Full Of Eels    schedule 31.12.2012
comment
@HovercraftFullOfEels - Спасибо. В то же время я бы также попробовать что-то другое.   -  person dareurdream    schedule 31.12.2012


Ответы (1)


ты имеешь в виду

  • используйте недекорированный JDialog вместо JWindow, иначе JTextComponets нельзя редактировать

  • JDialog лучше поддерживает AlwaysOnTop и ModalityTypes (только для setAlwaysOnTop)

  • не пересоздавайте базовые настройки снова и снова, не пересоздавайте всплывающее окно, используйте переменную lolac, удалите все содержимое и добавьте новый, определите все настройки для JDialog один раз, см. исключение (диалог отображается.) в случае, если всплывающее окно скрыто и значение в JTextField не пустое

  • пропущенное действие для скрытия JDialog на ESC key event, скрытие JDialog, если JFrame минимизировано

  • пропущено перемещение с JDialog, если JFrame изменен размер, перемещено по экрану на другое Point,

  • прикрепите Document к JTextField напрямую, не потерявшись где-то в определениях JScrollPane

  • в вашем коде отсутствует несколько хороших практик, тогда все возможно, но не с этот код (тоже после моего редактирования)

  • найдите JCalendar by Kay Toedter (лучший обходной путь для всплывающего окна, который я видел для всплывающего окна)

только удалены полезные методы, перемещены из- в, обратите внимание non_optimized_code, просто поместите в recyclebin и снова напишите это

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.RowFilter;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

public class SearchBox extends JPanel {

    private static final long serialVersionUID = 1L;
    private static JFrame frame = new JFrame();
    private JTextField editor;
    private JButton arrowButton;
    //private JToggleButton arrowButton;
    private JDialog popupWindow = new JDialog(frame);
    private Component userComponent;
    private JTable table;
    private TableRowSorter<DefaultTableModel> rowSorter;
    private Object[] columnNames;
    private DefaultTableModel tableModel;
    private Object[][] sheetDataInString;

    public SearchBox() {
        super(new FlowLayout(FlowLayout.LEFT, 0, 0));
        editor = new JTextField();
        editor.setPreferredSize(new Dimension(250, 25));
        editor.getDocument().addDocumentListener(new DocumentListener() {

            @Override
            public void changedUpdate(DocumentEvent e) {
                newFilter();
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                newFilter();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                newFilter();
            }

            private void newFilter() {
                RowFilter<DefaultTableModel, Object> rowFilter = null;
                Document document = editor.getDocument();
                String filterText;
                try {
                    filterText = document.getText(0, document.getLength()).trim();
                    rowFilter = RowFilter.regexFilter("(?i)" + filterText);
                } catch (java.util.regex.PatternSyntaxException e) {
                    return;
                } catch (BadLocationException badLocationException) {
                    return;
                }
                rowSorter.setRowFilter(rowFilter);
                table.setRowSorter(rowSorter);
            }
        });
        initialize();
        addListeners();
        setBorders();
    }

    private void addListeners() {
        arrowButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (!popupWindow.isVisible()) {
                    showWindow();
                } else {
                    hideWindow();
                }
            }
        });
    }

    protected void showWindow() {
        if (null != getWindowComponent()) {
            popupWindow.getContentPane().add(getWindowComponent());
            popupWindow.setLocation(new Point(SearchBox.this.getLocationOnScreen().x, SearchBox.this.getLocationOnScreen().y + 25));
            popupWindow.setUndecorated(true);
            popupWindow.setAlwaysOnTop(true);
            popupWindow.pack();
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    popupWindow.setVisible(true);
                }
            });
        }
    }

    protected void hideWindow() {
        popupWindow.setVisible(false);
    }

    private Component getWindowComponent() {
        return userComponent;
    }

    public void setWindowComponent(Component component) {
        userComponent = component;
    }

    private void initialize() {
        arrowButton = new BasicArrowButton(SwingConstants.SOUTH);//In my code there is an icon here
        arrowButton.setBorder(null);
        arrowButton.setContentAreaFilled(false);
    }

    private void setBorders() {
        add(editor);
        add(arrowButton);
        setBackground(editor.getBackground());
        setBorder(editor.getBorder());
        editor.setBorder(null);
    }

    public JTextField getTextComponent() {
        return editor;
    }

    public JButton getActionButton() {
        return arrowButton;
    }

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

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    protected static void createAndShowGUI() {
        JPanel panel = new JPanel();

        frame.setPreferredSize(new Dimension(500, 400));
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        panel.add(new JLabel("Test Table Combo"));
        SearchBox searchBox = new SearchBox();
        searchBox.userComponent = searchBox.new SearchBoxTable();
        panel.add(searchBox);

        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private class SearchBoxTable extends JScrollPane {

        private static final long serialVersionUID = 1L;

        public SearchBoxTable() {
            columnNames = new Object[]{"Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6"};
            sheetDataInString = new Object[21][6];
            for (int i = 0; i < sheetDataInString.length; i++) {
                for (int j = 0; j < 6; j++) {
                    sheetDataInString[i][j] = "Row Value : " + i + ", Column Value : " + j;
                }
            }

            tableModel = new DefaultTableModel(sheetDataInString, columnNames) {

                private static final long serialVersionUID = 1L;

                @Override
                public boolean isCellEditable(int row, int column) {
                    return true;
                }
            };
            rowSorter = new TableRowSorter<DefaultTableModel>(tableModel);
            table = new JTable(tableModel);
            table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
            table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            table.setAutoCreateRowSorter(true);
            table.setFillsViewportHeight(true);
            table.getTableHeader().setFont(new Font(null, Font.PLAIN, 13));
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
            setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            getViewport().add(table);
        }
    }
}
person mKorbel    schedule 31.12.2012
comment
Но у меня есть один вопрос. Могу ли я не уничтожить всплывающее окно и создавать снова и снова? Не будет ли это потреблять много ресурсов, чтобы удерживать ресурсы всплывающих окон. В одном графическом интерфейсе, если у пользователя есть 20 таких компонентов, он не будет содержать много ресурсов. Спасибо - person dareurdream; 01.01.2013
comment
создать всплывающее окно только раз, использовать CardLayout для переключения между представлениями, затем это идея требует очистить/установить только значение для JComponent в текущем представлении - person mKorbel; 01.01.2013
comment
Оки сделает это наверняка, так как это сэкономит усилия на их создание снова и снова. А вот как у них с потреблением ресурсов.... - person dareurdream; 01.01.2013
comment
Я прошел по предоставленной вами ссылке, и я понимаю, что простое удаление не освободит ресурсы. Итак, что мне делать, чтобы высвободить все ресурсы, когда пользователь переходит от одной бизнес-функции к другой. Поскольку это отдельное приложение, которое также кэширует не менее 15000 строк данных Excel (15 столбцов), управление памятью важно для меня. Я должен сделать это, так как эти данные в основном предназначены для раскрывающегося списка, таблицы данных и списков (все статические данные). - person dareurdream; 01.01.2013
comment
@dareurdream по умолчанию (15000 rows of excel data (15 columns) memory management is important for me) нет проблем с хранением в памяти, но может возникнуть проблема с фильтрацией (поиск во всех строках и столбцах любых комбинаций в тексте), первый и второй символы, введенные в JTextField, могут вызвать зависание графического интерфейса, необходимо применить RowFilter после ввода 3-х символов в JTextField числовые комбинации уменьшаются - person mKorbel; 01.01.2013
comment
Фильтрация выполняется при изменении значения в полях со списком, выборе строки таблицы и выборе элемента списка. И большая часть данных сохраняется в HashMap как значение ключа/объекты, созданные (в зависимости от типа компонента, с которым он будет использоваться). Фильтрация динамических данных не производится. Все данные загружаются в память при запуске приложения. Это хороший подход? На сегодняшний день у меня нет проблем с зависанием производительности/графического интерфейса и памятью, но я беспокоюсь о том, что происходит, когда приложение имеет 30000 строк (скажем, 30 столбцов). - person dareurdream; 01.01.2013