我有以下窗口。当我单击 JTextField 时,我需要能够编辑文本。

说明: JTextField 位于名为 PriorityPanel 的 JComponent 中。当我点击 JTextField 时,它会调用 this.requestFocus();这意味着 PriorityPanel 将获得焦点。
这样我就无法编辑 TextField 的文本。
相比之下,我仍然可以修改 JSlider 的值,即使它的方式完全相同。当我点击 JSlider 时,PriorityPanel 将获得焦点。

描述的问题在这部分:

//constructor
public PriorityPanel(Priority p, int row) {
    this.Slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 100);
    this.model = p;
    this.rowName = row;
    this.TextField = new JTextField(model.getTitle());
    setLayout(new GridLayout(1, 2));
    add(TextField);
    add(Slider);
    addFocusListener(new FocusAdapter() {
        @Override
        public void focusGained(FocusEvent e) {
            TextField.setBackground(new Color(220, 220, 255));
            Slider.setBackground(new Color(220, 220, 255));
            JPriorityEditor.this.selectedRow = rowName;
        }

        @Override
        public void focusLost(FocusEvent e) {
            TextField.setBackground(Color.WHITE);
            Slider.setBackground(Color.WHITE);
        }
    });
    Slider.addMouseListener(new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {
            requestFocus();
        }
    });
    TextField.addMouseListener(new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {
            requestFocus();
        }
    });
    //atc
}

这是 SSCCE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import static test.Priority.staticPriorities;

class Main{
    public static void main(String[] args) {
        staticPriorities.add(new Priority("AutoGen1"));
        staticPriorities.add(new Priority("AutoGen2"));
        GridBagConstraints gbc = new GridBagConstraints();
        JPanel panelAll = new JPanel(new GridBagLayout());
        JPanel panelBottom = new JPanel(new GridLayout(1,2));
        JButton buttonNew = new JButton("buttonNew");
        JButton buttonRemove = new JButton("buttonErase");
        final JPriorityEditor priorityEditor = new JPriorityEditor();

        //Add to panelBottom
        panelBottom.add(buttonNew);
        panelBottom.add(buttonRemove);

        //Add to panelAll
        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.fill = GridBagConstraints.BOTH;
        panelAll.add(priorityEditor, gbc);
        gbc.weighty = 0;
        gbc.gridy = 1;
        panelAll.add(panelBottom, gbc);

        buttonNew.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                priorityEditor.AddNewPriority();
            }
        });
        buttonRemove.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                priorityEditor.RemovePriority();
            }
        });

        JFrame d = new JFrame("windowPrioritiesTitle");
        d.add(panelAll, BorderLayout.CENTER);
        d.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        d.pack();
        d.setMinimumSize(d.getSize());
        d.setLocationRelativeTo(null);
        d.setVisible(true);
    }
}

/**
 * This is only an object
 * @author Daniel
 */
class Priority {

    public static ArrayList<Priority> staticPriorities = new ArrayList<>();
    private String Title;
    private int Percent;

    public Priority(String title) {
        this.Title = title;
        int sum = 0;
        for (Priority p : staticPriorities) {
            sum += p.Percent;
        }
        this.Percent = 100 - sum;
    }

    public String getTitle() {
        return Title;
    }

    public void setTitle(String title) {
        this.Title = title;
    }

    public int getPercent() {
        return Percent;
    }

    public void setPercent(int newValue) {
        this.Percent = newValue;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Priority) {
            return ((Priority) obj).getTitle().equals(this.getTitle());
        } else {
            return false;
        }
    }
}

/**
 * My own component
 */
public final class JPriorityEditor extends JScrollPane {

    private PriorityPanel[] priorityPanels;
    private int selectedRow;
    private JPanel con;

    public JPriorityEditor() {
        super(new JPanel());
        this.selectedRow = -1;
        ArrayList<Priority> Priorities = Priority.staticPriorities;
        priorityPanels = new PriorityPanel[Priorities.size()];
        this.con = (JPanel) getViewport().getView();
        con.setLayout(new GridBagLayout());
        con.setBackground(Color.WHITE);
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.weightx = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        int i = 0;
        for (; i < Priorities.size(); i++) {
            gbc.gridy = i;
            priorityPanels[i] = new PriorityPanel(Priorities.get(i), i);
            con.add(priorityPanels[i], gbc);
        }
        gbc.weighty = 1;
        gbc.gridy = i;
        con.add(new JComponent(){},gbc);
    }

