как обнаружить нажатие ввода во время редактирования ячейки jtable?

У меня есть прослушиватель ключей на jtable, поэтому, когда кто-то нажимает ввод, происходят некоторые вычисления. Однако это происходит только в том случае, если человек не редактирует. Я хотел бы применить это действие, когда человек заканчивает редактирование ячейки и нажимает клавишу ввода, чтобы завершить и закрыть редактирование.

Я не могу понять это, кто-нибудь когда-либо делал это или знает, как это сделать?

По сути, теперь, чтобы действие было выполнено, люди должны дважды нажать клавишу ввода, один раз, чтобы завершить редактирование, а другой — для действия, которое я хочу выполнить, я бы хотел, чтобы это требовалось только один раз, во время редактирования.

Спасибо


person allegroBegin    schedule 07.01.2014    source источник
comment
KeyListener, вероятно, не ваш друг, это бывает редко. Когда ячейка обновляется, вызывается метод setValueAt модели, который может быть лучшим выбором для получения обновлений. Если это слишком много работы. Это должно вызвать событие модели таблицы, на которое вы также можете отреагировать...   -  person MadProgrammer    schedule 08.01.2014
comment
это, наверное, хорошая идея, но я не могу ее осуществить, я переопределяю оригинал, но в основном это становится циклом, так как я делаю setValue, он вызывает метод, который вычисляет, а затем снова использует setValue и так далее и так далее, пока он не станет переполнение стека.   -  person allegroBegin    schedule 08.01.2014
comment
Лично у меня была бы кнопка с названием «Обновить» (например) и привязка клавиши (возможно, F5), которая отвечала бы за обновление вычислений и обновление состояния модели. Намерение здесь состоит в том, чтобы отделить расчет от модели и таблицы... но это только я;)   -  person MadProgrammer    schedule 08.01.2014
comment
MadProgrammer, да, это слишком простая идея (которую я бы использовал и для себя), но непригодная для использования обычными пользователями, которые хотят делать что-то быстро и легко (поверьте мне, у меня было так много проблем с этими людьми) в основном, все должно работать так же, как excel, вы вносите изменения, все нужно обновлять, не нажимая кнопку, ничего не нажимая, поэтому редактирование остановлено здесь отлично работает   -  person allegroBegin    schedule 08.01.2014
comment
Вы должны поставить @MadProgrammer, тогда он получит уведомление.   -  person nachokk    schedule 08.01.2014
comment
вы делаете модификацию, все нужно обновить это задача модели..   -  person kleopatra    schedule 08.01.2014
comment
@allegroBegin Это может означать. Либо делайте свои обновления в модели (используя setValueAt), либо используйте прослушиватель модели. Переопределение JTable не рекомендуется, связывает вас с одной реализацией, может мешать известному рабочему процессу и, как правило, является анти-шаблоном и плохим дизайном...   -  person MadProgrammer    schedule 09.01.2014


Ответы (3)


Вы можете переопределить JTable.editingStopped, который вызывается после завершения редактирования, и примените ваши действия в этом методе.

ИЗМЕНИТЬ:

JTable.editingStopped не предназначен для расширения приложения. Чтобы избежать осложнений, в частности зависящих от платформы, лучше переопределить setValueAt модели или зарегистрировать TableModelListener. Вот пример:

import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

public class DemoTable3 {
    private static void createAndShowUI() {
        JFrame frame = new JFrame("DemoTable");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Object[][] rows = { { "Column 1", "Column 2" },
                { "Column 1", "Column 2" } };
        Object[] columns = { "Column 1", "Column 2" };

        DefaultTableModel model = new DefaultTableModel(rows, columns);
        model.addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
                System.out.println("apply additional action");
            }
        });

        JTable table = new JTable(model);
        frame.add(new JScrollPane(table));
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);
    }

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

Другой альтернативой является добавление CellEditorListener для перехвата событий editingStopped. Например:

import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableModel;

public class DemoTable2 {

    private static void createAndShowUI() {
        JFrame frame = new JFrame("DemoTable");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Object[][] rows = { { "Column 1", "Column 2" },
                { "Column 1", "Column 2" } };
        Object[] columns = { "Column 1", "Column 2" };

        final JTable table = new JTable(new DefaultTableModel(rows, columns));

        table.getDefaultEditor(String.class).addCellEditorListener(
                new CellEditorListener() {
                    public void editingCanceled(ChangeEvent e) {
                        System.out.println("editingCanceled");
                    }

                    public void editingStopped(ChangeEvent e) {
                        System.out.println("editingStopped: apply additional action");
                    }
                });

        frame.add(new JScrollPane(table));
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);
    }

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

Также обратите внимание на Table Cell Listener от @camickr, который предлагает пользовательская обработка правок.

person tenorsax    schedule 07.01.2014
comment
-1 Application code will not use these methods explicitly, they are used internally by JTable. Я думаю, вам следует реализовать CellEditorListener - person nachokk; 08.01.2014
comment
CellEditorListener вообще не работал, вероятно, по моей вине, однако способ, предложенный Аква, работал отлично, спасибо, несколько дней работы, наконец, с чем-то, что можно было бы показать для него. } - person allegroBegin; 08.01.2014
comment
@allegroBegin Добро пожаловать! Я рад, что это помогло вам :) - person tenorsax; 08.01.2014
comment
@nachokk прав; если вы не можете использовать привязку клавиш, альтернатива предлагается здесь. - person trashgod; 08.01.2014
comment
Кстати, table.putClientProperty (terminateEditOnFocusLost, Boolean.TRUE); с успехом для стандартных JComponets - person mKorbel; 08.01.2014
comment
@allegroBegin, если это решение, вы, скорее всего, боретесь с ветрами свинга - лучший совет, который я мог бы дать, - повторно посетить ваш дизайн ;-) -1 за предложение ядерного оружия. - person kleopatra; 08.01.2014
comment
трэшбод, я просмотрел все ваши ответы на эту тему, прежде чем спросить (вы постоянно появлялись в Google), но ничего из того, что я нашел, здесь или в любом другом сообществе не работало так, как я делал, я рад узнавать новые вещи для других программ я могу сделать, но это работает очень хорошо и очень быстро, я действительно не понимаю, в чем проблема, @kleopatra, я вижу, ты самопровозглашенный эксперт по свингу, и я не сомневаюсь в этом, но не могли бы вы быть немного более точным в своем совете о пересмотре моего дизайна вместо того, чтобы использовать что-то, что мне кажется совершенно подходящим? Например, почему бы и нет, что еще и т. д. - person allegroBegin; 08.01.2014
comment
@allegroBegin хорошо, если вы переопределите JTable#editingStopped, если вы прочитаете ссылку, в которой парни из оракула говорят, что этот метод используется внутри JTable, Application code will not use these method explicity если вы решили переопределить его, вам нужно вызвать super.editingStopped что такое плохой дизайн, и, возможно, этот метод это внутренний вызов иногда, когда вы не хотите, чтобы вам звонили;).. - person nachokk; 08.01.2014
comment
@allegroBegin: я бы выбрал привязку ключа, описанную здесь, вместо ключевого прослушивателя; Аква: +1 за CellEditorListener, оставшийся после поспешного прочтения исходного ответа. - person trashgod; 08.01.2014
comment
Было бы лучше использовать TableModel#setValueAt или реализовать прослушиватель TableModel. Переопределение таблицы таким образом является плохим дизайном и анти-шаблоном. Поскольку таблица может использовать несколько редакторов, это также означает, что вам не нужно беспокоиться о попытке охватить все возможности... ИМХО - person MadProgrammer; 09.01.2014
comment
@MadProgrammer согласен, TableModelListener чище, отредактировано :) - person tenorsax; 09.01.2014
comment
проблема плохо определена - я предполагаю, что @allegroBegin делает что-то довольно далекое от рекомендуемых подходов: это определенно собственный бизнес модели (по сравнению с слушателем), чтобы обновлять свое внутреннее состояние, если что-то изменилось, т.е. путем редактирования или по другим причинам. Проблема с конкретным ключом (и его различным поведением без редактирования) больше похожа на проблему с предполагаемым (неправильным) решением, чем с реальным требованием. Не зная этого, на вопрос нельзя ответить, поэтому проголосовали за закрытие. - person kleopatra; 09.01.2014
comment
Хорошо, я использовал cellEditorListener, он тоже работает, я все еще думаю, что Aqua дала лучшие ответы не только для меня, но и для всех, кто ищет это, и я также считаю этот вопрос закрытым. - person allegroBegin; 10.01.2014

Вы можете настроить свой собственный редактор. Использование DefaultCellEditor Вместо использования KeyListener следует использовать Привязки ключей.

См. этот пример.

            JTable table = new JTable(myModel);
            JTextField cell = new JTextField();
            final TableCellEditor cellEditor = new DefaultCellEditor(cell);
            table.getColumnModel().getColumn(column).setCellEditor(cellEditor);
            InputMap iMap = cell.getInputMap(JComponent.WHEN_FOCUSED);
            iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),    KeyEvent.getKeyText(KeyEvent.VK_ENTER));
            ActionMap aMap = cell.getActionMap();
            aMap.put(KeyEvent.getKeyText(KeyEvent.VK_ENTER), new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(callSomeOperationsIsOk()){
                      cellEditor.stopCellEditing();
                    }else{
                      cellEditor.cancelCellEditing();
                    }
                }
            });
    }

Узнайте больше в учебниках Как использовать таблицы, и, возможно, вы у меня та же проблема, что и у моего предыдущего вопроса

person nachokk    schedule 07.01.2014
comment
спасибо, интересная идея, я бы проголосовал, но не могу на моем нынешнем ранге - person allegroBegin; 08.01.2014
comment
@allegroBegin я убираю наследование, потому что теперь в этом нет необходимости, оно лучше и гибче :) - person nachokk; 08.01.2014
comment
это выглядит очень круто для другой программы, над которой я работаю, но я еще не добрался до пользовательского интерфейса, большое спасибо - person allegroBegin; 08.01.2014

У меня есть прослушиватель ключей на jtable, поэтому, когда кто-то нажимает ввод, происходят некоторые вычисления. Однако это происходит только в том случае, если человек не редактирует. Я хотел бы применить это действие, когда человек заканчивает редактирование ячейки и нажимает клавишу ввода, чтобы завершить и закрыть редактирование.

  • TableCellEditor не имеет чего-то с KeyListener, добавленным в JTable

По сути, теперь, чтобы действие было выполнено, люди должны дважды нажать клавишу ввода, один раз, чтобы завершить редактирование, а другой — для действия, которое я хочу выполнить, я бы хотел, чтобы это требовалось только один раз, во время редактирования.

  • JComponents (используется как TableCellEditor) по умолчанию реагирует на нажатие клавиши ENTER

  • не помещайте JComponent в TableModel, там должно храниться только значение, нарисованное TableCellRenderer, и начальное значение для TableCellEditor

  • TableCellEditor временно является JComponent, вам нужно добавить KeyBindings для вызова stopCellEditing в случае, если JComponents, используемые в качестве TableCellEditor, не реагируют на нажатие клавиши ENTER


person mKorbel    schedule 07.01.2014
comment
Подробнее здесь о подходящей привязке клавиш. - person trashgod; 08.01.2014
comment
спасибо за все советы, я не мог опубликовать какой-либо полезный SSCCE, так как у меня там нет ничего, что могло бы показать, в чем моя проблема, кроме прослушивателя ключей на jtable. Я ценю ваши ссылки, я читал о пользовательских рендерерах, но не помешает прочитать больше. - person allegroBegin; 08.01.2014