如何在Java Swing中控制JTextField的宽度?

26

我想在一行上放置多个JTextField,但不希望它们具有相同的宽度。如何控制其宽度并使某些JTextField更宽?我希望它们共同占据总宽度的100%,因此最好使用一些权重来调整宽度。

我尝试使用 .setColumns(),但没有效果。

以下是一个示例,在该示例中,我使用了三行和三个字符串,应该按列显示:

import java.awt.GridLayout;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class RowTest extends JPanel {

    class Row extends JComponent {
        public Row(String str1, String str2, String str3) {
            this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

            JTextField fld1 = new JTextField(str1);
            JTextField fld2 = new JTextField(str2);
            JTextField fld3 = new JTextField(str3);

            fld1.setColumns(5); // makes no sense

            this.add(fld1);
            this.add(fld2);
            this.add(fld3);
        }
    }

    public RowTest() {
    this.setLayout(new GridLayout(5,0));

    this.add(new Row("Short", "A long text that takes up more space",
        "Short again"));
    this.add(new Row("Longer but short", "Another long string", "Short"));
    this.add(new Row("Hello", "The long field again",
        "Some info"));
    }

    public static void main(String[] args) {
        new JFrame() {{ this.getContentPane().add(new RowTest());
                            this.pack(); this.setVisible(true); }};
    }

}

我认为你的Row类不应该使用BoxLayout。Box会将所有元素都推入盒子中。你需要一个将元素推在一起的布局。 - Yishai
@Yishai:是的,我认为问题可能出在那里。但我不知道应该使用哪种LayoutManager……有什么建议吗? - Jonas
@Jonas,你想要什么类型的算法来确定实际宽度?你的运行示例(至少对我来说)具有不同的宽度,因此你显然想以不同的方式进行变化。是什么方式呢? - Yishai
我发现在大多数情况下(约95%),无法击败GridBagLayout。虽然一开始可能有点困惑,但是掌握它绝对是值得的。 - vickirk
@Jonas,请原谅我的愚钝,您的意思是您希望给定行中的每个标签都与其下方的标签在一个平均网格中对齐吗? - Yishai
显示剩余2条评论
4个回答

53
yourTextField = new JTextField("", 20);

如果你像这样启动它,它会将文本字段设置为空并拥有20列


这应该是被接受的答案。在竞争性答案中提到的“SetPreferredSize()”方法对于JTextField对象的代码洞察力来说是显而易见的,并且对于所有实际目的来说都是无用的。 - Tegiri Nenashi
3
对于其他读者:您可以通过调用此 JTextField 方法而不是通过构造函数进行设置:void setColumns(int columns) - kevinarpe

8

试试这个:

textfield.setPreferredSize(new Dimension(int width, int height));

7
所有Swing组件都有一个首选大小。文本组件的首选大小基于组件的文本。因此,通常组件会以其首选大小绘制。
因此,我不认为您代码片段存在问题。每个文本字段应该具有不同的首选大小。另外,随着框架的调整大小,宽度将被调整,因为BoxLayout将尝试将每个组件调整到其最大/最小大小。
如果需要更多帮助,请发布 SSCCE,其中实际演示了您遇到的大小问题。
编辑:
根据最新要求,您可以使用相对布局

我现在已经更新了我的示例。它的工作正常,只是因为我无法控制它的宽度,所以我无法在列中获取 TextFields。 - Jonas
如果您想让组件在列中对齐,则不能使用多个子面板,因为布局管理器彼此独立工作。您需要将所有组件添加到同一个面板中,并使用支持列的布局管理器。您可以尝试使用SpringLayout或GridBagLayout。每种布局管理器的示例都可以在Swing教程中找到:http://java.sun.com/docs/books/tutorial/uiswing/TOC.html。您还可以使用GridLayout,但是您需要将每个文本字段包装在JPanel中,以防止文本字段被调整大小。 - camickr
我没有尝试过,但是如果面板要保持单独的布局管理器,相对布局似乎是合理的解决方案。通常这种情况是通过一个面板具有所有9个组件的一个布局来解决的。 - Yishai
谢谢,RelativeLayout正是我所需要的! - Jonas

0
// 1. create JTextField
yourTextField = new JTextField();
// 2. store default height
int defaultHeight = yourTextField.getSize().getHeight();
// 3. set custom width and default height
yourTextField.setSize(new Dimension(yourWidth, defaultHeight));

谢谢,我可以尝试一下。但是我想使用默认的高度,而不是设置它。 - Jonas
@Xorty:这个不起作用。我认为问题可能是布局管理器忽略了这些值。我更喜欢一种不必手动设置高度的解决方案。 - Jonas
-1,不,你永远不应该使用setSize()方法。布局管理器使用首选大小、最大大小和最小大小(在某些情况下)的信息来确定组件将被绘制的大小。请阅读Swing教程中关于“使用布局管理器”的部分 - http://java.sun.com/docs/books/tutorial/uiswing/TOC.html - camickr
@camickr:最近我一直在构建相当大的Swing应用程序,它完美地运行了 - 经过多个管理器和不同操作系统的多个系统管理员测试 :O - Xorty
在使用布局管理器时,setSize() 方法不起作用。请阅读教程。这正是布局管理器存在的原因。根据布局管理器的规则计算组件的大小和位置。你可以设置大小,但它会被忽略。 - camickr
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接