【问题标题】:Example text in JTextFieldJTextField 中的示例文本
【发布时间】:2011-06-30 00:00:11
【问题描述】:

我正在寻找一种将示例文本放入摇摆 JTextField 并使其变灰的方法。只要在该文本字段中输入任何内容,示例文本就会消失。有些类似于当用户发布带有标题字段的问题时 stackoverflow 所做的事情。

我希望它已经是 JTextField 的扩展实现,以便我可以将它作为简单的替代品放入。来自 swingx 的任何东西都可以。我想如果没有一种简单的方法可以做到这一点,我的选择可能是覆盖 JTextField 的paint方法可能会这样做。

谢谢

【问题讨论】:

    标签: java swing jtextfield


    【解决方案1】:

    不要覆盖,而是在字段中输入一个值并添加一个KeyListener,这将在注册按键时删除该值。也许也让它改变前景。

    您可以将其包装到您自己的自定义 JTextField 类中,该类将在构造函数中采用默认文本。

    【讨论】:

    • 您不能使用按键监听器,因为数据可以通过复制和粘贴等其他方法输入。
    • 我实际上不会在值字段中添加此示例文本,因为使用 getText() 检索该示例文本存在风险
    • @Hover,我首先想到了一个焦点侦听器,但是在 OP 作为示例提到的 SO 标题示例中,文本不会在焦点上消失,而是在您开始输入时消失。如果您确实允许粘贴添加 DocumentListener 可能是更好的解决方案。
    • @DavidM,getText() 方法可以被覆盖以防止示例文本在没有被输入的情况下被返回。
    【解决方案2】:

    您无法使用纯文本字段执行此操作,但您可以将禁用的 JLabel 放在 JTextField 的顶部,并在文本字段获得焦点时将其隐藏。

    【讨论】:

      【解决方案3】:

      如果你可以使用外部库,Jide software 的 Swing 组件有你想要的;它被称为 LabeledTextField (javadoc),它是 JIDE 公共层(开源项目)的一部分——它是免费的。它正在按照 mklhmnn 的建议进行操作。

      【讨论】:

        【解决方案4】:

        如何使用默认文本初始化文本字段并为其提供焦点侦听器,以便在获得焦点时,如果文本 .equals 默认文本,则在 JTextField 上调用 selectAll()。

        【讨论】:

          【解决方案5】:

          这样做:

          1. 使用您喜欢的初始文本定义字符串并设置您的 TextField:

            String initialText = "Enter your initial text here";
            jTextField1.setText(initialText);
            
          2. 将焦点侦听器添加到您的 TextField,如果 TextField 仍然具有初始值,它将选择 TextField 的全部内容。您可以输入的任何内容都将替换整个内容,因为它已被选中。

            jTextField1.addFocusListener(new java.awt.event.FocusAdapter() {
                public void focusGained(java.awt.event.FocusEvent evt) {
                   if (jTextField1.getText().equals(initialText)) {
                      jTextField1.selectAll();
                   }
                }
            });
            

          【讨论】:

          • 这正是气垫船所建议的。我忙着贴,没看他的回答。
          【解决方案6】:

          Text Prompt 类无需使用自定义 JTextField 即可提供所需的功能。

          它允许您指定在文本字段为空时显示的提示。只要您输入文本,提示就会被删除。

          提示符其实是JLabel,所以可以自定义字体、前景等:

          JTextField tf7 = new JTextField(10);
          TextPrompt tp7 = new TextPrompt("First Name", tf7);
          tp7.setForeground( Color.RED );
          

          【讨论】:

            【解决方案7】:
            private JLabel l;
            
            JPromptTextField(String prompt) {
                l = new JLabel(prompt, SwingConstants.CENTER);
                l.setForeground(Color.GRAY);
            }
            
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
            
                if (this.getText().length() == 0) {
                    // Reshape the label if needed, then paint
            
                    final Rectangle mine = this.getBounds();
                    final Rectangle its = l.getBounds(); 
                    boolean resized = (mine.width != its.width) || (mine.height != its.height);
                    boolean moved = (mine.x != its.x) || (mine.y != its.y);
                    if (resized || moved)
                        l.setBounds(mine);
            
                    l.paint(g);
                }
            }
            

            【讨论】:

            • 不要,永远不要,不要在paintComponent中创建任何东西,而不是JComponents,所有对象都必须准备好,只是为了调用Graphics/2D方法,而不是永远不要改变它的属性
            • @mKorbel:为什么?能否详细说明或提供参考?
            • 因为paintComponent被调用1.内部当repaint()需要JComponent时,2.调用repaint()之后,3.从每个鼠标和键盘事件中,4.当Hierarchy或Container(添加JComponents, resize ei) 以编程方式更改或触发事件, 5. 在 Native OS 中应达到延迟(重载此刷新率以冻结绘画),每个 6 或此事件以创建新的 JLabel,也必须使用 OutOfMemoryExceptions 计算,7,同样的问题不从该块加载图像,将其准备为局部变量,仅从数组或变量名中提取
            • @mKorbel:把 JLabel 移到外面了,谢谢指出。
            • @mKorbel:调试表明当前的paintComponent() 开销在大多数调用中是不可察觉的。现在我只在它们发生变化时才调用 setBounds()(因此 EDT 被冻结的时间与 setBounds() 在外面完成的时间相同)。
            猜你喜欢
            • 1970-01-01
            • 2023-03-14
            • 1970-01-01
            • 1970-01-01
            • 2016-06-27
            • 2015-07-10
            • 2015-06-07
            • 2013-04-04
            • 1970-01-01
            相关资源
            最近更新 更多