I'm working on the GUI part of the input dock on the truss_connection_bolted module on a project called Osdag and the whole GUI part is written using the PyQt5 module. My task is to finish the connecting members attribute on the Input dock which happens to be a set of QComboBox
widgets on a single QTableWidget
. I have successfully written most of the part by there is one section of QComboBox
in the Table widget that depends on another QComboBox
.
After long research, I was able to create a stud that shows the required functionality. Here is the following code snippet for the stub.
# ---------------
# More Code above
# ---------------
# Table Widget Creation
table_widget = QtWidgets.QTableWidget(self.dockWidgetContents)
table_widget.setObjectName(option[0])
table_widget.setRowCount(8)
table_widget.setColumnCount(6)
# Attributes dictionary
selectable_options = {
'Section profile': ['Angle', 'Star Angles', 'Back to Back Angles', 'Channel','Back to Back Channels'],
'Connection Location': {
'Angle': ['Long leg connected', 'Short leg connected'],
'Channel': ['Web-connected']
},
'Section Size': ['20 x 20 x 3', '20 x 20 x 4', '25 x 25 x 3', '25 x 25 x 4', ...],
'Material': [ 'E165', 'E250 (Fe 410W) A', 'E250 (Fe 410W) B', 'E250 (Fe 410W) C', ....]
}
# Setting Head Labels to the table widget
table_widget.setHorizontalHeaderLabels(
list(selectable_options.keys()) + ["Angle with x-axis (Degrees)", "Factored Load (KN)"]
)
# Creating two indivdual QComboBox for testing out the dependency functionality
combo_box_secpro = QtWidgets.QComboBox()
combo_box_connloc = QtWidgets.QComboBox()
# Adding values to the "Section Profile" QComboBox
for item in selectable_options['Section profile']:
value = None
if item in ['Angle', 'Star Angles', 'Back to Back Angles']:
value = selectable_options['Connection Location']['Angle']
elif item in ['Channel', 'Back to Back Channels']:
value = selectable_options['Connection Location']['Channel']
combo_box_secpro.addItem(item, value)
# Connecting "Section Profile" QComboBox to "Connection Location" QComboBox
combo_box_secpro.activated.connect(
lambda: combo_box_connloc.clear() or combo_box_connloc.addItems(
selectable_options['Connection Location'][ 'Angle' if combo_box_secpro.currentText() in ['Angle', 'Star Angles', 'Back to Back Angles'] else 'Channel']
)
)
# Placing both of those the QComboBoxes into table Widget
table_widget.setCellWidget(0,0,combo_box_secpro)
table_widget.setCellWidget(0,1,combo_box_connloc)
# ---------------
# More code below
# ---------------
The above code snippet worked fine but, when I tried to loop the same logic... It's not working as Intended... The code snippet for the looping logic:
# ---------------------
# More other code above
# ---------------------
# Note that this is just a looped version of the above logic,
# so all the other declarations of the dictionary mentioned above are present here..
combo_box_dictionary = dict() # Just in case, if we need the combo_box object for each option
for col, (key, value) in enumerate(selectable_options.items()):
# Skipping 'Connection location' as I have handled it in 'Section profile'
if key == 'Connection Location':
continue
# Creating 'Connection location' QComboBox that depend on 'Section profile' QComboBox
elif key == 'Section profile':
combo_box_section_profile_list = []
combo_box_connection_location_list = []
# Looping for 8 times for each row in table widget
for row in range(8):
# Creating QComboBox Object for both 'Section profile' & 'Connection location'
combo_box_section_profile = QtWidgets.QComboBox()
combo_box_connection_location = QtWidgets.QComboBox()
# Adding items into 'Section profile' QComboBox
for item in selectable_options['Section profile']:
value = None
if item in ['Angle', 'Star Angles', 'Back to Back Angles']:
value = selectable_options['Connection Location']['Angle']
elif item in ['Channel', 'Back to Back Channels']:
value = selectable_options['Connection Location']['Channel']
combo_box_section_profile.addItem(item, value)
# Connecting 'Section profile' dependent functionality to 'Connection Location'
combo_box_section_profile.activated.connect(
lambda: combo_box_connection_location.clear() or combo_box_connection_location.addItems(
selectable_options['Connection Location']['Angle' if combo_box_section_profile.currentText() in ['Angle', 'Star Angles', 'Back to Back Angles'] else 'Channel']
)
)
# Added Default Items into 'Connection Location'
combo_box_connection_location.addItems(selectable_options['Connection Location']['Angle'])
# Setting the QComboBoxes into their respective places
table_widget.setCellWidget(row, col, combo_box_section_profile)
table_widget.setCellWidget(row, col+1, combo_box_connection_location)
# Storing their Object References per each row
combo_box_section_profile_list.append(combo_box_section_profile)
combo_box_connection_location_list.append(combo_box_connection_location)
# Collectively storing Object References for both of them for all the rows
combo_box_dictionary['Section profile'] = combo_box_section_profile_list
combo_box_dictionary['Connection Location'] = combo_box_connection_location_list
else:
# Logic for adding simple QComboBoxes to the table widget
combo_box_list = []
for row in range(8):
combo_box = QtWidgets.QComboBox()
combo_box.addItems(value)
table_widget.setCellWidget(row, col, combo_box)
combo_box_list.append(combo_box)
combo_box_dictionary[key] = combo_box_list
# ---------------------
# More other code below
# ---------------------
Note:
- If you want to see the whole code you can find it within my GitHub in truss-connection-bolted-gui.
- If you wish to setup the project within you system, make sure the following things;
- Use Ubuntu 20.04 LTS version through your VM.
- Follow the README.md instrustion to install the project environment.
- And It's recommended to use Pycharm IDE.
I have spent a lot of time search for some answers but, could find one. Is there way to fix this problem ?
Other than my original implementation, I have tried searching for an alternative to the connecting method but couldn't find one...
Then I tried different approaches like storing the object references and then assigning the connecting method to link up the required functionality to the respective QComboBoxes. But, That didn't work out either...
for col, (key, value) in enumerate(selectable_options.items()):
combo_box_list = []
for row in range(8):
combo_box = QtWidgets.QComboBox()
if key == 'Connection Location':
value = selectable_options['Connection Location']['Angle']
combo_box.addItems(value)
table_widget.setCellWidget(row, col, combo_box)
combo_box_list.append(combo_box)
combo_box_dictionary[key] = combo_box_list
for index, secpro_QComboBox in enumerate(combo_box_dictionary['Section profile']):
connloc_QComboBox = combo_box_dictionary['Connection Location'][index]
secpro_QComboBox.activated.connect(lambda:
connloc_QComboBox.clear() or
connloc_QComboBox.addItems(
selectable_options['Connection Location']['Angle' if secpro_QComboBox.currentText() in ['Angle', 'Star Angles', 'Back to Back Angles'] else 'Channel']
)
)
I don't know what to do, it's giving me the same error. Can anyone figure out what's going on ?
Top comments (1)
Even though, My question is marked as duplicate and has been closed *( I've applied for review that even though it was a similar case, it's no way near my case )*I have resolved the issue with the advice given by @musicamante in Stackoverflow. Even though it was abstract, I got the idea to implement the same logic differently.
In the comment, he suggested that I use an explicit function instead of complex code for creating the dependent
QComboBox
. So, I have taken the same logic which I initially created and placed it into a method and used it within the current method where the whole logic was supposed to be executed. This method only takes the required data dictionary and returns a pair of dependentQComboBox
es.