【问题标题】:Java JComboBox PlaceholderJava JComboBox 占位符
【发布时间】:2021-03-04 13:25:24
【问题描述】:

美好的一天

目前我正在使用 GUI NetBeans 用 java 开发桌面应用程序,每次我意识到使用它有点适得其反,我在这方面是新的,我的应用程序有一个表单,其中有几个组合框,我想要实现占位符效果。

我想要实现的示例:

*Country
Germany
Brazil
Japan
United States
  

我希望“国家”一词出现在组合框中,但不能选择,从而实现占位符效果,但我不知道该怎么做。

目前我拥有的是组合框索引 0 中的标题“国家”,我根本不喜欢它是一个可选选项,此刻我用 cmbo_country.setForeground(Color.gray); 启动组合框模拟占位符效果。

然后,当组合框的选择将索引 0“国家”更改为任何其他时,将颜色更改为白色并删除索引 0。

cmbo_country.setForeground(Color.WHITE);
cmbo_country.removeItemAt(0);

但这是一个非常糟糕的解决方案。

你能帮我解决这个问题吗?

当我阅读时,我看到了使用负索引 (-1) 的可能性,我可以默认选择它而不在选择中显示它,但我不能这样做,因为我立即得到一个错误。

cmbo_country.insertItemAt("Country", -1);

错误:Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException

我还没有找到任何方法来增加限制以便允许索引 (-1),我不知道这是否是最好的解决方案,但我很感激你能给我的帮助。

提前致谢。

升级

测试类:PromptComboBoxRenderer

正如我所说,我正在使用 netbeans GUI

public class Jframe extends javax.swing.JFrame {

    public Jframe() {
        initComponents();
        
        setTitle("CMBO Prueba");
        setSize(600,400);
        setResizable(false);
        setLocationRelativeTo(null);
        
        jComboBox1.removeAllItems();        
        jComboBox1.addItem("Germany");
        jComboBox1.addItem("Brazil");
        jComboBox1.addItem("Japan");
        jComboBox1.addItem("United States");
        
    }
.
.
.

}

到目前为止,我有我的标准组合框:

[样本][1]

[显示组合框打开][2]

现在应用类PromptComboBoxRenderer

public class Jframe extends javax.swing.JFrame {
    
    public Jframe() {
        initComponents();
        
        setTitle("CMBO Prueba");
        setSize(600,400);
        setResizable(false);
        setLocationRelativeTo(null);
        
        jComboBox1.removeAllItems();        
        jComboBox1.addItem("Germany");
        jComboBox1.addItem("Brazil");
        jComboBox1.addItem("Japan");
        jComboBox1.addItem("United States");
        
        jComboBox1.setSelectedIndex(-1);
        
        jComboBox1.setRenderer(new PromptComboBoxRenderer("Country"));

    }
.
.
.

}

目前看来结果是正确的

[应用经典示例][3]

当打开组合框时出现问题,它完全失去了颜色,类似于函数jComboBox1.setEnabled(false); 也失去了选择的颜色。

[无色选样][4]

我自己尝试通过以下方式应用选择颜色:

public class Jframe extends javax.swing.JFrame {
    
    /**
     * Creates new form Jframe
     */
    public Jframe() {
        initComponents();
        
        setTitle("CMBO Prueba");
        setSize(600,400);
        setResizable(false);
        setLocationRelativeTo(null);
        
        jComboBox1.removeAllItems();        
        jComboBox1.addItem("Germany");
        jComboBox1.addItem("Brazil");
        jComboBox1.addItem("Japan");
        jComboBox1.addItem("United States");
        
        jComboBox1.setSelectedIndex(-1);
        
        jComboBox1.setRenderer(new PromptComboBoxRenderer("Country"));
     
 
        jComboBox1.setRenderer(new DefaultListCellRenderer() {
        public void paintCurrentValueBackground(Graphics g,
                                Rectangle bounds,
                                boolean hasFocus)
     {
         g.setColor( Color.RED );            
         g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
     }
});
    
    }
.
.
.
}

这对我也不起作用,首先占位符效果丢失并且组合框为空白

[样本][5]

