Я обнаружил странную аномалию в Java Swing. Первая кнопка JButton, добавленная в пользовательский интерфейс в хронологическом порядке, всегда срабатывает, когда пользователь нажимает клавишу пробела, при условии, что перед этим он не нажал другую кнопку. Такое поведение возникает даже при вызове getRootPane().setDefaultButton(JButton)
и JButton.requestFocus()
. При запросе фокуса на JButton, кажется, есть как минимум 2 различных типа «фокуса». Один из «фокусов» или выделений - это пунктирный прямоугольник вокруг текста на кнопке, а другой - более толстый контур вокруг указанной кнопки.
Кнопка с пунктирным текстом срабатывает всякий раз, когда клавиша пробела нажата. Кнопка с толстой рамкой срабатывает всякий раз, когда нажимается клавиша ввода.
Я подготовил компилируемый минимальный пример, иллюстрирующий это поведение. Здесь вообще нет привязки / привязки клавиш.
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class ButtonFocusAnomalyExample extends JFrame {
public ButtonFocusAnomalyExample() {
super();
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
int frameWidth = 300;
int frameHeight = 300;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setTitle("Any Frame");
setResizable(false);
Container cp = getContentPane();
cp.setLayout(null);
setVisible(true);
new DialogMinimal(this, true); // Runs the Dialog
}
public static void main(String[] args) {
new ButtonFocusAnomalyExample();
}
static class DialogMinimal extends JDialog {
private final JTextField output = new JTextField();
public DialogMinimal(final JFrame owner, final boolean modal) {
super(owner, modal);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
int frameWidth = 252;
int frameHeight = 126;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setTitle("Minimal Button Focus Example");
Container cp = getContentPane();
cp.setLayout(null);
JButton bYes = new JButton();
bYes.setBounds(0, 0, 100, 33);
bYes.setText("Yes (Space)");
bYes.addActionListener(this::bYes_ActionPerformed);
JPanel buttonPanel = new JPanel(null, true);
buttonPanel.add(bYes);
JButton bNo = new JButton();
bNo.setBounds(108, 0, 120, 33);
bNo.setText("No (Enter/Return)");
getRootPane().setDefaultButton(bNo); // Set "No" as default button
bNo.requestFocus(); // Get focus on "No" button
bNo.addActionListener(this::bNo_ActionPerformed);
buttonPanel.add(bNo);
buttonPanel.setBounds(8, 8, 400, 92);
buttonPanel.setOpaque(false);
cp.add(buttonPanel);
output.setBounds(8, 50, 220, 32);
cp.add(output);
setResizable(false);
setVisible(true);
}
public void bYes_ActionPerformed(final ActionEvent evt) {
output.setText("Yes"); // Still fires on every space bar press
}
public void bNo_ActionPerformed(final ActionEvent evt) {
output.setText("No"); // Only fires on every return/enter press
}
}
}
Вот как это выглядит:
![Button Focus Example](https://i.stack.imgur.com/h0SO2.png)
The executable code can also be found здесь .
Мои вопросы:
- Что это за разные фокусы?
- Как можно изменить фокус, который отображается в виде пунктирного контура вокруг текста кнопки, чтобы пробел и клавиша ввода вызовет событие кнопки «Нет»?