【问题标题】:Jtextfield begins in a smaller stateJtextfield 以较小的状态开始
【发布时间】:2014-09-14 21:33:54
【问题描述】:

我正在制作一个示例应用程序,只是为了学习基础知识。我有一个问题,我有 3 个JTextFields,当我启动应用程序时,底部的 2 个JTextFields 没有出现,但第一个有 focus 的却出现了。但只有我打算的最终大小的一小部分。但是,当我单击它们或开始输入字段时,它们会扩展为我最初想要的大小。

尽管它们在启动时显示不正确,但它们都位于正确的位置。有什么想法吗?

package password;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class password implements  ActionListener{
    static int width = 220, height = 250;

    JPanel textPanel, panelForTextFields, completionPanel;
    JLabel serviceLabel, usernameLabel, passwordLabel;
    JTextField serviceField, usernameField, passwordField;
    JButton Submit;

    public JPanel setupPane (){

        // We create a bottom JPanel to place everything on.
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(null);

        textPanel = new JPanel();
        textPanel.setLayout(null);
        textPanel.setLocation(0, 0);
        textPanel.setSize(width, height);
        mainPanel.add(textPanel);

        panelForTextFields = new JPanel();
        panelForTextFields.setLayout(null);
        panelForTextFields.setLocation(0, 0);
        panelForTextFields.setSize(width, height);
        mainPanel.add(panelForTextFields);

        //---------------------------------------------------------------------------------------------------------------------------------
        //                                              Service text field and label
        //---------------------------------------------------------------------------------------------------------------------------------

        serviceLabel = new JLabel("Service:");
        serviceLabel.setLocation(60, 0);
        serviceLabel.setSize(80, 40);
        textPanel.add(serviceLabel);

        serviceField = new JTextField();
        serviceField.setLocation(60, 30);
        serviceField.setSize(100, 20);
        panelForTextFields.add(serviceField);

        //---------------------------------------------------------------------------------------------------------------------------------
        //                                              Username text field and label
        //---------------------------------------------------------------------------------------------------------------------------------

        usernameLabel = new JLabel("Username:");
        usernameLabel.setLocation(60, 45);
        usernameLabel.setSize(80, 40);
        textPanel.add(usernameLabel);

        usernameField = new JTextField();
        usernameField.setLocation(60, 75);
        usernameField.setSize(100, 20);
        panelForTextFields.add(usernameField);

        //---------------------------------------------------------------------------------------------------------------------------------
        //                                              Password text field and label
        //---------------------------------------------------------------------------------------------------------------------------------

        passwordLabel = new JLabel("Password:");
        passwordLabel.setLocation(60, 90);
        passwordLabel.setSize(80, 40);
        textPanel.add(passwordLabel);

        passwordField = new JTextField();
        passwordField.setLocation(60, 120);
        passwordField.setSize(100, 20);
        panelForTextFields.add(passwordField);

        //---------------------------------------------------------------------------------------------------------------------------------
        //                                                      Submit button
        //---------------------------------------------------------------------------------------------------------------------------------        

        Submit = new JButton("Submit");
        Submit.setLocation(60, 165);
        Submit.setSize(100, 20);
        panelForTextFields.add(Submit);
        Submit.addActionListener(this);

        return mainPanel;
    }

    public void actionPerformed(ActionEvent e) {

        Object source = e.getSource();
        if(source == Submit) {
            JOptionPane.showMessageDialog(null," information added.","Success!", JOptionPane.PLAIN_MESSAGE);
        }
    }

    private static void password() {    
        JFrame mainF = new JFrame("Password Application");

        password demo = new password();
        mainF.setContentPane(demo.setupPane());
        mainF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainF.setSize(width, height);
        mainF.setResizable(false);
        mainF.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                password();
            }
        });
    }
}

【问题讨论】:

  • 罪魁祸首是这里的AbsoluteLayout,其他没有为有问题的JTextField 提供列。做JTextField tField = new JTextField(10),这足以设置它的大小:-)
  • 要获得布局方面的帮助,请提供 ASCII 艺术或简单的图形,说明 GUI 应如何以默认大小显示,并且(如果可调整大小)具有额外的宽度/高度。

标签: java swing jtextfield layout-manager null-layout-manager


【解决方案1】:

将您的示例视为如何不构建布局的课程。

绝对定位无法应对各种挑战 Java GUI 应用程序面临:

  • 字体更改
  • (人类)语言切换
  • 不同的屏幕分辨率
  • DPI 的变化
  • 各种操作系统及其布局标准

因此,程序员需要使用布局管理器。这些年来, 为 Swing 创建了多个布局管理器。我推荐 以下三个(按特定顺序):

  1. MigLayout
  2. 组布局
  3. 表单布局

MigLayoutFormLayout 是第三方管理员。因此,我们需要 下载并将他们的库添加到我们的项目中。这三位经理最 灵活而强大的所有经理。

我用这三个经理创建了您的简单布局。

MigLayout

MigLayout 有一套丰富的工具来构建所需的布局。

package com.zetcode;

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;


public class MigLayoutPassword extends JFrame {

