I have the following window. I need to be able to edit the text when I click on the JTextField.

enter image description here

Explanation: JTextField is inside a JComponent called PriorityPanel. When I click on JTextField, it calls this.requestFocus(); meaning that the PriorityPanel will gain focus. This way I cannot edit the text of the TextField.
In comparison, I can still modify the value of JSlider even if it bahaves exactly the same way. When I click on JSlider, the PriorityPanel will gain focus.

The described problem is in this part:

//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
}

Here is the 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());
                }
            });
        }
    }
}
有帮助吗?

解决方案

From the looks of things, you are trying to modify the state of the parent container when one of the child components becomes focused.

Instead of trying to add a focus listener to the parent container, which is going to cause you some considerable havoc, try adding a single FocusListener to all the child components, for example...

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);

Now, I would be taking a peek at the KeyBoardFocusManager#getFocusOwner and back tracking it's container hierarcy when ever focusLost is called to try and determine if the component who now has focus is a child of mine...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top