当前位置: 首页 > 知识库问答 >
问题:

在JavaSwing中,当我从组合框中取出标签时,如何让一个可编辑JComboBox的Table CellEditor保持其值?

丁豪
2023-03-14

我正在使用NetBeans IDE为我的一个项目中遇到的问题创建一个简单的测试(所以请原谅NetBeans的一些不必要的膨胀,但这其实并不太糟糕)。

我有一个JTable,它有一个单元格编辑器和一个可编辑的JComboBox(因此用户可以从列表中选择一个项目,或者在组合框中键入新文本)。

当用户退出组合框时,组合框的单元格编辑器将丢失键入其中的文本。

如何调整此代码,以便当我键入后离开组合框时,它将保留文本?

package testtablecellfocuslostissue;

import java.awt.Color;
import java.awt.Component;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

/**
 *
 * @author admin
 */
public class Main extends javax.swing.JFrame {

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

        table1.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

        DefaultTableModel model = (DefaultTableModel) table1.getModel();

        String[] values = new String[] { "Maintained By", "Endpoint" };

        JComboBox comboBox = new JComboBox(values);

        TableColumn col = table1.getColumnModel().getColumn(0);
        col.setCellEditor(new MyComboBoxEditor(comboBox));
        col.setCellRenderer(new MyComboBoxRenderer(values));
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        table1 = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        table1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null}
            },
            new String [] {
                "Key", "Value"
            }
        ));
        jScrollPane1.setViewportView(table1);

        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()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 167, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        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(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);
        }
        //</editor-fold>

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

    class MyComboBoxRenderer extends JComboBox implements TableCellRenderer {
        public MyComboBoxRenderer(String[] items) {
        super(items);
    }

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        if (isSelected) {
          //setForeground(table.getSelectionForeground());
          setForeground(Color.BLACK);
          super.setBackground(table.getSelectionBackground());
        } else {
          setForeground(table.getForeground());
          setBackground(table.getBackground());
        }
        setSelectedItem(value);

        return this;
    }
}

class MyComboBoxEditor extends DefaultCellEditor {
    private JComboBox comboBox;
    public MyComboBoxEditor(JComboBox comboBox) {
        super(comboBox);
        comboBox.setEditable(true);
    }
}

    // Variables declaration - do not modify                     
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable table1;
    // End of variables declaration                   
}

共有1个答案

谭畅
2023-03-14

这似乎成功了,但哇,这个解决方案真是一场噩梦:

package testtablecellfocuslostissue;

import java.util.ArrayList;
import javax.swing.AbstractCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;

/**
 *
 * @author admin
 */
public class Main extends javax.swing.JFrame {

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

        // Initial choices in the list
        ArrayList<String> values = new ArrayList();
        values.add("Male");
        values.add("Female"); 

        table1.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

        TableColumn col = table1.getColumnModel().getColumn(0);
        col.setCellEditor(new MyComboBoxEditor(new ArrayList(values)));

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        table1 = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        table1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null}
            },
            new String [] {
                "Key", "Value"
            }
        ));
        jScrollPane1.setViewportView(table1);

        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()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 167, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
        setLocationRelativeTo(null);
    }// </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(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);
        }
        //</editor-fold>

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

public class MyComboBoxEditor extends AbstractCellEditor implements TableCellEditor {
   private JComboBox comboBox;
   private ArrayList<String> comboBoxChoices;

   public MyComboBoxEditor(ArrayList<String> choices) {
      this.comboBoxChoices = choices;
   }

   @Override
   public JComponent getTableCellEditorComponent(JTable table, Object item, boolean isSelected, int row, int column) {
      comboBox = new JComboBox(comboBoxChoices.toArray());
      comboBox.setEditable(true);

      if (item != null) {
         comboBox.setSelectedItem(item);
      }

      return comboBox;
   }

   @Override
   public Object getCellEditorValue() {
      return comboBox.getEditor().getItem();
   }

   @Override
    public boolean stopCellEditing()
    {
        DefaultComboBoxModel comboModel = (DefaultComboBoxModel) comboBox.getModel();
        Object editingValue = getCellEditorValue();

        //  Needed because your TableModel is empty
        if (editingValue == null){
            return super.stopCellEditing();
        }

        // Get the selected index
        int selectedIndex = comboModel.getIndexOf(editingValue);
        if (! (selectedIndex == -1)){
            return super.stopCellEditing();
        }

        comboBoxChoices.add((String)editingValue);
        return super.stopCellEditing();

    }
}

    // Variables declaration - do not modify                     
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable table1;
    // End of variables declaration                   
}
 类似资料:
  • 我正在使用金属 L 但当我这样做时,cb。setEditable(false),框内出现一个附加边框(在图片“下拉”中变为红色,您可以在名为“固定”的图片中看到原始颜色)。虽然我尝试设置边界,也尝试使用自己的CellRenderer,但边界仍然会被绘制。在我看来,不需要的边界不是来自细胞渲染器。当我试图从cb本身操纵边框时(请参见注释/),它只添加/删除了一个额外的外部边框。编辑部分似乎也不对我负

  • 我正在尝试使用一个可编辑的组合框。因为我想添加一个用于按回车键的监听器。我尝试了下面的选项,但都不起作用。:( < code>cmb_year是组合框对象。

  • 视图(在本例中,ViewPager)有自己的保存和恢复状态的实现,我依靠它在设备旋转后将ViewPager保持在同一页面上。 当ViewPager在活动中时,它工作得非常好。我滚动到一个页面,旋转设备,它仍然在那个页面上。在SaveInstanceState中不需要任何代码。 我已经把那个活动转化成了一个片段。现在,ViewPager无法保持其状态!如果我滚动到一个页面并旋转设备,它会返回到第1页

  • 是的,有关于这个问题的早期线索和指南。他们告诉我答案应该是或。但是做任何这些都会给我一个。 我想做的是每次将某样东西写入组合框时清除所选内容。这是因为当你在组合框中写了一些东西,而在组合框弹出窗口中仍然选择了其他东西时,它会导致问题和看起来很奇怪。 这是一个SSCCE:

  • 这里的想法是:假设我有一个扩展的类,它具有类似于字段的内容。在事件中,我想清除并重新添加行,其中一个特定列是组合框;组合框中的项是“我的列表”中中的中的项。因此,我迭代添加行,并迭代每个添加组合框项。 没有事件侦听器。当单击一个单独的按钮时,只要我可以在每个组合框上就可以确定需要发生什么。 我已经花了两个半小时把我的GUI变成了通心粉代码,在这里我几乎扩展了所有内容,并且几乎所有内容都有最大程度的

  • 当我点击ListFragment中的EditText(请参见“您的答案…”字段是下面的屏幕上限)时,它不会保持焦点,因此无法使用。文本光标一出现在EditText字段上,它就会迅速消失,EditText域就会失去焦点。 我发现了一些相关的堆栈帖子,并怀疑有什么东西可能从EditText中窃取了焦点。请参阅此处的相关帖子。我也读过关于强迫聚焦的帖子,但没有什么意义。 我可以以编程方式构建视图,但是使