    public MigLayoutPassword() {

        initUI();

        setTitle("Password application");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    private void initUI() {

        JPanel pnl = new JPanel(new MigLayout("wrap 2, ins dialog", 
                "[right][grow]"));

        JLabel serviceLbl = new JLabel("Service:");
        JLabel userNameLbl = new JLabel("User name:");
        JLabel passwordLbl = new JLabel("Password:");

        JTextField field1 = new JTextField(10);
        JTextField field2 = new JTextField(10);
        JPasswordField field3 = new JPasswordField(10);

        pnl.add(serviceLbl);
        pnl.add(field1, "growx");

        pnl.add(userNameLbl);
        pnl.add(field2, "growx");

        pnl.add(passwordLbl);
        pnl.add(field3, "growx");

        add(pnl);

        pack();

    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MigLayoutPassword ex = new MigLayoutPassword();
                ex.setVisible(true);
            }
        });
    }
}

请注意,没有定位,也没有明确的组件大小设置。这 由经理处理。只有几行进行布局。 对布局的更改可以轻松快速地完成。

JPanel pnl = new JPanel(new MigLayout("wrap 2, ins dialog", 
        "[right][grow]"));

注意dialog 关键字。这个关键字被翻译成标准空间 当前平台的边框。

组布局

MigLayout 相比,GroupLayout 只有几个工具可以影响 布局。然而,它的威力惊人。在这个管理器中,我们定义 分别为每个维度使用组件组进行布局。

package com.zetcode;

import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.Alignment.BASELINE;
import static javax.swing.GroupLayout.Alignment.TRAILING;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;


public class GroupLayoutPassword extends JFrame {

    public GroupLayoutPassword() {

        initUI();

        setTitle("Password application");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    private void initUI() {

        Container pane = getContentPane();
        GroupLayout gl = new GroupLayout(pane);
        pane.setLayout(gl);

        JLabel serviceLbl = new JLabel("Service:");
        JLabel userNameLbl = new JLabel("User name:");
        JLabel passwordLbl = new JLabel("Password:");

        JTextField field1 = new JTextField(10);
        JTextField field2 = new JTextField(10);
        JTextField field3 = new JTextField(10);

        gl.setAutoCreateGaps(true);
        gl.setAutoCreateContainerGaps(true);   

        gl.setHorizontalGroup(gl.createSequentialGroup()
                .addGroup(gl.createParallelGroup(TRAILING)
                        .addComponent(serviceLbl)
                        .addComponent(userNameLbl)
                        .addComponent(passwordLbl))
                .addGroup(gl.createParallelGroup()
                        .addComponent(field1)
                        .addComponent(field2)
                        .addComponent(field3))
        );        

        gl.setVerticalGroup(gl.createSequentialGroup()
                .addGroup(gl.createParallelGroup(BASELINE)
                        .addComponent(serviceLbl)
                        .addComponent(field1))
                .addGroup(gl.createParallelGroup(BASELINE)
                        .addComponent(userNameLbl)
                        .addComponent(field2))
                .addGroup(gl.createParallelGroup(BASELINE)
                        .addComponent(passwordLbl)
                        .addComponent(field3))
        );

        pack();
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                GroupLayoutPassword ex = new GroupLayoutPassword();
                ex.setVisible(true);
            }
        });
    }
}

表单布局

为了创建这个简单的布局,我使用了高级DefaultFormBuilder。 对于更复杂的布局,我们需要不使用这个(或类似的) 建设者。

package com.zetcode;

import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.FormLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;


public class FormLayoutPassword extends JFrame {

    public FormLayoutPassword() {

        initUI();

        setTitle("Password application");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    private void initUI() {

        FormLayout fl = new FormLayout(
            "r:p, $rg, p:g", // columns
            "");  // rows

        DefaultFormBuilder builder = new DefaultFormBuilder(fl);
        builder.border(Borders.DIALOG); 

        JTextField field1 = new JTextField(10);
        JTextField field2 = new JTextField(10);
        JPasswordField field3 = new JPasswordField(10);        

        builder.append("&Service: ", field1);
        builder.nextLine();

        builder.append("&User name: ", field2);
        builder.nextLine();

        builder.append("&Password: ", field3);
        builder.nextLine();

        JPanel pnl = builder.getPanel();
        setContentPane(pnl);

        pack();

    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                FormLayoutPassword ex = new FormLayoutPassword();
                ex.setVisible(true);
            }
        });
    }
}

同样,我们没有看到组件或间隙的明确定位或设置大小。

    FormLayout fl = new FormLayout(
        "r:p, $rg, p:g", // columns
        "");  // rows

三位经理都使用了相关差距的概念,此处指定 作为$rg。一个相关的差距是 对刚性像素间隙大小的抽象。 (以像素为单位的刚性间隙是 取决于硬件和操作系统。)

【讨论】:

    【解决方案2】:
    1. 不要使用空布局!!!!不要使用 setSize() 或 setLocation()。布局管理器的工作是确定组件的大小/位置。 Swing 旨在与布局管理器一起使用。

    2. 在创建 JTextField 时,使用 JTextField textField = new JTextField(10) 之类的东西来指定文本字段可以基于其首选大小的字符数。现在布局管理器可以完成它的工作了。

    由于您希望垂直放置组件,因此您可以使用BoxLayoutGridBagLayout。阅读Using Layout Managers 上的 Swing 教程,了解更多信息和工作示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-25
      • 2013-01-01
      • 1970-01-01
      • 2014-12-21
      • 2020-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多