简体   繁体   English

JTreeTable的动态列

[英]Dynamic columns for JTreeTable

I am building a JTreeTable. 我正在建立一个JTreeTable。 I found some starter code and have come pretty far. 我找到了一些入门代码,并且已经走得很远了。 In the end my goal is to be able to have different data at different levels like a hierarchical list. 最后,我的目标是能够在不同层次上拥有不同的数据,例如层次列表。

Currently, I have it working with data at different levels. 目前,我可以处理不同级别的数据。 However, I am running up against a wall when it comes to changing the columns as a next goal. 但是,在改变列作为下一个目标时,我遇到了困难。 From where I currently stand I have 3 more milestones: 从目前的立场来看,我还有3个里程碑:

  • Show different set of columns for different levels 显示不同级别的不同列集
  • Ability to adjust column widths for different levels 能够针对不同级别调整列宽
  • Ensure the JTree part of the table always stays to left 确保表的JTree部分始终保持在左侧

I am getting close to closing out this task but again stuck at the first of these 3. 我即将结束这项任务,但再次陷入了这3个任务中的第一个。

Since creating a JTreeTable is complex, the minimum example leverages several class listed below in the image: 由于创建JTreeTable很复杂,因此最小示例利用了以下图像中列出的几个类:

在此处输入图片说明

I am happy to post the code to any of those classes but I also did not want clog the question with useless code. 我很高兴将代码发布到任何这些类中,但是我也不想用无用的代码阻塞问题。 First let me show the functionality I want. 首先让我展示我想要的功能。

The first image is when the top level is selected and the second image is when the second level is selected. 第一张图像是在选择最高级别时,第二张图像是在选择第二级别时。 Notice how the columns are different. 请注意列之间的不同。 That is what I want to happen in my application. 那就是我想要在应用程序中发生的事情。

Top level selected: 所选的最高级别:

JTreeTable-TopLevelSelected

Second level selected: 选择的第二级:

JTreeTable-SecondLevelSelected

So one way I tried to solve this problem, is when the list selection is changed inside this section of code: 因此,我尝试解决此问题的一种方法是在此部分代码中更改列表选择时:

ListSelectionListener listener = (ListSelectionEvent e) -> {
        TreeTableModelAdapter adapter = (TreeTableModelAdapter) JTreeTable.this.getModel();
        //Need to see why this breaks.
        JTreeTable.this.getTableHeader().setColumnModel(adapter.getColumnModel());
    };
    this.getSelectionModel().addListSelectionListener(listener);

This code is in the initialization of the JTreeTable. 这段代码在JTreeTable的初始化中。 I have tried setting the column model on both the TableHeader and the table as well. 我尝试过在TableHeader和表上同时设置列模型。 Below is what happens then when I select a row: 下面是当我选择一行时发生的情况:

JTreeTable-ColumnModelUpdated

The columns just disappear on me. 专栏就消失在我身上。 The creation of the column model is happening in the TreeTableModelAdapter class with the following method: 使用以下方法在TreeTableModelAdapter类中TreeTableModelAdapter列模型:

public TableColumnModel getColumnModel(){
     DefaultTableColumnModel model  = new DefaultTableColumnModel();
     for(int i=0;i<getColumnCount();i++){
         TableColumn column = new TableColumn();
         column.setIdentifier(getColumnName(i));
         model.addColumn(column);
     }
     return model;
 }

Any direction would be very helpful. 任何方向都将非常有帮助。 Again happy to post any code you think could be helpful to answer the question. 再次高兴地发布您认为可能有助于回答问题的任何代码。 Just put a comment in and I will add it right away. 只需发表评论,我会立即添加。

I will add the milestones as I find them in case this helps others, but for now this question is answered. 我将在找到里程碑时添加这些里程碑,以防对其他人有所帮助,但现在此问题已得到解答。

Milestone 1 里程碑1

I was actually able to solve the first milestone. 实际上,我能够解决第一个里程碑。 The key is to trigger the creation of the columns of the column model, not to create a new column model. 关键是触发创建列模型的列,而不是创建新的列模型。 Below is the code for when the row selection is changed: 下面是更改行选择时的代码:

//Change columns depending on row
ListSelectionListener listener = (ListSelectionEvent e) -> {
    createDefaultColumnsFromModel();
};
this.getSelectionModel().addListSelectionListener(listener);

This code creates the columns based on the row selected in the JTree part of the JTreeTable . 这段代码根据JTreeTableJTree部分中选择的行创建列。 The TreeTableModelAdapter implements the getColumnCount() and getColumnName() methods by also passing the selected row in the JTree to the JTreeTableModel so that the columns and their names are dynamically retrieved based on a particular node in the JTree . TreeTableModelAdapter通过将JTree的选定行也传递给JTreeTableModel来实现getColumnCount()getColumnName()方法,以便根据JTree的特定节点动态检索列及其名称。 The key for this for me was trigger those to be called again to update the JTreeTable . 对我而言,关键是触发再次调用它们以更新JTreeTable

Milestone 2 里程碑2

Adjusting column widths based on the data level proved to be much more difficult than I had originally anticipated. 事实证明,根据数据级别调整列宽比我最初预期的要困难得多。 In order to retain the cells state when the column model changed I had to disconnect the painting of the cells from it. 为了在更改列模型时保留单元格状态,我不得不断开单元格的绘制。 This is a hairy process because this is done inside BasicTableUI and the method that gets the rectangle of the cell is private. 这是一个繁琐的过程,因为这是在BasicTableUI内部完成的,并且获取单元格矩形的方法是私有的。 So I had to subclass it, overload the paint() method and create my own methods that get called inside the paint method. 所以我必须对其进行子类化,重载paint()方法并创建自己的方法,这些方法在paint方法内部被调用。 There was a lot of copy pasting so that I could call normally private methods. 复制粘贴很多,因此我通常可以调用私有方法。 I just renamed them and referenced these methods instead. 我只是重命名了它们,而是引用了这些方法。 The way the ui class was designed did not make it very flexible. ui类的设计方法并不十分灵活。 Below is 2 images where I am selecting different levels and the columns are obviously different widths at different levels. 下面是2张图片,其中我选择了不同的级别,列在不同级别上的宽度明显不同。

顶层

第二级

Milestone 3 里程碑3

I was able to make this work by keeping track of the view in the model. 我能够通过跟踪模型中的视图来完成这项工作。 This seems very dirty to me as the model should separated from the view. 这对我来说似乎很肮脏,因为模型应该与视图分开。 Since the tree column's class is unique, I just returned the right class if that column was the first in the view. 由于树列的类是唯一的,因此如果该列是视图中的第一列,我只是返回了正确的类。

The one problem I have with this technique is that I get unexpected behavior where the value returned is not consistent. 我使用此技术的一个问题是,我得到了意外的行为,其中返回的值不一致。 I attempted to resolve this by overriding JTree.covertValueToText() . 我试图通过重写JTree.covertValueToText()解决此问题。 Since a JTree only expects 1 value and depending on the sequence of columns in the view this value could change. 由于JTree仅期望1值,并且根据视图中列的顺序,此值可能会更改。 So in overriding this method I check the stored index for the JTree column's value. 因此,在覆盖此方法时,我检查了JTree列的值的存储索引。 Again this causes the unexpected behavior. 同样,这会导致意外的行为。 I will update the post if I find the fix. 如果找到修复程序,我将更新帖子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM