# Alarm table checkbox size

**URL:** <https://forum.inductiveautomation.com/t/alarm-table-checkbox-size/67665>\
**Category:** Ignition\
**Tags:** ignition81, vision\
**Created:** [December 15, 2022, 10:44am UTC](https://forum.inductiveautomation.com/t/alarm-table-checkbox-size/67665 "2022-12-15T10:44:26Z")\
**Posts on this page:** 1\
**Showing post:** 3

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [January 12, 2023, 3:14pm UTC](https://forum.inductiveautomation.com/t/alarm-table-checkbox-size/67665/3 "2023-01-12T15:14:52Z")

</div>

Lately, I've been messing around with the alarm status table in my spare time for fun, and in doing so, I've developed a way to produce larger checkboxes. In reality, it's just a simple overlay that adjusts the row height and column width to accommodate whatever size checkbox is specified and then paints the larger checkboxes over the originals. Listeners are used to repaint the checkboxes whenever they are clicked or when the table model changes as a result of filtering, sorting, or alarm state changes.

The checkbox size is specified in the second line of the script, and it can be set to any integer. Below is a picture that depicts the result. Four alarm status tables of equal size are staggered on top of each other. The bottom table is original and does not have the customization applied. The next three tables have specified checkboxes of size 25, 50, and 80 respectively.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/2/f21883f873f190efba5bb58b4be70104b107439b.png)

Here is a short video that illustrates how the modification looks when scrolling and sorting :

[https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/9/f979ad6e79cb4ed791ac00098aa011618145a876.mp4](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/9/f979ad6e79cb4ed791ac00098aa011618145a876.mp4)

This script adds listeners to the table, so it shouldn't be activated from a place that could fire more than once. My recommendation is to use the parent window's internalFrameOpened event handler. Here is the source code:

> **Source Code:**
>
> ```auto
> alarmStatusTable = system.gui.getParentWindow(event).getComponentForPath('Root Container.Alarm Status Table') #From the parent window's internalFrameOpened event handler
> checkboxSize = 50
> from javax.swing import JTable, JLabel, ImageIcon, OverlayLayout
> from javax.swing.table import DefaultTableModel, DefaultTableCellRenderer, TableCellEditor
> from javax.swing.event import TableModelListener
> from java.awt import Color, Font, Dimension, BasicStroke, Graphics
> from java.awt.event import MouseAdapter, MouseEvent
> from java.awt.image import BufferedImage
> from com.jidesoft.grid import JideTable
> from com.jidesoft.swing import TristateCheckBox
> class CheckboxRenderer(DefaultTableCellRenderer):
> def __init__ (self):
> self.setSelected = False
> def getTableCellRendererComponent(self, table, value, isSelected, hasFocus, row, column):
> self.setEnabled(table.isEnabled())
> self.setForeground(table.getForeground())
> self.setBackground(table.getBackground())
> if value == True:
> self.setSelected = True
> else:
> self.setSelected = False
> return self
> def paintComponent(self, g):
> if self.setSelected:
> checkedBox = g.create()
> checkedBox.setColor(Color.blue)
> checkedBox.fillRoundRect(0, 0, self.getWidth()-1, self.getHeight()-1, 8, 8)
> checkedBox.setColor(Color(214,214,214))
> checkedBox.drawRoundRect(0, 0, self.getWidth()-1, self.getHeight()-1, 8, 8)
> checkedBox.setStroke(BasicStroke(int(.14*float(checkboxSize))))
> checkedBox.drawLine((int(.16*float(checkboxSize))), int(float(checkboxSize)*.5), int(.3*checkboxSize), (checkboxSize - int(.16*float(checkboxSize))))
> checkedBox.drawLine(int(.3*checkboxSize), (checkboxSize - int(.16*float(checkboxSize))), (checkboxSize - int(.16*float(checkboxSize))), (int(.16*float(checkboxSize))))
> checkedBox.dispose()
> else:
> uncheckedBox = g.create()
> uncheckedBox.setColor(Color(214,214,214))
> uncheckedBox.fillRoundRect(0, 0, self.getWidth()-1, self.getHeight()-1, 8, 8)
> uncheckedBox.setColor(Color.black)
> uncheckedBox.drawRoundRect(0, 0, self.getWidth()-1, self.getHeight()-1, 8, 8)
> uncheckedBox.dispose()
> class LabelMouseListener(MouseAdapter):
> def mouseClicked(self, event):
> checkboxModel = getTable('checkbox').getModel()
> checked = False
> unchecked = False
> triStateCheckbox = getTriStateCheckbox(alarmStatusTable)
> triStateCheckbox.doClick()
> class TableChangeListener(TableModelListener):
> def tableChanged(self, event):
> if not alarmStatusTable.multiSelect:
> return
> mainModel = event.source
> checkboxModel = getTable('checkbox').getModel()
> overlayModel = getTable('overlay').getModel()
> triStateCheckBox = getTriStateCheckbox(alarmStatusTable)
> bigTriStateCheckbox = getBigCheckbox(alarmStatusTable)
> if overlayModel.rowCount < checkboxModel.rowCount:
> for row in range(overlayModel.rowCount, checkboxModel.rowCount):
> overlayModel.addRow([False])
> for row in range(overlayModel.rowCount):
> overlayModel.setValueAt(checkboxModel.getValueAt(row, 0), row, 0)
> else:
> for row in range(overlayModel.rowCount):
> if row < checkboxModel.rowCount:
> overlayModel.setValueAt(checkboxModel.getValueAt(row, 0), row, 0)
> else:
> for deletedRow in range(checkboxModel.rowCount, overlayModel.rowCount):
> overlayModel.removeRow(checkboxModel.rowCount)
> if triStateCheckBox.getState() == 0:
> bigTriStateCheckbox.setIcon(setUnchecked())
> elif triStateCheckBox.getState() == 1:
> bigTriStateCheckbox.setIcon(setChecked())
> else:
> bigTriStateCheckbox.setIcon(setPartialChecked())
> class TableMouseListener(MouseAdapter):
> def __init__ (self, table):
> self.table = table
> def mousePressed(self, event):
> if event.getButton() == MouseEvent.BUTTON1:
> point = event.getPoint()
> row = self.table.rowAtPoint(point)
> if row != -1:
> checkboxModel = getTable('checkbox').getModel()
> modifiedTable = self.table 
> if checkboxModel.getValueAt(modifiedTable.convertRowIndexToModel(row), 0):
> checkboxModel.setValueAt(False, modifiedTable.convertRowIndexToModel(row), 0)
> else:
> checkboxModel.setValueAt(True, modifiedTable.convertRowIndexToModel(row), 0)
> class BooleanEditor(TableCellEditor):
> def getTableCellEditorComponent(self, table, value, isSelected, row, column):
> checkboxModel = getTable('checkbox').getModel()
> if value:
> table.getModel().setValueAt(False, row, column)
> checkboxModel.setValueAt(False, row, column)
> else:
> table.getModel().setValueAt(True, row, column)
> checkboxModel.setValueAt(True, row, column)
> def isCellEditable(self, event):
> return True
> def setCheckboxOverlay(checkboxTable):
> checkboxModel = checkboxTable.getModel()
> overlayModel = DefaultTableModel()
> checkBoxOverlay = JTable(overlayModel)
> checkBoxOverlay.setPreferredScrollableViewportSize(checkboxTable.getPreferredScrollableViewportSize())
> overlayModel.addColumn([])
> for row in range(checkboxModel.rowCount):
> overlayModel.addRow([checkboxModel.getValueAt(row, 0)])
> checkBoxOverlay.getColumnModel().getColumn(0).setCellRenderer(CheckboxRenderer())
> checkBoxOverlay.getColumnModel().getColumn(0).setCellEditor(BooleanEditor())
> return checkBoxOverlay
> def getTable(tableType):#Retrieves a fresh jTable instance from the alarmStatusTable
> def tableSearch(tableType, alarmStatusTable):
> if alarmStatusTable.componentCount > 0:
> for component in alarmStatusTable.getComponents():
> if 'AlarmStatusTable$1' in str(component. __class__ ) and tableType == 'main':
> return component
> elif 'JideTable' in str(component. __class__ ) and tableType == 'checkbox':
> return component
> elif 'JTable' in str(component. __class__ ) and tableType == 'overlay':
> return component
> else:
> table = tableSearch(tableType, component)
> if table is not None:
> return table
> return None
> return tableSearch(tableType, alarmStatusTable)
> def initializeTable():
> checkboxTable = getTable('checkbox')
> mainTable = getTable('main')
> checkboxViewport = checkboxTable.getParent()
> checkboxTable.visible = False
> checkBoxOverlay = setCheckboxOverlay(checkboxTable)
> overlayModel = checkBoxOverlay.getModel()
> checkboxTable.getParent().getParent().add(checkboxTable)
> checkboxViewport.add(checkBoxOverlay)
> checkBoxscrollPane = checkBoxOverlay.getParent().getParent()
> checkBoxViewport = checkBoxOverlay.getParent()
> checkBoxscrollPane.setPreferredSize(Dimension(checkboxSize, checkBoxscrollPane.getPreferredSize().height))
> checkBoxViewport.setPreferredSize(Dimension(checkboxSize, checkBoxViewport.getPreferredSize().height))
> checkBoxOverlay.setRowHeight(checkboxSize)
> mainTable.setRowHeight(checkboxSize)
> mainTable.getTableHeader().setPreferredSize(Dimension(mainTable.getTableHeader().getPreferredSize().width, checkboxSize))
> checkBoxOverlay.setShowGrid(True)
> checkBoxOverlay.setGridColor(Color.black)
> mainTable = getTable('main')
> modelListener = TableChangeListener()
> mainTable.getModel().addTableModelListener(modelListener)
> triStateCheckbox = getTriStateCheckbox(alarmStatusTable)
> bigTriStateCheckbox = JLabel()
> bigTriStateCheckbox.name = 'bigCheckBox'
> bigTriStateCheckbox.setIcon(setUnchecked())
> parent = triStateCheckbox.getParent()
> parent.setLayout(OverlayLayout(parent))
> parent.remove(triStateCheckbox)
> parent.add(bigTriStateCheckbox)
> parent.add(triStateCheckbox)
> listener = LabelMouseListener()
> bigTriStateCheckbox.addMouseListener(listener)
> def getTriStateCheckbox(component):
> if component.componentCount > 0:
> for component in component.getComponents():
> if isinstance(component, TristateCheckBox):
> return component
> else:
> triStateCheckbox = getTriStateCheckbox(component)
> if triStateCheckbox is not None:
> return triStateCheckbox
> return None
> def getBigCheckbox(component):
> if component.componentCount > 0:
> for component in component.getComponents():
> if component.name == 'bigCheckBox':
> return component
> else:
> triStateCheckbox = getBigCheckbox(component)
> if triStateCheckbox is not None:
> return triStateCheckbox
> return None
> def setUnchecked():
> uncheckedImage = BufferedImage(checkboxSize, checkboxSize, BufferedImage.TYPE_INT_ARGB)
> uncheckedBox = uncheckedImage.createGraphics()
> uncheckedBox.setColor(Color(214,214,214))
> uncheckedBox.fillRoundRect(0, 0, checkboxSize-1, checkboxSize-1, 8, 8)
> uncheckedBox.setColor(Color.black)
> uncheckedBox.drawRoundRect(0, 0, checkboxSize-1, checkboxSize-1, 8, 8)
> uncheckedBox.dispose()
> uncheckedIcon = ImageIcon(uncheckedImage)
> return uncheckedIcon
> def setChecked():
> checkedImage = BufferedImage(checkboxSize, checkboxSize, BufferedImage.TYPE_INT_ARGB)
> checkedBox = checkedImage.createGraphics()
> checkedBox.setColor(Color.blue)
> checkedBox.fillRoundRect(0, 0, checkboxSize-1, checkboxSize-1, 8, 8)
> checkedBox.setColor(Color(214,214,214))
> checkedBox.drawRoundRect(0, 0, checkboxSize-1, checkboxSize-1, 8, 8)
> checkedBox.setStroke(BasicStroke(int(.14*float(checkboxSize))))
> checkedBox.drawLine((int(.16*float(checkboxSize))), int(float(checkboxSize)*.5), int(.3*checkboxSize), (checkboxSize - int(.16*float(checkboxSize))))
> checkedBox.drawLine(int(.3*checkboxSize), (checkboxSize - int(.16*float(checkboxSize))), (checkboxSize - int(.16*float(checkboxSize))), (int(.16*float(checkboxSize))))
> checkedBox.dispose()
> checkedIcon = ImageIcon(checkedImage)
> return checkedIcon
> def setPartialChecked():
> checkedImage = BufferedImage(checkboxSize, checkboxSize, BufferedImage.TYPE_INT_ARGB)
> checkedBox = checkedImage.createGraphics()
> checkedBox.setColor(Color.blue)
> checkedBox.fillRoundRect(0, 0, checkboxSize-1, checkboxSize-1, 8, 8)
> checkedBox.setColor(Color(214,214,214))
> checkedBox.drawRoundRect(0, 0, checkboxSize-1, checkboxSize-1, 8, 8)
> checkedBox.setStroke(BasicStroke(int(.14*float(checkboxSize))))
> checkedBox.drawLine(int(.16*float(checkboxSize)), int(float(checkboxSize)*.5), (checkboxSize - int(.16*float(checkboxSize))), int(float(checkboxSize)*.5))
> checkedBox.dispose()
> checkedIcon = ImageIcon(checkedImage)
> return checkedIcon
> initializeTable()
> 
> ```

I've tested this script with more than 1100 active alarms, and it worked quite well:  
 ![Capture](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/b/5b8a5afe197027ccc347df3f9fce654240ddadae.png)

---

_[View the full topic](https://forum.inductiveautomation.com/t/alarm-table-checkbox-size/67665)._