    public void AddNewPriority(){
        con.removeAll();
        Priority p = new Priority("NewTitle");
        Priority.staticPriorities.add(p);

        ArrayList<Priority> Priorities = Priority.staticPriorities;
        priorityPanels = new PriorityPanel[Priorities.size()];
        con.setLayout(new GridBagLayout());
        con.setBackground(Color.WHITE);
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.weightx = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        int i = 0;
        for (; i < Priorities.size(); i++) {
            gbc.gridy = i;
            priorityPanels[i] = new PriorityPanel(Priorities.get(i), i);
            con.add(priorityPanels[i], gbc);
        }
        gbc.weighty = 1;
        gbc.gridy = i;
        con.add(new JComponent() {
        }, gbc);
        con.updateUI();
    }

    public void RemovePriority() {
        if (selectedRow != -1) {
            Priority.staticPriorities.remove(Priority.staticPriorities.get(selectedRow));
            con.removeAll();
            ArrayList<Priority> Priorities = Priority.staticPriorities;
            priorityPanels = new PriorityPanel[Priorities.size()];
            con.setLayout(new GridBagLayout());
            con.setBackground(Color.WHITE);
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            int i = 0;
            for (; i < Priorities.size(); i++) {
                gbc.gridy = i;
                priorityPanels[i] = new PriorityPanel(Priorities.get(i), i);
                con.add(priorityPanels[i], gbc);
            }
            gbc.weighty = 1;
            gbc.gridy = i;
            con.add(new JComponent() {
            }, gbc);
            con.updateUI();
        }
    }

    /**
     * Another custom component
     */
    private class PriorityPanel extends JComponent {

        int rowName;
        JSlider Slider;
        JTextField TextField;
        Priority model;

        public PriorityPanel(Priority p, int row) {
            this.Slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 100);
            this.model = p;
            this.rowName = row;
            this.TextField = new JTextField(model.getTitle());
            setLayout(new GridLayout(1, 2));
            add(TextField);
            add(Slider);
            addFocusListener(new FocusAdapter() {
                @Override
                public void focusGained(FocusEvent e) {
                    TextField.setBackground(new Color(220, 220, 255));
                    Slider.setBackground(new Color(220, 220, 255));
                    JPriorityEditor.this.selectedRow = rowName;
                }

                @Override
                public void focusLost(FocusEvent e) {
                    TextField.setBackground(Color.WHITE);
                    Slider.setBackground(Color.WHITE);
                }
            });
            Slider.addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    requestFocus();
                }
            });
            TextField.addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    requestFocus();
                }
            });
            Slider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    int value = Slider.getValue();
                    model.setPercent(value);
                }
            });
            TextField.getDocument().addDocumentListener(new DocumentListener() {
                @Override
                public void insertUpdate(DocumentEvent e) {
                    SetText();
                }

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

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

                private void SetText() {
                    model.setTitle(TextField.getText());
                }
            });
        }
    }
}

最佳答案

从表面上看,当其中一个子组件成为焦点时,您正在尝试修改父容器的状态。

与其尝试向父容器添加一个焦点监听器,这会给您造成相当大的破坏,不如尝试向所有子组件添加一个 FocusListener,例如...

FocusAdapter fa = new FocusAdapter() {
    @Override
    public void focusGained(FocusEvent e) {
        TextField.setBackground(new Color(220, 220, 255));
        Slider.setBackground(new Color(220, 220, 255));
        JPriorityEditor.this.selectedRow = rowName;
    }

    @Override
    public void focusLost(FocusEvent e) {
        TextField.setBackground(Color.WHITE);
        Slider.setBackground(Color.WHITE);
    }
});
Slider.addFocusListener(fa);
TextField.addFocusListener(fa);

现在,当 KeyBoardFocusManager#getFocusOwner 被调用以尝试确定现在具有焦点的组件是否是我的 child 时,我将查看 focusLost 并回溯跟踪它的容器层次结构......

关于java - 在其父容器上调用 requestFocus() 后,我需要 JTextField 可编辑,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18800852/

10-13 00:41