【问题标题】:JButton in single table cell java, not entire column单个表格单元java中的JButton,而不是整个列
【发布时间】:2015-02-04 08:13:00
【问题描述】:

我一直在相当彻底地研究 JTable,并找到了一些出色的资源来解释如何为列设置 CellRenderer 和 CellEditor,但我发现尝试设置单个单元格的 Renderer 和 Editor 不太容易。

我的表格的总体思路是有两列,其中左列显示变量名称,右列允许修改关联变量。大多数单元格我已经能够执行验证,甚至发现了如何以我需要的方式使用 DefaultCellRenderer 和 DefaultCellEditor,但是尝试使用我正在努力解决的自定义渲染器和编辑器来做到这一点。下面我试图说明我设计的表格的外观: (左侧值为变量名,右侧为值)

x 0

y 0

isDestructable [复选框]

图片[可点击的单元格]


图像值应该允许用户单击单元格,然后会弹出一个 JFileChooser,提取响应并在单元格内呈现字符串表示。我编写了许多 sn-ps 代码,但试图将它们链接在一起是我真正迷失的地方。下面我提供了迄今为止与这些功能相关的代码:

/*
Code that creates the table and passes a custom model to it. Code for setting the other
types of renderers and editors I have already got working have been omitted
*/
table = new JTable(new MyDataModel(columnNames, values))
{
    public TableCellRenderer getCellRenderer(int row, int col)
    {
        if(col == 1)
        {
            if(table.getModel().getValueAt(row, 0).equals("image"))
            {
                //This is where I would want to set my renderer I believe
            }
        }

        return super.getCellRenderer(row, col);
    }

    public TableCellEditor getCellEditor(int row, int col)
    {
        if(col == 1)
        {
            if(table.getModel().getValueAt(row, 0).equals("image"))
            {
                //This is where I would want to set my editor I believe
            }
         }

         return super.getCellEditor(row, col);
     }
};

/*
As an inner class, I have created the following editor that should display a JFileChooser
when the user clicks on the cell
*/
private class ButtonTableCellEditor extends AbstractTableCellEditor implements TableCellEditor
{
    private JFrame mainframe;
    private JFileChooser jfc;

    public ButtonTableCellEditor(JFrame frame)
    {
        mainframe = frame;
        jfc = new JFileChooser();
    }

    @Override
    public void addCellEditorListener(CellEditorListener arg0)
    {

    }

    @Override
    public void cancelCellEditing()
    {
        //Hide the JFileChooser here
        super.cancelCellEditing();
    }

    @Override
    public Object getCellEditorValue()
    {
        //Here we need to return the filename that has been returned by the JFileChooser
        return "test";
    }

    @Override
    public boolean isCellEditable(EventObject arg0)
    {
        return true;
    }

    @Override
    public void removeCellEditorListener(CellEditorListener arg0)
    {
        //Not sure that I will actually need to use this at all
    }

    @Override
    public boolean shouldSelectCell(EventObject arg0)
    {
        int returned = jfc.showOpenDialog(mainFrame);

        if(returned == JFileChooser.APPROVE_OPTION)
        {
            System.out.println("File was fine");
        }
        else
        {
            stopCellEditing();
        }

        return true;
    }

    public boolean stopCellEditing()
    {
        return false;
    }

    public Component getTableCellEditorComponent(JTable table, Object value, boolean arg2, int row, int col)
    {
         //This is something I know that is incredibly important based off other examples, but
         //I am unsure what to do in here in my case
         return null;
     }
}

我真正需要帮助的只是(我认为)将 ButtonTableCellEditor 与我需要的单个单元格链接(条件是左侧列是否等于“图像”,以及在我的情况下如何处理 getTableCellEditorComponent()。任何帮助将不胜感激,我已经被困了一段时间了。

另外,这是我的第一个问题(我已经阅读了很多问题,并试图尽可能多地记下),所以如果我提出问题的方式有任何反馈,以便以后的问题可能会更好结构化,这将是最受欢迎的。谢谢大家!

【问题讨论】:

  • 为什么不使用JTable#setDefaultRenderer ...扩展类只是为了像这样自定义渲染器/编辑器......有点烦人......
  • getTableCellEditorComponent不要返回null,返回你在table上显示的组件...
  • 我确实有 table.setDefaultRenderer(JComboBox.class, new ComboRenderer()); 来设置我的 JComboBox 的呈现,但我不确定我是否希望“按钮”呈现为按钮。我认为它显示为 String 就足够了;它主要是我关注的功能(目前)。关于 getTableCellEditorComponent 中的 null 返回,这只是一个占位符,以便编译代码。如果我决定简单地拦截单击单元格的事件,您认为这是必要的吗?这是一种可行的做事方式吗?感谢您的快速回复!
  • 您可以在表格中使用ListSelectionListener,而不是将“动作”放在表格中,这可以改变UI中其他组件的状态
  • 我已经提到了这个问题:Intercept JTable selection change events 并在答案中发现该人正在覆盖 changeSelection。如果我要这样做并检查是否单击了右侧列,并且左侧列包含所需的字符串,那么我可以显示 JFileChooser。然后我可以使用返回的文件名更新单元格。我不明白为什么这现在不起作用,但这是一个好的设计吗?感谢您将我指向ListSelectionListener。

标签: java swing jtable tablecellrenderer tablecelleditor


【解决方案1】:

根据Intercept JTable Selection ChangeEvents 中提供的答案,以及 MadProgrammer 研究 ListSelectionListeners 的极其有用的指导,我已经能够提出以下解决方案:

table = new JTable(new CustomModel(columnNames, values))
{
    /*
    I have omitted the other functions I have overridden here as they are not necessary for the
    solution*/

    @Override
    public void changeSelection(int row, int col, boolean toggle, boolean extend)
    {
        if(col == 1 && table.getModel().getValueAt(row, 0).equals("image"))
        {
            /*
            imageChooser is the name of the JFileChooser I am using, and I am passing the
            main frame of my application to centre the window that appears
            */
            int returned = imageChooser.showOpenDialog(frame);

            if(returned == JFileChooser.APPROVE_OPTION)
                table.getModel().setValueAt(imageChooser.getSelectedFile().getName(), row, col);
        }

        super.changeSelection(row, col, toggle, extend);
    }
}

我不认为这个解决方案具有很强的可扩展性,但就我的程序而言,它运行得非常好。每当单击相应的单元格时,我都能成功打开 JFileChooser,并且单元格内的字符串会更改以表示所选文件的名称。

单元格本质上是一个按钮,而不是一个按钮。根据 UI 外观要求,这可能并不总是合适的,因为它看起来就像一个普通的表格单元格,可能会导致可用性问题。

编辑:

一种更具可扩展性的方法是使用“instanceof”之类的内容确定第 1 列中值的类型,因为这将适用于该类型的所有对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 2011-11-26
    • 2015-08-04
    相关资源
    最近更新 更多