[IGN-6531]The check-mark box is not visible (it is transparent) in ignition version 8.1.17

Hello all.

We are using ignition version 8.1.17 and we are facing the issue of the check box in the power tables. Meaning that they are transparent but if you click on the raw to select it present itself but still very slight.

NOTE:If the background is white it is ok, soon the background is black it “disappears”.

Can you please help me with this topic? I also posted a picture for you to see how it looks.

This is probably a background color issue. if so, change the checkmark box’s background color in the component property editor. If you are changing the parent’s background color dynamically, with themes or something of that nature, bind the checkbox’s background color, so that it changes appropriately

The check-mark box is built in the code itself. When we build data and headers we push “False” also in there knowing for the power table that the check-mark should be set.

Where to find this specific property only for the check mark to modify specially color, this i cannot find.

That makes sense. I forgot about the Boolean column that can be added to the power tables

1 Like

Perhaps one approach to this problem could be to modify the column color using the the configureCell extension function to set the columns color to some variation of grey

if colName == "Selected":
       return {'background': (211,211,211)}

This could probably even be qualified with the power table’s background color, so that it only occurs if black is selected:

if self.background == (0,0,0)
	if colName == "Selected":
		return {'background': (211,211,211)}

or, perhaps the problem is actually the foreground color. Another approach could be to change the foreground color of the boolean column, so that it contrasts better with the black using the same method mentioned above:

if colName == "Selected":
	return {'foreground': (255,255,255)}

Still digging around under the hood for a better solution. Here is what I’ve found so far:

import java.awt.Color
import javax.swing.border.Border
table = event.source.table
editor = table.getDefaultEditor(java.lang.Boolean)
renderer = table.getDefaultRenderer(java.lang.Boolean)
renderer.setBackground(java.awt.Color(255,255,255))
renderer.setForeground(java.awt.Color(255, 255, 255))
table.setDefaultRenderer(java.lang.Boolean, renderer)
#renderer.border = javax.swing.plaf.synth.SynthCheckBoxUI.paintBorder()
renderer.repaint( )

print "Table = ", 
print table
print ""
print "Editor = ", 
print editor
print ""
print "Renderer = ", 
print renderer
print ""
print "Border = ",
print renderer.border

This code produces the following information, but has absolutely no effect on the checkbox:

Table =  com.inductiveautomation.factorypmi.application.components.VisionAdvancedTable$3[Power Table->view,0,0,610x273,alignmentX=0.0,alignmentY=0.0,border=,flags=251658600,maximumSize=,minimumSize=,preferredSize=,autoCreateColumnsFromModel=true,autoResizeMode=AUTO_RESIZE_SUBSEQUENT_COLUMNS,cellSelectionEnabled=false,editingColumn=-1,editingRow=-1,gridColor=javax.swing.plaf.ColorUIResource[r=250,g=250,b=251],preferredViewportSize=java.awt.Dimension[width=450,height=400],rowHeight=16,rowMargin=1,rowSelectionAllowed=true,selectionBackground=javax.swing.plaf.ColorUIResource[r=71,g=169,b=230],selectionForeground=javax.swing.plaf.ColorUIResource[r=255,g=255,b=255],showHorizontalLines=true,showVerticalLines=true]

Editor =  com.jidesoft.grid.BooleanCheckBoxCellEditor@3c4d8d28

Renderer =  javax.swing.table.DefaultTableCellRenderer[Table.cellRenderer,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@291abc5b,flags=25165832,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=,verticalAlignment=CENTER,verticalTextPosition=CENTER]

Border =  javax.swing.plaf.synth.SynthBorder@291abc5b

You are passing java.lang.Boolean where you should be passing either True or False. java.lang.Boolean is the class for booleans, not a boolean itself.

@pturmel:
That particular function needs a specific class specified. It won’t allow java.lang.Boolean.TRUE to be passed

I finally figured this out. Add this code to your configureCell extension function, and it will give you exactly what you were originally looking for:

	if colName == "Selected":
		if rowIndex != self.selectedRow:
			import java.awt.BorderLayout
			import javax.swing.JCheckBox
			table = self.table
			editorComponent = table.getCellEditor(rowIndex, colIndex).getTableCellEditorComponent(table, value, selected, rowIndex, colIndex)
			editorComponent.setOpaque(0)
			editorComponent.setBackground(java.awt.Color(255, 255, 255))
			editorComponent.setBorderPainted(0)
			return{'renderer': editorComponent}

The preceding code produces this result:
ResultCapture

Edit: added column name qualifier and moved the self.selected qualifier to eliminate some errors that were showing up in the console

1 Like

Even though this code works, I would consider it a “get by.”

I feel that this really is a bug that needs to be addressed on IA’s side.

1 Like

Hello justinedwards.jle…

Much appreciate the help and time you put into this. I will try it today and see how this plays out.

I will let you know as soon as possible.

Best regards,
Sebastijan

1 Like

Hey… just letting you know that it worked perfectly. Much appreciated.

1 Like

I would agree. The situation is somewhat complicated, though; if you set opaque to false, then any customization to the background color in configureCell won't be applied.

For a fun bonus, though, you can greatly simplify your script. The docstring doesn't hint at this, but any bean property can be set on the rendering component automatically, so you can just return a dictionary like this when appropriate:

return {'background': 'white', 'opaque': False, 'borderPainted': False}
1 Like

Perhaps an alternate approach would be to just toy around with the opacity of the customizers until a workable and uniform look and feel is achieved.
Example:

def configureCell(self, value, textValue, selected, rowIndex, colIndex, colName, rowView, colView):
	import java.awt.Color	
	customizations = {'background':java.awt.Color(255, 255, 255, 60)}
	if rowView % 2 != 0:
		customizations = {'background': java.awt.Color(150, 150, 150, 255)}
	return customizations

The preceding code produces the following result:
VariableOpacityResultCapture

I played around with this a little bit more, and I found something interesting that is possibly of note. I developed this code to make the power table completely transparent believing that if I blew all of the background colors out, then perhaps I could build them back in in a way that didn’t effect the JCheckboxes. So far, I found that the Boolean column behaves differently than the other classes:

def configureCell(self, value, textValue, selected, rowIndex, colIndex, colName, rowView, colView):
	import java.awt.BorderLayout
	layout = self.layout.getViewport()
	layout.setOpaque(0)
	self.table.setOpaque(0)
	self.table.getDefaultRenderer(self.table.getColumnClass(colIndex)).setOpaque(0)
	self.background = java.awt.Color(255, 255, 255 ,0)
	customizations = {}
	customizations = {'background': java.awt.Color(0, 0, 0 ,0)}
	return customizations

The preceding code produces this result:

Now, when I restore the original customizations, all of the other columns respond in the expected way, but the boolean column remains transparent while only the JCheckboxes inherit the color:

	if rowView % 2 != 0:
		customizations = {'background': java.awt.Color(150, 150, 150 ,255)}
	else:
		customizations = {'background':java.awt.Color(0, 0, 0, 255)}

image

Filtering the customizers using column class allows me to get all of the checkboxes white (what we want), but we are still back to the original problem of not being able to customize the Boolean column row by row

	if self.table.getColumnClass(colIndex) != java.lang.Boolean:
		if rowView % 2 != 0:
			customizations = {'background': java.awt.Color(150, 150, 150 ,255)}
		else:
			customizations = {'background':java.awt.Color(0, 0, 0, 255)}
	else:
		customizations = {'background': java.awt.Color(255, 255, 255 ,255)}
	return customizations

Anybody have an idea? One idea I’m toying with is simply positioning an empty power table under this one. Since the column is transparent, the grey and black cells from other table’s empty column would effectively produce the effect I’m looking for if I could bind the number of rows and the scroll functions of the two tables together.

Edit: added missing self.background = java.awt.Color(255, 255, 255 ,0) to the script. This is required for transparency to occur. I had originally done this manually from the property editor, so I had accidently left it unscripted

