I know this is done is perspective easily but its there a way to replicate this in vision. I have a large dataset with username and nth roles as columns and will like to be able to maintain the username column visible when I scroll through the role columns.
No, that is Perspective.
Okay, so there have been many requests for this on the forum for a while, and it’s something I knew was possible and have been meaning to get to, just havent had a “good” reason. Well, I guess this was as good of one as any, as I have been meaning to make a solution for this for some time for my own applications.
Anyway, here is how you can do it.
On your table component (can be either a Power Table or a standard Table) create a custom property. I’ve called it hasFrozenColumns
, this is to maintain the state of the table.
Then execute this code, ( I would strongly recomend placing this code in a project library script and sending a component reference to it. So for instance, I have created a project library script with the following import statements and class definition at the top.
from javax.swing import JTable, JScrollPane
from javax.swing.table import DefaultTableModel
from javax.swing.border import MatteBorder
from javax.awt import Color
class CustomTableModel(DefaultTableModel):
def __init__(self,dataset):
self.data = dataset
self.setDataVector([list(row) for row in zip(*[dataset.getColumnAsList(col) for col in xrange(dataset.columnCount)])], dataset.columnNames)
def getColumnClass(self, index):
return self.data.getColumnType(index)
This class primarily provides an otherwise DefaultTableModel, but returns the column type from the dataset. This allows the JTable to take care of selecting an appropriate renderer for the frozen columns.
Next, I have the following function
def toggleFrozenColumns(self,tableComp):
if not tableComp.hasFrozenColumns:
#set up a table model with just the data that we want to be frozen.
freezeDS = system.dataset.toDataSet([tableComp.data.getColumnName(selectedColumn) for selectedColumn in tableComp.selectedColumns],[list(row) for row in zip(*[tableComp.data.getColumnAsList(selectedColumn) for selected column in tableComp.selectedColumns])])
freezeModel = CustomTableModel(freezeDS)
ffreezeTable = JTable(freezeModel)
#define a border to mark the end of frozen columns
newBorder = MatteBorder(0,0,0,3, Color.black)
freezeTable.border = newBorder
freezeTable.tableHeader.border = newBorder
#set the new frozen columns table as the row header of the table
tableComp.setRowHeaderView(freezeTable)
#get the current header size
headerSize = tableComp.rowHeader.preferredSize
#set the width of the header to the witdh of the frozen columns
headerSize.width = freezeTable.columnModel.totalColumnWidth
#set the row header size to the new width
tableComp.rowHeader.preferredSize = headerSize
#set the uper left corner component to the table header
#this displays the column headers above the frozen columns
tableComp.setCorner(JScrollPane.UPPER_LEFT_CORNER, freezeTable.tableHeader)
#remove the frozen columns from the table comps column model
#this prevents the frozen columens from being displayed in the table body
selCols = [col for col in tableComp.table.columnModel.columns if col.modelIndex in tableComp.selecctedColumns]
for col in selCols:
tableComp.table.columnModel.removeColumn(col)
#set the state to indicate that columns have been frozen
tableComp.hasFrozenColumns = True
else:
#add the frozen columns back into the tableComps column model
for col in tableComp.rowHeader.view.columnModel.columns:
tableComp.table.columnModel.addColumn(col)
#loop through the column model and re-align the columns to point at the correct columns in the data. Assumes there are no hidden columns
for i, (col, name) in enumerate(zip([col for col in tabelComp.table.columnModel.columns],[naem for name in tableComp.data.columnNames])):
col.modelIndex = i
col.headerValue = name
#clear the row header (remove frozen columns)
tableComp.setRowHeader(None)
#set the state to indicate that no columns are frozen
tableComp.hasFrozenColumns = False
I have found that the AutoRowHeight option does not lend itself to this, so turn that off. Also, you’ll need to set the Auo-Resize Mode to Off, to keep the columns from resizing. Otherwise, kind of eliminates the purpose of freezing columns.
If you are doing anything particularly special such as using specilaized renderers or giving users the ability to manipulte gridlines, row heights, etc. then you will need to make appropriate changes to this code to insure those things are traslated to the frozen columns. Otherwise you can end up with odd artifacts such as rows being different sizes or showing gridlines when you shouldn’t.
Finally, once that is done. Then you would add code similar to the follwing to a button action preformed script or other appropriate script event.
tableComp = event.source.parent.getComponent('Power Table')
myScriptLibrary.toggleFrozenColumns(tableComp)
Things like this are why I love the Ignition Platform and particularly the flexability of Vision.
Super-simple solution might be to create 2 tables. One with just the one column and one with all the other columns.
Here is a clip of how it looks: