【问题标题】:Swing getHeight() value changing from 0 to 16Swing getHeight() 值从 0 变为 16
【发布时间】:2012-06-27 06:35:49
【问题描述】:

我正在尝试在 Swing 中创建一个带有“用户”标签、用户名文本字段和“登录”按钮的框。这是我的代码

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.*;

public class Engine
{
    JFrame frame;
    public void go()
    {
        setUpGui();
        userNameScreen();
    }
    public void setUpGui()
    {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    public void userNameScreen()
    {
        JPanel background = new JPanel();
            frame.getContentPane().add(background);
        JLabel labelUserName = new JLabel("User:");
            background.add(labelUserName);
            System.out.println(labelUserName.getHeight()); // 0
        JTextField textFieldUserName = new JTextField();
            System.out.println(labelUserName.getHeight()); // 16
            textFieldUserName.setPreferredSize(new Dimension(110,labelUserName.getHeight()));
            background.add(textFieldUserName);
        JButton buttonSignIn = new JButton("Sign In");
            background.add(buttonSignIn);
        /*
        background.add(labelUserName);
        background.add(textFieldUserName);
        background.add(buttonSignIn);
        frame.getContentPane().add(background);
        */
        frame.pack();
    }
}

我的驱动程序类只是创建了一个引擎实例,然后运行 ​​go() 方法。
我读到 Swing 组件在添加之前没有高度/宽度属性(因为这是由布局管理器决定它们有多少空间),所以在方法 userNameScreen() 中添加所有组件是有道理的最后*(在此处注释掉)使 textFieldUserName 变量没有高度。
但是,您可以在相同的方法 userNameScreen() 中看到,我已经做到了

System.out.println(labelUserName.getHeight());

两次。第一次是0 第二次是16 不明白为什么第一次注册为0 ' 似乎不会在第一个 println() 和下一个之间改变它的高度。那么为什么第一个中的值是 0,为什么之后几乎立即变为 16?

*我应该注意,当我说添加最后注释掉的所有内容时,它还包括删除/注释掉代码中其他地方执行的所有相同命令。

【问题讨论】:

标签: java swing jlabel jtextfield layout-manager


【解决方案1】:

这是未在 EDT 上创建/修改 Swing 组件的副作用。现在 EDT 正忙于布局,而您正在另一个线程中添加组件。

你的主要方法应该是这样的:

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            new Engine().go();
        }
    });
}

【讨论】:

  • 他还没有创建另一个线程,你说 EDT 正忙于布局。 EDT 应该忙于布局。
  • @vedant1811 主线程(由 JVM 创建)不是 EDT。当您自动创建组件时,EDT 由 Swing/AWT 创建,因此您最终(至少)有两个线程。
  • @walterLann 我现在明白了。那么使用 inovkeLater 会导致一切都在 EDT 上运行?
【解决方案2】:

我不确定为什么会发生这种情况,但可能是因为添加的组件可能在后台线程上,并且可能在调用下一个语句之前不会更新,并且它会在几毫秒后更新并在您调用时出现第二次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 2017-11-23
    相关资源
    最近更新 更多