Power table with drop down with listener

I have a project where the power tables are populated dynamically from a database and this is working fine. They then requested the ability to add dynamic drop-downs in the table with separate options. I used the solution from the following post modifying as needed.

David Wisely Solution

This works well, thank you David! I am having a problem trying to implement a listener with the dynamic JComboBox and I have never used this before so any help is appreciated. The issue I am trying to solve is when a user selects an option then clicks another component the selection is not written to the underlying table dataset. Here is the code in the configureEditor.

	from javax.swing import AbstractCellEditor,JComboBox, JTextField
	from javax.swing.table import TableCellEditor
	from java.awt.event import ItemListener, ItemEvent


	# used to listen to item change events in the combobox
	class MyItemListener(ItemListener):
		
		# Constructor
		def __init__(self, table, value, rowIndex, colIndex,editor):
			self.table = table
			self.rowIndex = rowIndex
			self.colIndex = colIndex
			self.value = value
			#self.options = {'':0, 'OPEN':1, 'CLOSED':2}
			self.editor = editor
			
		# this is fired when the combobox changes
		def itemStateChanged(self, event):
			if (event.getStateChange() == ItemEvent.SELECTED):
				item = event.getItem()
	
				# convert the new value to the index. E.g. OFF -> 0
				if type(self.editor) is JComboBox:
					newValue = self.editor.getSelectedItem() 
				else:
					newValue = self.editor.getText()
#				
#				
#				
#				if item in self.options:
#					newValue = self.options[item]
#					
				# create a new dataset with the updated value					
				newDS = system.dataset.setValue(self.table.data, self.rowIndex, self.colIndex, newValue)
				self.data = system.dataset.setValue(self.data, rowIndex, colIndex, newValue)
					# write back to the source property
					# update this to whereever your master data is
				self.table.data = newDS
	
	rootSelf = self
	class myTableCellEditor(TableCellEditor, AbstractCellEditor):	
	
		def __init__(self, tableComponent):
			self.table= tableComponent
			self.editor = None
			
		
		def getTableCellEditorComponent(self, table, value, isSelected, rowIndex, vColIndex):	
			def setJComboBox(ds):
				ddList = ['']
				values = [row['ddValue'] for row in system.dataset.toPyDataSet(ds)]
				ddList.extend(values)
				self.editor = JComboBox(ddList)
			
			if rowIndex == 0: # Collar
				ds = rootSelf.ddCollar
				setJComboBox(ds)
			elif rowIndex == 1: # Holes
				ds = rootSelf.ddHoles
				setJComboBox(ds)
			elif rowIndex == 3: # Edge Slitters
				ds = rootSelf.ddSlitter
				setJComboBox(ds)
			elif rowIndex in [6,7]: # Pressure
				ds = rootSelf.ddPressureBar
				setJComboBox(ds)
			else:
				self.editor = JTextField()
	
			return self.editor
		
		def getCellEditorValue(self):
			if type(self.editor) is JComboBox:
				newValue = self.editor.getSelectedItem() 
			else:
				newValue = self.editor.getText()
		
			return newValue
			
	if colName == "User Defined":
		m = myTableCellEditor(self)
		return {"editor":m}

Hi TimE,

The idea of the ItemListener is that you don’t need to click on another component. As soon as the selection is made in the combobox the ItemListener is fired and updates the underlying dataset.

You need to add the listener to the JComboBox.
When you create the JComboBox with this line:

self.editor = JComboBox(ddList)

on the next lines, set the index and add the listener, like this:

self.editor = JComboBox(ddList)
# set the selected item to the current value in the underlying data
self.editor.setSelectedIndex(value)
# add an Item changed listener
self.editor.addItemListener(MyItemListener(self.table, value, rowIndex, colIndex))

you also don’t need these lines in the itemStateChanged function:

if type(self.editor) is JComboBox:
	newValue = self.editor.getSelectedItem() 
else:
	newValue = self.editor.getText()

as you get the newValue from the event.getItem() function:

newValue = event.getItem()

MyItemListener should look something like this:

	# used to listen to item change events in the combobox
	class MyItemListener(ItemListener):
		
		# Constructor
		def __init__(self, table, value, rowIndex, colIndex):
			self.table = table
			self.rowIndex = rowIndex
			self.colIndex = colIndex
			self.value = value
		
		# this is fired when the combobox changes
		def itemStateChanged(self, event):
			if (event.getStateChange() == ItemEvent.SELECTED):
				# get the new value from the combobox
				newValue = event.getItem()

				# create a new dataset with the updated value					
				self.table.data = system.dataset.setValue(self.table.data, self.rowIndex, self.colIndex, newValue)
1 Like