虽然现在如果我获得选择,它不会以示例的颜色绘制,在本例中为红色。

[带颜色的选择样本][6]

提前感谢您为我提供的所有帮助,并为新手感到抱歉。

添加

我已经合并了以下函数来更改 L&F,看看我得到了什么:

public void ChangeFormat(){
    
        try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    Logger.getLogger(Jframe.class.getName()).log(Level.SEVERE, null, ex);
                }
    
    }

这里是结果,现在问题不在于选择,而在于带有白色帽子的组合框。

[改变L&F时显示][7]

当你打开它时,一切似乎都是正确的

[样本][8]

虽然我不想为我的项目更改 nimbus 的 L&F 也许这将有助于找到解决方案

感谢您给予我的帮助。

新更新

应用新的东西,尝试修改我放在SynthComboBoxRenderer 的扩展,但这对我不起作用,因为我认为组件不正确,这就是我使用.getRenderer() 得到的:

javax.swing.plaf.synth.SynthComboBoxUI$SynthComboBoxRenderer[ComboBox.listRenderer,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@16514247,flags=8388616,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=Item 4,verticalAlignment=CENTER,verticalTextPosition=CENTER]

我可以在课堂上应用它PromptComboBoxRenderer ???非常感谢大家的帮助

下次更新

我在一个空白项目中测试了 PromptComboBoxRenderer 类的原始代码,并验证它可以正常工作:

package class;

import java.awt.FlowLayout;
import java.awt.Panel;
import javax.swing.JComboBox;
import javax.swing.JFrame;


public class test {
    
    private JComboBox combo;
    
     public static void main(String[] args) {
        new test();
       
    }
     
     public test(){
     
        JFrame v=new JFrame("window);
        combo = new JComboBox();
        combo.addItem("Germany");
        combo.addItem("Brazil");
        combo.addItem("Japan");
        combo.addItem("United States");
        
        v.getContentPane().setLayout(new FlowLayout());  
        v.pack();
        v.getContentPane().add(combo);
        v.setVisible(true);
        v.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        v.add(new Panel());
        v.setSize(600, 400);
        v.setLocationRelativeTo(null);
        
        combo.setSelectedIndex(-1);
        
        combo.setRenderer(new PromptComboBoxRenderer("Country"));

     }
     
    
}

正如我在使用 jframe 创建器和使用 Nimbus UI 时看到的那样,问题发生了。

在这种情况下,我需要能够将其应用到我的项目中,我将完整的代码和有问题的问题留到实现目标的那一刻。


package ventanas;

import clases.PromptComboBoxRenderer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComboBox;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Jframe extends javax.swing.JFrame {

    public Jframe() {
 
        initComponents();
        
        setTitle("CMBO Prueba");
        setSize(600,400);
        setResizable(false);
        setLocationRelativeTo(null);
        
        jComboBox1.removeAllItems();
        
        jComboBox1.addItem("Germany");
    jComboBox1.addItem("Brazil");
    jComboBox1.addItem("Japan");
        jComboBox1.addItem("United States");
        
        jComboBox1.setSelectedIndex(-1);
        
        jComboBox1.setRenderer(new PromptComboBoxRenderer("Country"));
        
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jComboBox1 = new javax.swing.JComboBox<>();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        getContentPane().add(jComboBox1, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 60, 260, 40));

        pack();
    }// </editor-fold>                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Jframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Jframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Jframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Jframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Jframe().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JComboBox<String> jComboBox1;
    // End of variables declaration                   
}

正如我之前所说,这种方式是我设法解决问题的最接近的方式,因为成功应用了所需的效果,唯一的问题是当鼠标经过组合框的不同选项时,选择颜色会丢失by 出于某种原因,我也不能把它还给那个选择颜色。似乎打开组合框时,选择有一个方法jComboBox1.setEnabled(false);

我已经在上面留下了一张照片

我尝试过但没有得到任何结果的另一种方法是:


package ventanas;

