我有以下窗口。我需要能够在单击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());
}
});
}
}
}
答案 0 :(得分:3)
从外观上看,当其中一个子组件聚焦时,您正在尝试修改父容器的状态。
不要试图将焦点侦听器添加到父容器中,这会给您带来一些相当大的破坏,请尝试向所有子组件添加单个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
,并在调用focusLost
时回溯跟踪它的容器层次,以尝试确定现在具有焦点的组件是否是我的孩子。 ..