滚动后通过 JComboBox 的下拉列表显示的 JTextField
JTextField showing through JComboBox's dropdown after Scrolling
当 JTextField
在 JScrollPanel
中时,如果面板已滚动,只要 JComboBox
的下拉菜单位于 JTextField
上方,文本字段通过下拉菜单显示。
这仅发生在内容滚动之后(不是在应用程序启动时)。
主要问题是我们如何解决这个问题?
答案加分:
- 不是黑客
- 首先解释为什么会发生这种情况
我尝试过的事情:
- 将下拉列表移到滚动窗格外(无变化)
- 为我在卷轴上找到的所有容器添加重绘(无变化)
- 滚动窗格内容的不同布局管理器(无变化)
代码示例:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TextFieldShowsThrough{
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createScrollDemo());
frame.pack();
// For demonstration purposes
frame.setSize(frame.getWidth() + 100, frame.getHeight() - 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static JScrollPane createScrollDemo(){
final Box optionsPanel = Box.createVerticalBox();
optionsPanel.add(createDropDown());
optionsPanel.add(createTextField("Option1"));
optionsPanel.add(createTextField("Option2"));
optionsPanel.add(createTextField("Option3"));
optionsPanel.add(createTextField("Option4"));
optionsPanel.add(createTextField("Option5"));
optionsPanel.add(Box.createVerticalGlue());
JScrollPane result = new JScrollPane(optionsPanel);
// Made attempts to fix here, but to no avail
/*result.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
result.repaint();
}
});*/
return result;
}
public static Box createDropDown(){
Box b = Box.createVerticalBox();
b.setAlignmentX(JLabel.LEFT_ALIGNMENT);
b.add(new JLabel("Language"));
JComboBox combo = new JComboBox(new String[]{"en", "fr", "es"});
combo.setMaximumSize(new Dimension(500, 25));
b.add(combo);
return b;
}
public static Box createTextField(String label){
Box mainBox = Box.createVerticalBox();
mainBox.setOpaque(true);
mainBox.setBackground(new Color((int)(Math.random() * 0x1000000))); // because fun
JLabel jLabel = new JLabel(label);
jLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
mainBox.add(jLabel);
Box secondaryBox = Box.createHorizontalBox();
secondaryBox.setAlignmentX(JLabel.LEFT_ALIGNMENT);
TextField tf = new TextField();
tf.setMaximumSize(new Dimension(500, 25));
secondaryBox.add(tf);
mainBox.add(secondaryBox);
return mainBox;
}
}
那是因为您在轻量级容器中使用了 java.awt.TextField
,这是一种重量级组件。 JComboBox
使用的弹出窗口 window 也可以是轻量级组件。
AWT 组件不能很好地与 Swing 组件配合使用,它们存在 z 顺序问题。
将TextField tf = new TextField();
更改为JTextField tf = new JTextField();
您还应避免使用 setPreferred/Minimum/MaximumSize
(有关详细信息,请参阅 Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?),而是使用布局约束和大小调整提示(例如 columns
属性 JTextField
)
当 JTextField
在 JScrollPanel
中时,如果面板已滚动,只要 JComboBox
的下拉菜单位于 JTextField
上方,文本字段通过下拉菜单显示。
这仅发生在内容滚动之后(不是在应用程序启动时)。
主要问题是我们如何解决这个问题? 答案加分:
- 不是黑客
- 首先解释为什么会发生这种情况
我尝试过的事情:
- 将下拉列表移到滚动窗格外(无变化)
- 为我在卷轴上找到的所有容器添加重绘(无变化)
- 滚动窗格内容的不同布局管理器(无变化)
代码示例:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TextFieldShowsThrough{
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createScrollDemo());
frame.pack();
// For demonstration purposes
frame.setSize(frame.getWidth() + 100, frame.getHeight() - 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static JScrollPane createScrollDemo(){
final Box optionsPanel = Box.createVerticalBox();
optionsPanel.add(createDropDown());
optionsPanel.add(createTextField("Option1"));
optionsPanel.add(createTextField("Option2"));
optionsPanel.add(createTextField("Option3"));
optionsPanel.add(createTextField("Option4"));
optionsPanel.add(createTextField("Option5"));
optionsPanel.add(Box.createVerticalGlue());
JScrollPane result = new JScrollPane(optionsPanel);
// Made attempts to fix here, but to no avail
/*result.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
result.repaint();
}
});*/
return result;
}
public static Box createDropDown(){
Box b = Box.createVerticalBox();
b.setAlignmentX(JLabel.LEFT_ALIGNMENT);
b.add(new JLabel("Language"));
JComboBox combo = new JComboBox(new String[]{"en", "fr", "es"});
combo.setMaximumSize(new Dimension(500, 25));
b.add(combo);
return b;
}
public static Box createTextField(String label){
Box mainBox = Box.createVerticalBox();
mainBox.setOpaque(true);
mainBox.setBackground(new Color((int)(Math.random() * 0x1000000))); // because fun
JLabel jLabel = new JLabel(label);
jLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
mainBox.add(jLabel);
Box secondaryBox = Box.createHorizontalBox();
secondaryBox.setAlignmentX(JLabel.LEFT_ALIGNMENT);
TextField tf = new TextField();
tf.setMaximumSize(new Dimension(500, 25));
secondaryBox.add(tf);
mainBox.add(secondaryBox);
return mainBox;
}
}
那是因为您在轻量级容器中使用了 java.awt.TextField
,这是一种重量级组件。 JComboBox
使用的弹出窗口 window 也可以是轻量级组件。
AWT 组件不能很好地与 Swing 组件配合使用,它们存在 z 顺序问题。
将TextField tf = new TextField();
更改为JTextField tf = new JTextField();
您还应避免使用 setPreferred/Minimum/MaximumSize
(有关详细信息,请参阅 Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?),而是使用布局约束和大小调整提示(例如 columns
属性 JTextField
)