import clases.PromptComboBoxRenderer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComboBox;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Jframe extends javax.swing.JFrame {

    public Jframe() {
 
        initComponents();
        
        setTitle("CMBO Prueba");
        setSize(600,400);
        setResizable(false);
        setLocationRelativeTo(null);
        
        jComboBox1.removeAllItems();
        
        jComboBox1.addItem("Germany");
    jComboBox1.addItem("Brazil");
    jComboBox1.addItem("Japan");
        jComboBox1.addItem("United States");
        
        jComboBox1.setSelectedIndex(-1);

        jComboBox1 = new JComboBox<String>()
        {
            @Override
            public Object getSelectedItem()
            {
                Object selected = super.getSelectedItem();

                if (selected == null)
                    selected = "Country";

                return selected;
            }
        };

        
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jComboBox1 = new javax.swing.JComboBox<>();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        getContentPane().add(jComboBox1, new org.netbeans.lib.awtextra.AbsoluteConstraints(150, 60, 260, 40));

        pack();
    }// </editor-fold>                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Jframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Jframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Jframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Jframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Jframe().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JComboBox<String> jComboBox1;
    // End of variables declaration                   
}

希望你能帮我解决这个问题,在此先感谢

【问题讨论】:

  • 一种选择是将“国家/地区”放在 JComboBox 旁边或上方的 JLabel 中。
  • 1) 这不是minimal reproducible example,因为我无法复制/粘贴/编译和测试。 2) 正如我建议的那样,您没有使用默认的 LAF,因此您的代码使用的渲染器不是 BasicComboBoxRenderer。因此,您应该扩展 LAF 使用的默认渲染器,而不是扩展 BasicComboBoxRenderer。您只需使用组合框的getRenderer() 方法来获取默认渲染器。然后你应该能够添加在我的渲染器中找到的基本逻辑。
  • @camickr 再次感谢您的帮助,抱歉没有提供完整的可执行代码,但这是使用 GUI netbeans 自动创建的,我将考虑尽快从代码开始创建 Jframe,我仍然这样做没有解决问题,但上面很有意义,不,我明白如何修改扩展,我已经更新了我正在尝试的问题,希望你能帮助我的朋友,非常感谢你的所有帮助。
  • javax.swing.plaf.synth.SynthComboBoxUI$SynthComboBoxRenderer - 所以 Nimbus 的默认渲染器是一个内部类。因此无法扩展,因为它将使用我们无权访问的 SynthComboBoxUI 类的实例变量。所以这里建议的方法不适用于 Nimbus LAF。
  • @camickr 我明白了,有没有办法用 nimbus L&F 实现这种效果(占位符),或者如果我发布我的自定义组合框的代码,你能给我最后一个建议如何应用它我正在使用 BasicComboBoxUI ???提前致谢。

标签: java swing jcombobox placeholder


【解决方案1】:

我希望“国家”这个词出现在组合框中,但不能选择,从而实现占位符效果

您可以为组合框使用自定义渲染器来实现此效果:

class PromptComboBoxRenderer extends BasicComboBoxRenderer
{
    private String prompt;

    /*
     *  Set the text to display when no item has been selected.
     */
    public PromptComboBoxRenderer(String prompt)
    {
        this.prompt = prompt;
    }

    /*
     *  Custom rendering to display the prompt text when no item is selected
     */
    public Component getListCellRendererComponent(
        JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
    {
        super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

        if (value == null)
            setText( prompt );

        return this;
    }
}

当未选择任何值时,渲染器将显示您的提示。

创建组合框后,组合框中的第一个项目被选中,因此您需要使用以下命令清除选择:

comboBox.setSelectedIndex(-1);

有关完整信息,请参阅Combo Box Prompt

替代方法:

一些外观和感觉,如 Nimbus,不使用 BasicComboBoxRenderer,因此扩展默认渲染器以显示提示文本可能会更加困难。

在这种情况下,您也许可以重写getSelectedItem() 方法以达到相同的效果:

comboBox = new JComboBox<String>( ... )
{
    @Override
    public Object getSelectedItem()
    {
        Object selected = super.getSelectedItem();

        if (selected == null)
            selected = "Country";

        return selected;
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 2015-08-31
    • 2013-06-26
    • 2012-10-13
    • 2017-10-12
    相关资源
    最近更新 更多