class PeriodicTableWidget(QWidget): selectionChanged = Signal() def __init__(self, parent=None): QWidget.__init__(self, parent) # Widgets, layouts and signals self._group = QButtonGroup() layout = QGridLayout() layout.setSpacing(0) ## Element for z, position in _ELEMENT_POSITIONS.items(): widget = ElementPushButton(z) widget.setCheckable(True) layout.addWidget(widget, *position) self._group.addButton(widget, z) ## Labels layout.addWidget(QLabel(''), 7, 0) # Dummy layout.addWidget(QLabel('*'), 5, 2, Qt.AlignRight) layout.addWidget(QLabel('*'), 8, 2, Qt.AlignRight) layout.addWidget(QLabel('**'), 6, 2, Qt.AlignRight) layout.addWidget(QLabel('**'), 9, 2, Qt.AlignRight) for row in [0, 1, 2, 3, 4, 5, 6, 8, 9]: layout.setRowStretch(row, 1) self.setLayout(layout) # Signals self._group.buttonClicked.connect(self.selectionChanged) # Default self.setColorFunction(_category_color_function) def setColorFunction(self, func): if not callable(func): raise ValueError('Not a function') self._color_function = func # Redraw for widget in self._group.buttons(): z = self._group.id(widget) bcolor = func(z) fcolor = 'white' if _calculate_brightness(bcolor) < 128 else 'black' sheet = 'background-color: %s; color: %s' % (bcolor.name(), fcolor) widget.setStyleSheet(sheet) def colorFunction(self): return self._color_function def setMultipleSelection(self, multiple): self._group.setExclusive(not multiple) def isMultipleSelection(self): return not self._group.exclusive() def setSelection(self, selection): def _uncheckedAll(): for widget in self._group.buttons(): widget.setChecked(False) if selection is None: _uncheckedAll() self.selectionChanged.emit() return if isinstance(selection, (int, six.string_types)): selection = [selection] if not self.isMultipleSelection() and len(selection) > 1: raise ValueError('Multiple selection mode is off. Cannot select more than one element') _uncheckedAll() for z in selection: if isinstance(z, six.string_types): z = get_atomic_number(z) self._group.button(z).setChecked(True) self.selectionChanged.emit() # def selection(self): selection = set() for widget in self._group.buttons(): if widget.isChecked(): selection.add(self._group.id(widget)) if self.isMultipleSelection(): return frozenset(selection) else: if len(selection) > 0: return list(selection)[0] else: return None def selectionSymbol(self): selection = self.selection() if self.isMultipleSelection(): return frozenset(map(get_symbol, selection)) else: if selection is None: return None else: return get_symbol(selection)