Java setVisible()和正在绘制的组件之间发生了什么?
我有一个包含,然后包含一些自定义组件,它们是JPanel的扩展(它们都是相同类型)。此JScrollPane在显示包含内容之前设置为不可见 当用户选择一个按钮时,我将使用它来显示滚动窗格。但是,第一次显示窗格时,在调用Java setVisible()和正在绘制的组件之间发生了什么?,java,swing,visibility,Java,Swing,Visibility,我有一个包含,然后包含一些自定义组件,它们是JPanel的扩展(它们都是相同类型)。此JScrollPane在显示包含内容之前设置为不可见 当用户选择一个按钮时,我将使用它来显示滚动窗格。但是,第一次显示窗格时,在调用setVisible()和绘制窗格之间有明显的延迟。如果用户取消选中并重新选中该复选框,则会立即绘制窗格 我的自定义组件已经构建并添加到面板中。它们是s,但除了。它们也有一个自定义方法,但该方法中的断点显示延迟发生在调用this之前,因此这不是一个缓慢绘制的情况 JScrollPa
setVisible()
和绘制窗格之间有明显的延迟。如果用户取消选中并重新选中该复选框,则会立即绘制窗格
我的自定义组件已经构建并添加到面板中。它们是s,但除了。它们也有一个自定义方法,但该方法中的断点显示延迟发生在调用this之前,因此这不是一个缓慢绘制的情况
JScrollPane或JPanel都没有任何其他侦听器。在setVisible()
和paintComponent()
之间还会发生什么?我还可以在哪里确定延迟的来源
编辑: 在试图创造和在我的建议发现我的问题是略有不同,我认为。似乎如果没有其他事情发生,滚动窗格将永远不会被绘制 在我的最小示例(见下文)中,在调整框架大小之前,不会显示该项目。初始显示后,尽管
setVisible()
与完整程序一样立即应用。下面是演示问题的示例代码:
public class VisibilityDelayExample extends JFrame {
private JPanel contentPane;
private JCheckBox chckbxAdvancedView;
private JScrollPane scrollPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
VisibilityDelayExample frame = new VisibilityDelayExample();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public VisibilityDelayExample() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
chckbxAdvancedView = new JCheckBox("Advanced View");
chckbxAdvancedView.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent arg0) {
System.err.println("Property Changed");
if(chckbxAdvancedView.isSelected() != scrollPane.isVisible()){
scrollPane.setVisible(chckbxAdvancedView.isSelected());
scrollPane.invalidate();
scrollPane.repaint();
VisibilityDelayExample.this.invalidate();
VisibilityDelayExample.this.repaint();
}
}
});
contentPane.add(chckbxAdvancedView, BorderLayout.NORTH);
scrollPane = new JScrollPane();
scrollPane.setVisible(false);
contentPane.add(scrollPane, BorderLayout.CENTER);
JPanel panel = new JPanel();
scrollPane.setViewportView(panel);
for(int j = 0; j < 100;j++){
panel.add(new JLabel("Label " + j));
}
}
}
公共类VisibilityDelayExample扩展了JFrame{
私有JPanel内容窗格;
私人JCheckBox chckbxAdvancedView;
私有JScrollPane滚动窗格;
/**
*启动应用程序。
*/
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
VisibilityDelayExample frame=新VisibilityDelayExample();
frame.setVisible(true);
}捕获(例外e){
e、 printStackTrace();
}
}
});
}
/**
*创建框架。
*/
公众可视性延迟示例(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
立根(100100450300);
contentPane=newjpanel();
setboorder(新的EmptyBorder(5,5,5,5));
setLayout(新的BorderLayout(0,0));
setContentPane(contentPane);
chckbxAdvancedView=新的JCheckBox(“高级视图”);
chckbxAdvancedView.addPropertyChangeListener(新的PropertyChangeListener(){
公共作废propertyChange(PropertyChangeEvent arg0){
System.err.println(“财产变更”);
if(chckbxAdvancedView.isSelected()!=scrollPane.isVisible()){
setVisible(chckbxAdvancedView.isSelected());
scrollPane.invalidate();
scrollPane.repaint();
VisibilityDelayExample.this.invalidate();
VisibilityDelayExample.this.repaint();
}
}
});
添加(chckbxAdvancedView,BorderLayout.NORTH);
scrollPane=新的JScrollPane();
scrollPane.setVisible(false);
添加(滚动窗格,BorderLayout.CENTER);
JPanel面板=新的JPanel();
scrollPane.setViewportView(面板);
对于(int j=0;j<100;j++){
面板添加(新的JLabel(“标签”+j));
}
}
}
现在的问题是,在调整大小的过程中发生了什么导致setVisible()
生效,我如何使其立即生效
现在的问题是,在调整大小的过程中发生了什么,这会导致
调整框架大小时,将调用布局管理器,以便将滚动窗格的大小从(0,0)更改为适当的值
我怎样才能使它立即发生
从可见GUI添加/删除组件时,需要使用父容器的revalidate()和repaint()。我知道您没有添加组件,但效果是一样的,因为它没有有效的大小
// scrollPane.revalidate();
// scrollPane.repaint();
// VisibilityDelayExample.this.invalidate();
// VisibilityDelayExample.this.repaint();
contentPane.revalidate();
contentPane.repaint();
,此示例的变体将覆盖scrollpane的getPreferredSize()
方法以提供任意大小。该复选框使用itemstener
切换可见性。注意使用,它“使此窗口的大小符合其子组件的首选大小和布局。”
附录:此更新使滚动窗格最初不可见,并调整框架大小以适应
public class VisibilityDelayExample extends JFrame {
private JCheckBox chckbxAdvancedView;
private JScrollPane scrollPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
VisibilityDelayExample frame = new VisibilityDelayExample();
frame.setVisible(true);
}
});
}
public VisibilityDelayExample() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout(0, 0));
chckbxAdvancedView = new JCheckBox("Advanced View");
chckbxAdvancedView.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
System.out.println(e);
scrollPane.setVisible(chckbxAdvancedView.isSelected());
}
});
add(chckbxAdvancedView, BorderLayout.NORTH);
JPanel panel = new JPanel(new GridLayout(0, 1));
for (int j = 0; j < 100; j++) {
panel.add(new JLabel("Label " + j));
}
scrollPane = new JScrollPane(panel) {
@Override
public Dimension getPreferredSize() {
return new Dimension(450, 300);
}
};
add(scrollPane, BorderLayout.CENTER);
pack();
scrollPane.setVisible(false);
setSize(scrollPane.getPreferredSize());
}
}
公共类VisibilityDelayExample扩展了JFrame{
私人JCheckBox chckbxAdvancedView;
私有JScrollPane滚动窗格;
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
VisibilityDelayExample frame=新VisibilityDelayExample();
frame.setVisible(true);
}
});
}
公众可视性延迟示例(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(新边界布局(0,0));
chckbxAdvancedView=新的JCheckBox(“高级视图”);
chckbxAdvancedView.addItemListener(新的ItemListener(){
@凌驾
公共无效itemStateChanged(ItemEvent e){
系统输出打印ln(e);
setVisible(chckbxAdvancedView.isSelected());
}
});
添加(chckbxAdvancedView,BorderLayout.NORTH);
JPanel面板=新JPanel(新网格布局(0,1));
对于(int j=0;j<100;j++){
面板添加(新的JLabel(“标签”+j));
}
scrollPane=新的JScrollPane(面板){