动态创建 jCheckBox 并添加到 jScrollPane

Posted

技术标签:

【中文标题】动态创建 jCheckBox 并添加到 jScrollPane【英文标题】:Dynamically create jCheckBox and add to a jScrollPane 【发布时间】:2012-05-01 08:36:38 【问题描述】:

编辑:使用下面介绍的解决方案,我已将代码更改为在 JScrollPane 中包含 JPanel。使用 JButton 我将 JCheckBoxes 添加到 JScrollPane 内的 JPanel。这是解决了一个问题,因为 JScrollPane 只能使用一个 JComponent。其余问题已解决,为 JScrollPane 内的 JPanel 设置了一个网格布局。为了后代,我将最初的问题保留在这里:

原始问题:我正在尝试动态创建 JCheckBox 并将它们添加到 JScrollPane,但可惜我收效甚微。我已将其简化为单一的概念验证实现。

我在 JFrame 中有一个 JScrollPaneon 和一个 JPanel。同样在 JPanel 上,我添加了一个按钮,该按钮应该在单击时将 JCheckBox 添加到 JScrollPane。应该足够简单。按钮内部代码如下:

 private void addCheckBoxActionPerformed(java.awt.event.ActionEvent evt) 

    JCheckBox cb = new JCheckBox("New CheckBox");        

    jScrollPaneCheckBoxes.add(cb);
    jScrollPaneCheckBoxes.revalidate();
 

代码运行似乎没有错误。我没有例外,使用调试器表明 JCheckBox 实际上已添加到 JScrollPane 中。不幸的是,应用程序中没有显示任何内容。我需要关于在哪里寻找问题的方向。

这是一段您可以直接运行的快速代码。不幸的是,我使用 Netbeans 和它的 GUI 设计器将它放在一起,因此它比它需要的要长一点,尤其是生成的代码。关注jButton1ActionPerformed方法,上面的代码就是从那里得到的。

编辑:此代码现在可以满足我的需要。 :-)

package dynamiccheckboxsscce;

import javax.swing.JCheckBox;

public class Main extends javax.swing.JFrame 

    /**
     * Creates new form Main
     */
    public Main() 
        initComponents();
    

    @SuppressWarnings("unchecked")
    private void initComponents() 

        jScrollPane1 = new javax.swing.JScrollPane();
        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane1.setPreferredSize(new java.awt.Dimension(250, 250));

        jPanel1.setPreferredSize(new java.awt.Dimension(300, 250));
        jPanel1.setLayout(new java.awt.GridLayout(0, 2, 10, 10));
        jScrollPane1.setViewportView(jPanel1);

        jButton1.setText("Add Checkbox");
        jButton1.addActionListener(new java.awt.event.ActionListener() 
            public void actionPerformed(java.awt.event.ActionEvent evt) 
                jButton1ActionPerformed(evt);
            
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 309, Short.MAX_VALUE)
                .addContainerGap())
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(0, 0, Short.MAX_VALUE)
                .addComponent(jButton1)
                .addGap(112, 112, 112)))));
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE)
                .addComponent(jButton1)
                .addContainerGap()));

        pack();
    

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) 
        JCheckBox cb = new JCheckBox("New CheckBox");

        jPanel1.add(cb);
        jPanel1.revalidate();
        jPanel1.repaint();
    

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) 
        /*
         * Set the Nimbus look and feel
         */
        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(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
         catch (InstantiationException ex) 
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
         catch (IllegalAccessException ex) 
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
         catch (javax.swing.UnsupportedLookAndFeelException ex) 
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() 
            public void run() 
                new Main().setVisible(true);
            
        );
    
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;

提前致谢。

【问题讨论】:

不发布SSCCE,您可以等待与下面相同的答案 sscce 传入 - 请稍等。 This answer of mine 包含我动态添加项目的滚动窗格 我已经将上面的代码更新为一个工作示例,它结合了 mKorbel 提出的观点和他提供的代码。上面的代码只是使用了稍微不同的方法和不同的布局管理器,但结果或多或少是相同的。 【参考方案1】:

如果不发布SSCCE,您必须接受JScrollPane 被指定为仅嵌套一个JComponent

如果您想在JScrollPane 中添加更多JComponent,请将JPanel 放在那里,然后将新的JComponent 添加到JPanel 而不是JScrollPane

查看how dynamically add / remove JComponents

编辑

您必须为 JPanel 设置适当的 LayoutManager

您应该将 JPanel 添加到 JScrollPane

例如(不使用内置设计器,即使是安全的时间...,也需要对使用过的 SwingFramework 和 Swing 有最好的了解,我对普通的 Swing 很满意)

代码

import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class AddJCheckBoxToJScrollPane 

    private static final long serialVersionUID = 1L;
    private JFrame frame = new JFrame();
    private JButton jButton1;
    private JPanel jPanel1;
    private JScrollPane jScrollPane1;

    public AddJCheckBoxToJScrollPane() 
        jPanel1 = new JPanel();
        jPanel1.setLayout(new GridLayout(0, 2, 10, 10));
        jScrollPane1 = new JScrollPane(jPanel1);
        jButton1 = new JButton("Add Checkbox");
        jButton1.addActionListener(new java.awt.event.ActionListener() 

            public void actionPerformed(java.awt.event.ActionEvent evt) 
                JCheckBox cb = new JCheckBox("New CheckBox");
                jPanel1.add(cb);
                jPanel1.revalidate();
                jPanel1.repaint();
            
        );
        frame.add(jScrollPane1);
        frame.add(jButton1, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        //frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    

    public static void main(String args[]) 

        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) 
         catch (InstantiationException ex) 
         catch (IllegalAccessException ex) 
         catch (javax.swing.UnsupportedLookAndFeelException ex) 
        
        java.awt.EventQueue.invokeLater(new Runnable() 

            public void run() 
                new AddJCheckBoxToJScrollPane();
            
        );
    

【讨论】:

sscce 传入 - 请稍等。 感谢您的解决方案。我从这次经历中学到了两件事。 1. 显示的内容与布局有关,而不是与组件有关 2. 我对布局了解不够。 :-)【参考方案2】:

你应该调用 repaint() 而不是 revalidate()。

见Revalidate vs. Repaint

【讨论】:

用重绘替换了重新验证 - 没有区别。甚至两者都加了。谢谢你的建议。从您提供的链接中引用:“一旦添加新组件或删除旧组件,就会在容器上调用 revalidate。” 嗯。我的想法是,孩子们的重绘不会捕捉到添加的对象,但顶层面板上的重绘会。如果这不是问题,您需要向我们提供更多信息。 @Charles 请just try once,顺便说一句,我建议删除这个答案,因为它太敏感了 如果有的话,它会阻止更多人发布相同的内容。我不介意它是否被否决,因为这是错误的答案。 @mKorbel - 语气在网上非常困难,所以我要给你怀疑的好处,如果我的问题让你烦恼,你可以跳过它 -我不想激怒你或浪费你的时间;我只是想尝试解决我的问题而没有任何麻烦。您提供的链接包括这种语言,我无法将其识别为英语:“避免进一步讨论任何必需/非必需的方法......注意:用于添加/删除 JComponents(仅在一行/列中的简单结构并且在屏幕上具有相同的大小)就足够了,只需操作 JFrame.pack()"

以上是关于动态创建 jCheckBox 并添加到 jScrollPane的主要内容,如果未能解决你的问题,请参考以下文章

如何通过SQL将一列JCheckBox添加到JTable? [重复]

动态创建矢量并在 C++ 中添加到地图

如何检查 JCheckBox 是不是被选中?

如何将事件侦听器添加到动态创建的复选框并检查是不是选中了复选框。 JavaScript

将表字段转换为jCheckBox [复制]

JCheckbox 更改侦听器收到鼠标悬停事件的通知