I gave up on customizing checkboxes. For my application, I didn’t like the color and thought the checkboxes were too small. What I ended up doing is changing the column type from boolean to int and using iconPath to display an icon instead of a checkbox. Works much better when customizing, imo.

6 Likes

image

The goal of having normalized checkboxes on a power table with alternating colors that include black is achievable by making the Boolean column transparent and layering another power table underneath it. It requires binding the data of the lower z order chart to the primary so the alternating rows always line up. I also dispensed with the lower layer’s borders and hid all but one its columns, so the columns of the primary table can be resized without the other table being revealed.

During scrolling, the following code will automatically keep the the two tables synchronized if embedded into a standard javax.swing.event.ChangeListener that is launched from the initialize extension function.

currentPosition = self.layout.getViewport().getViewPosition()
self.parent.getComponent('Background Power Table').layout.getViewport().setViewPosition(currentPosition)

In any case, as fun as this was to explore all the way down the bottom of the proverbial rabbit hole, the idea presented @dkhayes117 is a far superior get by. If I ever have to do a dark mode in one of my projects that requires a power table with check marks, dkhayes117’s idea is definitely the one I am inclined to implement.

2 Likes

Recently, I was messing around with painting the cells of a power table a gradient color, and the process gave me an idea on an alternative approach to this old problem. Combining what I learned painting the gradient cells and code I had previously developed for changing the checkbox size on the alarm status table, I was able to produce this work around using the configureCell extension function:

The code checks each column to see if the column class is Boolean. If not, it colors the rows the normal way, but if it is a bool, it creates an image icon to put in place of the JCheckbox. To make the checkbox look good when toggling, I had to set the column to not editable, and use the onMouseClick extension function to change the value in the dataset. Otherwise, it looked kind of funny because the editor would override the painting and turn the whole cell white for a second.

Here is the configureCell script:

#def configureCell(self, [...]):
	from java.lang import Boolean
	from java.awt import BasicStroke
	from java.awt.image import BufferedImage
	from javax.swing import ImageIcon
	cellRect = self.table.getCellRect(rowIndex, colIndex, True)
	squareDims = 12
	margin = 14
	x = int(0.5 * float(cellRect.width - squareDims - margin))
	y = int(0.5 *float(cellRect.height - squareDims - margin))
	if self.table.getColumnClass(colView) != Boolean:
		if selected:
			return {'background': self.selectionBackground}
		if rowView % 2 != 0:
			return {'background': 'gray', 'foreground': 'white'}
		else:
			return {'background':'black', 'foreground': 'white'}
	else:
		renderer = self.table.defaultCellRenderer
		if selected:
			renderer.background = self.selectionBackground
		elif rowView % 2 != 0:
			renderer.background = system.gui.color('gray')
		else:
			renderer.background = system.gui.color('black')
		checkedImage = BufferedImage(cellRect.width - margin, cellRect.height - margin, BufferedImage.TYPE_INT_ARGB)
		checkBox = checkedImage.createGraphics()
		if self.data.getValueAt(rowIndex, colIndex):
			checkBox.setPaint(system.gui.color('blue'))
		else:
			checkBox.setPaint(system.gui.color('white'))
		checkBox.fillRect(x, y, squareDims, squareDims)
		checkBox.setColor(system.gui.color('white'))
		checkBox.setStroke(BasicStroke(2))
		checkBox.drawLine(x + 2, y + 5, x + 4, y + 8)
		checkBox.drawLine(x + 4, y + 8, x + 10, y + 2)
		renderer.icon = ImageIcon(checkedImage)
		renderer.text = None
		return {'renderer':renderer}

Here is the onMouseClick script:

#def onMouseClick(self, [...]):
	from java.lang import Boolean
	if self.table.model.getColumnClass(colIndex) == Boolean:
		currentValue = self.data.getValueAt(rowIndex, colIndex)
		self.data = system.dataset.setValue(self.data, rowIndex, colIndex, not currentValue)

Edit:
I still had the original table I used during my earlier attempt. Here's what it looks like with the updated approach:
image