assylias
assylias

Reputation: 328727

Focus lost when updating a JDialog

I have:

The code works as expected (information gets updated), except that the JTable loses focus and the JDialog gets the focus every time the selection is changed. So I have added a table.requestFocusInWindow but the JTable still loses the focus, although the call returns true.

How can I make sure that the JDialog gets updated but that the JTable does not lose the focus?

ps: My end goal is to be able to browse the table with the arrows (up / down) and see the information update in the JDialog - at the moment, I need to click on the rows to do that.

EDIT
See below a SSCCE that replicates my issue (the content of the JDialog changes when selection is changed but the focus is lost).

public class TestTable extends JTable {

    public static JFrame f = new JFrame();
    public static JTextField text = new JTextField();
    public static JDialog dialog;

    public static void main(String[] args) {
        f.setSize(300, 300);
        f.setLocation(300, 300);
        f.setResizable(false);
        showPopup();
        final JScrollPane jScrollPane = new JScrollPane();
        jScrollPane.getViewport().add(new TestTable());
        f.add(jScrollPane);
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public TestTable() {
        super();
        setModel(new TestTableModel());
        getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                ListSelectionModel lsm = (ListSelectionModel) e.getSource();
                int row = lsm.getAnchorSelectionIndex();

                Object item = getModel().getValueAt(row, 0);

                text.setText(item.toString());
                dialog.setVisible(true);
                TestTable.this.requestFocusInWindow(); //DOES NOT DO ANYTHING
            }
        });
        setCellSelectionEnabled(false);
    }

    public class TestTableModel extends DefaultTableModel {

        public TestTableModel() {
            super(new String[]{"DATA"}, 3);
            setValueAt(Double.valueOf(-0.1), 0, 0);
            setValueAt(Double.valueOf(+0.1), 1, 0);
            setValueAt(Double.valueOf(0), 2, 0);
        }
    }

    private static void showPopup() {
        dialog = new JDialog(f, "Title");
        dialog.setContentPane(text);
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.pack();
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);
    }
}

Upvotes: 0

Views: 1385

Answers (1)

Guillaume Polet
Guillaume Polet

Reputation: 47608

There must be something in your dialog that grabs the focus on the fly, because I have tried with a JLabel and it does not cause any problem. If you need to work around this, you can always call toFront() on your JTable parent Frame. If it does not help your case, try to edit this SSCCE to reproduce your issue.

See this code (comment the grabFocus on the label to convince yourself that there is something in your dialog that grabs the focus):

import java.awt.Component;
import java.util.Vector;

import javax.swing.FocusManager;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

public class Test {

    public static class MyTableModel extends DefaultTableModel {
        private int count;

        public MyTableModel() {
            addColumn("Test");
        }

        public void insertNewRow() {
            Vector<String> rowData = createNewRowData();
            insertRow(0, rowData);
        }

        private Vector<String> createNewRowData() {
            Vector<String> data = new Vector<String>(1);
            data.add("Hello-" + count++);
            return data;
        }

    }

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

    public void initUI() {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final MyTableModel model = new MyTableModel();
        final JTable table = new JTable(model);
        for (int i = 0; i < 100; i++) {
            model.insertNewRow();
        }
        final JLabel label = new JLabel();
        JDialog dialog = new JDialog(frame, false);
        dialog.add(label);
        dialog.setSize(300, 50);
        dialog.setLocation(400, 0);
        dialog.setVisible(true);
        table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                final Component focused = FocusManager.getCurrentManager().getFocusOwner();
                int index = table.getSelectionModel().getLeadSelectionIndex();
                if (index > -1) {
                    Object valueAt = model.getValueAt(index, 0);
                    label.setText("Current row selected is: " + valueAt);
                } else {
                    label.setText("No selection");
                }
                label.grabFocus();
                if (focused != null) {
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            frame.toFront();
                        }
                    });
                }
            }
        });
        final JScrollPane scroll = new JScrollPane(table);
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        frame.add(scroll);
        frame.pack();
        frame.setVisible(true);

    }
}

Upvotes: 1

Related Questions