I have built a GUI window that is part of a project, and I need to have three separate groups of radio-buttons, each group must be independent in the uniqueness. I can't find the way how to separate the linkage between the radio-buttons. So only one can be checked, and all the others are automatically unchecked.
I tried to use QtWidgets.QButtonGroup But the code failed and I don't understand why.
How can create separate groups that are independent?
this is the code I have:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import QDialog, QListWidget, QGridLayout, QListWidgetItem, QPushButton, QMessageBox, QLineEdit
from PyQt5 import QtCore, QtWidgets
class Add_Element(QDialog):
# def __init__(self, item_ls, parent=None):
# super(Calc_pro, self).__init__(parent)
def __init__(self, item_ls, parent=None):
super().__init__()
self.setupUi(Add_Element, item_ls)
def setupUi(self, Add_Element, item_ls):
self.result = ""
self.floor_data = [] # This is a list of a set of all the parameters needed for a single simulation
self.floor_data = ["no_floor", 0.0, "no file", 1.0, "0.0", "0.0", "20.", "20.", "50", 0, "no description"]
self.simulations_data_list = [] # This list will save all self.floor_data that the user defined, and will be
self.hbox1 = QtWidgets.QHBoxLayout()
self.hbox2 = QtWidgets.QHBoxLayout()
self.hbox3 = QtWidgets.QHBoxLayout()
self.hbox4 = QtWidgets.QHBoxLayout()
self.gbox1 = QtWidgets.QGridLayout()
self.gbox2 = QtWidgets.QGridLayout()
self.hbox5 = QtWidgets.QHBoxLayout()
self.hbox6 = QtWidgets.QHBoxLayout()
self.hbox7 = QtWidgets.QHBoxLayout()
# =================================================
# Header - hbox 1
# =================================================
self.calc_pop_lbl = QtWidgets.QLabel("Electrical Element", self)
self.hbox1.addWidget(self.calc_pop_lbl)
font_big = QtGui.QFont()
font_big.setPointSize(14)
font_big.setBold(True)
font_big.setWeight(75)
self.calc_pop_lbl.setFont(font_big)
self.calc_pop_lbl.setAlignment(QtCore.Qt.AlignCenter)
font_bld = QtGui.QFont()
font_bld.setPointSize(12)
font_bld.setBold(True)
font_bld.setWeight(75)
# ==============================
# Name & Type - hbox 2
# ==============================
self.element_name_lbl = QtWidgets.QLabel("Element Type", self)
self.hbox2.addWidget(self.element_name_lbl)
font = QtGui.QFont()
font.setPointSize(12)
self.element_name_lbl.setFont(font)
self.element_name_lbl.setAlignment(QtCore.Qt.AlignCenter)
self.element_selection_comboBox = QtWidgets.QComboBox(self)
self.hbox2.addWidget(self.element_selection_comboBox)
self.element_selection_comboBox.setFont(font)
self.element_selection_comboBox.setToolTip("<html><head/><body><p>Select the Type</p></body></html>")
self.element_selection_comboBox.addItem("לוח רגיל") # 0
self.element_selection_comboBox.addItem("לוח קומפקטי") # 1
self.element_selection_comboBox.addItem("Cable Square") # 2
self.element_selection_comboBox.addItem("Cable Flat") # 3
self.element_selection_comboBox.addItem("Trafo Long") # 4
self.element_selection_comboBox.addItem("Trafo Broad") # 5
self.element_selection_comboBox.addItem("כבל דו-גידי") # 6
self.element_selection_comboBox.addItem("חוט בודד") # 7
self.element_selection_comboBox.addItem("Cable 3Phase ELMF") # 8
self.element_selection_comboBox.addItem("Cable 1Phase ELMF") # 9
self.element_name_lbl = QtWidgets.QLabel("Element Name", self)
self.hbox2.addWidget(self.element_name_lbl)
font = QtGui.QFont()
font.setPointSize(12)
self.element_name_lbl.setFont(font)
self.element_name_lbl.setAlignment(QtCore.Qt.AlignCenter)
self.element_name_input = QtWidgets.QLineEdit("Panel")
self.element_name_input.setFont(font)
self.hbox2.addWidget(self.element_name_input)
# ==============================
# Description - hbox 3
# ==============================
self.element_desc_lbl = QtWidgets.QLabel("Element Description", self)
self.element_desc_lbl.setFont(font)
self.element_name_lbl.setAlignment(QtCore.Qt.AlignCenter)
self.element_desc_input = QtWidgets.QLineEdit("לוח ראשי קק")
self.element_desc_input.setFont(font)
self.hbox3.addWidget(self.element_desc_lbl)
self.hbox3.addWidget(self.element_desc_input)
# =====================================
# Position - grid box 1
# ======================================
self.start_lbl = QtWidgets.QLabel("Start Point")
self.end_lbl = QtWidgets.QLabel("End Point")
self.start_lbl.setFont(font)
self.end_lbl.setFont(font)
self.gbox1.addWidget(self.start_lbl, 1, 2, 1, 1)
self.gbox1.addWidget(self.end_lbl, 1, 3, 1, 1)
self.x_lbl = QtWidgets.QLabel("X[m]")
self.x_lbl.setFont(font)
self.gbox1.addWidget(self.x_lbl, 2, 1, 1, 1)
self.y_lbl = QtWidgets.QLabel("Y[m]")
self.y_lbl.setFont(font)
self.gbox1.addWidget(self.y_lbl, 3, 1, 1, 1)
self.z_lbl = QtWidgets.QLabel("Z[m]")
self.z_lbl.setFont(font)
self.gbox1.addWidget(self.z_lbl, 4, 1, 1, 1)
self.xs_pos = QtWidgets.QLineEdit("0")
self.xs_pos.setFont(font)
self.gbox1.addWidget(self.xs_pos, 2, 2, 1, 1)
self.ys_pos = QtWidgets.QLineEdit("0")
self.ys_pos.setFont(font)
self.gbox1.addWidget(self.ys_pos, 3, 2, 1, 1)
self.zs_pos = QtWidgets.QLineEdit("0")
self.zs_pos.setFont(font)
self.gbox1.addWidget(self.zs_pos, 4, 2, 1, 1)
self.xe_pos = QtWidgets.QLineEdit("0")
self.xe_pos.setFont(font)
self.gbox1.addWidget(self.xe_pos, 2, 3, 1, 1)
self.ye_pos = QtWidgets.QLineEdit("0")
self.ye_pos.setFont(font)
self.gbox1.addWidget(self.ye_pos, 3, 3, 1, 1)
self.ze_pos = QtWidgets.QLineEdit("0")
self.ze_pos.setFont(font)
self.gbox1.addWidget(self.ze_pos, 4, 3, 1, 1)
self.length_lbl = QtWidgets.QLabel("Length[m]")
self.length_lbl.setFont(font)
self.gbox1.addWidget(self.length_lbl, 5, 1, 1, 1)
self.length = QtWidgets.QLineEdit("1.0")
# self.length.setReadOnly(True)
self.length.setFont(font)
self.gbox1.addWidget(self.length, 5, 2, 1, 1)
self.dir_lbl = QtWidgets.QLabel("Direction")
self.dir_lbl.setFont(font)
self.dir_lbl.setAlignment(QtCore.Qt.AlignRight)
self.gbox1.addWidget(self.dir_lbl, 5, 3, 1, 1)
# direction_group = QtWidgets.QButtonGroup()
self.dir_x = QtWidgets.QRadioButton("X")
self.dir_x.setChecked(True)
self.dir_y = QtWidgets.QRadioButton("Y")
self.dir_z = QtWidgets.QRadioButton("Z")
self.gbox1.addWidget(self.dir_x, 5, 4, 1, 1)
self.gbox1.addWidget(self.dir_y, 5, 5, 1, 1)
self.gbox1.addWidget(self.dir_z, 5, 6, 1, 1)
# direction_group.addButton(self.dir_x, 0)
# direction_group.addButton(self.dir_y, 1)
# direction_group.addButton(self.dir_z, 2)
self.load_defaults_btn = QtWidgets.QPushButton("Load Defaults")
self.load_defaults_btn.setFont(font)
# ------------------------------------------
# gbox2
# ------------------------------------------
self.currant_lbl = QtWidgets.QLabel("Currents and Power")
self.currant_lbl.setFont(font_bld)
self.frame_current = QtWidgets.QFrame()
self.frame_current.setObjectName("frame_current")
self.imax_radio = QtWidgets.QRadioButton("Imax[A]")
self.imax_radio.setFont(font)
self.ityp_radio = QtWidgets.QRadioButton("Ityp[A]")
self.ityp_radio.setFont(font)
self.ityp_radio.setChecked(True)
self.imax_input = QtWidgets.QLineEdit("100")
self.ityp_input = QtWidgets.QLineEdit("60")
self.imax_input.setFont(font)
self.ityp_input.setFont(font)
i_group = QtWidgets.QButtonGroup()
self.gbox2.addWidget(self.currant_lbl, 1, 1, 1, 3)
self.gbox2.addWidget(self.imax_radio, 2, 1, 1, 1)
self.gbox2.addWidget(self.ityp_radio, 3, 1, 1, 1)
self.gbox2.addWidget(self.imax_input, 2, 2, 1, 1)
self.gbox2.addWidget(self.ityp_input, 3, 2, 1, 1)
i_group.addButton(self.imax_radio, 0)
i_group.addButton(self.ityp_radio, 1)
self.typ_max_ratio_lbl = QtWidgets.QLabel("Typ/Max Ratio")
self.typ_max_ratio_lbl.setFont(font)
self.imbalance_lbl = QtWidgets.QLabel("Imbalance factor")
self.imbalance_lbl.setFont(font)
self.typ_max_input = QtWidgets.QLineEdit("0.6")
self.imbalance_input = QtWidgets.QLineEdit("0.3")
self.typ_max_input.setFont(font)
self.imbalance_input.setFont(font)
self.gbox2.addWidget(self.typ_max_ratio_lbl, 4, 1, 1, 1)
self.gbox2.addWidget(self.imbalance_lbl, 5, 1, 1, 1)
self.gbox2.addWidget(self.typ_max_input, 4, 2, 1, 1)
self.gbox2.addWidget(self.imbalance_input, 5, 2, 1, 1)
self.voltage_lbl = QtWidgets.QLabel("Voltage[V]")
self.voltage_lbl.setFont(font)
self.power_lbl = QtWidgets.QLabel("Power[kVA]")
self.power_lbl.setFont(font)
self.voltage_input = QtWidgets.QLineEdit("220")
self.power_input = QtWidgets.QLineEdit("1000")
self.voltage_input.setFont(font)
self.power_input.setFont(font)
self.power_input.setReadOnly(True)
self.voltage_input.setReadOnly(True)
self.gbox2.addWidget(self.voltage_lbl, 3, 4, 1, 1)
self.gbox2.addWidget(self.power_lbl, 4, 4, 1, 1)
self.gbox2.addWidget(self.voltage_input, 3, 5, 1, 1)
self.gbox2.addWidget(self.power_input, 4, 5, 1, 1)
self.parameters_lbl = QtWidgets.QLabel("Physical Dimensions")
self.parameters_lbl.setFont(font_bld)
self.h_lbl = QtWidgets.QLabel("H[m]")
self.h_lbl.setFont(font)
self.d_lbl = QtWidgets.QLabel("d[m]")
self.d_lbl.setFont(font)
self.hc_lbl = QtWidgets.QLabel("Hc[m]")
self.hc_lbl.setFont(font)
self.dt_lbl = QtWidgets.QLabel("dT[m]")
self.dt_lbl.setFont(font)
trafo_group = QtWidgets.QButtonGroup()
self.dry_radio = QtWidgets.QRadioButton("Dry")
self.dry_radio.setFont(font)
self.oil_radio = QtWidgets.QRadioButton("Oil")
self.oil_radio.setFont(font)
self.dry_radio.setChecked(True)
self.h_input = QtWidgets.QLineEdit("1.8")
self.d_input = QtWidgets.QLineEdit("0.15")
self.hc_input = QtWidgets.QLineEdit("0")
self.dt_input = QtWidgets.QLineEdit("0")
self.h_input.setFont(font)
self.d_input.setFont(font)
self.hc_input.setFont(font)
self.dt_input.setFont(font)
self.gbox2.addWidget(self.parameters_lbl, 1, 6, 1, 2)
self.gbox2.addWidget(self.h_lbl, 2, 6, 1, 1)
self.gbox2.addWidget(self.d_lbl, 3, 6, 1, 1)
self.gbox2.addWidget(self.hc_lbl, 4, 6, 1, 1)
self.gbox2.addWidget(self.dt_lbl, 5, 6, 1, 1)
self.gbox2.addWidget(self.h_input, 2, 7, 1, 1)
self.gbox2.addWidget(self.d_input, 3, 7, 1, 1)
self.gbox2.addWidget(self.hc_input, 4, 7, 1, 1)
self.gbox2.addWidget(self.dt_input, 5, 7, 1, 1)
self.gbox2.addWidget(self.oil_radio, 6, 6, 1, 1)
self.gbox2.addWidget(self.dry_radio, 6, 7, 1, 1)
trafo_group.addButton(self.oil_radio, 0)
trafo_group.addButton(self.dry_radio, 1)
self.sheild_lbl = QtWidgets.QLabel("Sheilding & Twisting")
self.sheild_lbl.setFont(font_bld)
self.twist_reduction_lbl = QtWidgets.QLabel("Twist Reduction")
self.shield_chk = QtWidgets.QCheckBox("Shield Reduction")
self.twist_chk = QtWidgets.QCheckBox("Cable Twist")
self.mu_relative_lbl = QtWidgets.QLabel("µr Relative Permeability")
self.thickness_lbl = QtWidgets.QLabel("Thickness[m]")
self.distance_lbl = QtWidgets.QLabel("Distamce[m]")
self.twist_reduction_input = QtWidgets.QLineEdit("1")
self.mu_relative_input = QtWidgets.QLineEdit("100")
self.thickness_input = QtWidgets.QLineEdit("0.001")
self.distance_input = QtWidgets.QLineEdit("0.05")
self.gbox1.addWidget(self.sheild_lbl, 1, 7, 1, 2)
self.gbox1.addWidget(self.twist_reduction_lbl, 2, 7, 1, 1)
self.gbox1.addWidget(self.shield_chk, 3, 7, 1, 1)
self.gbox1.addWidget(self.twist_chk, 3, 8, 1, 1)
self.gbox1.addWidget(self.mu_relative_lbl, 4, 7, 1, 1)
self.gbox1.addWidget(self.thickness_lbl, 5, 7, 1, 1)
self.gbox1.addWidget(self.distance_lbl, 6, 7, 1, 1)
self.gbox1.addWidget(self.twist_reduction_input, 2, 8, 1, 1)
self.gbox1.addWidget(self.mu_relative_input, 4, 8, 1, 1)
self.gbox1.addWidget(self.thickness_input, 5, 8, 1, 1)
self.gbox1.addWidget(self.distance_input, 6, 8, 1, 1)
self.gbox1.setSpacing(10)
self.gbox2.setSpacing(10)
self.save_definition_btn = QtWidgets.QPushButton("Save Definition")
self.save_definition_btn.setFont(font)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.hbox4.addItem(spacerItem1)
self.hbox4.addWidget(self.load_defaults_btn)
self.hbox4.addItem(spacerItem1)
self.hbox4.addWidget(self.save_definition_btn)
self.hbox4.addItem(spacerItem1)
# =================================================
# Hbox6 Description
# =================================================
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\Panel.jpg")
self.img = QtWidgets.QLabel(self)
self.img.setPixmap(self.dev_img)
self.img.setScaledContents(False)
self.hbox6.addWidget(self.img)
# =================================================
# listbox
# =================================================
# row = 0
# self.hbox6.addWidget(self.listWidget)
# self.hbox1.addWidget(self.listWidget, row, 0, 1, 3) # col span=1, row span=3
# =================================================
# OK, Cancel
# =================================================
# row += 1
self.hbox7.addItem(spacerItem1)
self.but_ok = QPushButton("OK")
self.but_ok.setFont(font_bld)
self.hbox7.addWidget(self.but_ok)
self.but_ok.clicked.connect(self.OnOk)
self.hbox7.addItem(spacerItem1)
self.but_cancel = QPushButton("Cancel")
self.but_cancel.setFont(font_bld)
self.hbox7.addWidget(self.but_cancel)
self.but_cancel.clicked.connect(self.OnCancel)
self.hbox7.addItem(spacerItem1)
self.main_vbox = QtWidgets.QVBoxLayout()
self.main_vbox.addLayout(self.hbox1)
self.main_vbox.addLayout(self.hbox2)
self.main_vbox.addLayout(self.hbox3)
self.main_vbox.addLayout(self.gbox1)
self.main_vbox.addLayout(self.gbox2)
# self.main_vbox.addLayout(self.sheild_group_box)
self.main_vbox.addLayout(self.hbox4)
self.main_vbox.addLayout(self.hbox5)
self.main_vbox.addLayout(self.hbox6)
self.main_vbox.addLayout(self.hbox7)
self.setLayout(self.main_vbox)
# =================================================
#
# =================================================
self.setLayout(self.main_vbox)
self.setGeometry(300, 200, 500, 450)
self.element_selection_comboBox.currentIndexChanged.connect(self.element_cng)
self.oil_radio.clicked.connect(self.oil_trf)
self.dry_radio.clicked.connect(self.dry_trf)
self.power_input.editingFinished.connect(self.power_change)
self.voltage_input.editingFinished.connect(self.voltage_change)
self.typ_max_input.editingFinished.connect(self.typ_max_change)
self.imax_input.editingFinished.connect(self.imax_change)
self.ityp_input.editingFinished.connect(self.ityp_change)
def voltage_change(self):
if not self.is_number(self.voltage_input.text()):
QMessageBox.information(self, "Error", "The Voltage value is not a number!")
self.voltage_input.setText("220")
return
if float(self.voltage_input.text()) <= 0:
QMessageBox.information(self, "Error", "The Voltage value must be > 0 !")
self.voltage_input.setText("220")
return
def imax_change(self):
if not self.is_number(self.imax_input.text()):
QMessageBox.information(self, "Error", "The Imax value is not a number!")
self.imax_input.setText("100")
return
imax = float(self.imax_input.text())
if imax <= 0:
QMessageBox.information(self, "Error", "The Imax value must be > 0 !")
self.imax_input.setText("100")
return
typ_ratio = float(self.typ_max_input.text())
self.ityp_input.setText(str(round(imax * typ_ratio)))
def ityp_change(self):
if not self.is_number(self.ityp_input.text()):
QMessageBox.information(self, "Error", "The Ityp value is not a number!")
self.ityp_input.setText("60")
return
if float(self.ityp_input.text()) <= 0 or float(self.ityp_input.text()) > float(self.imax_input.text()):
QMessageBox.information(self, "Error", "The Ityp value must be < Imax !")
self.ityp_input.setText("60")
return
def typ_max_change(self):
if not self.is_number(self.typ_max_input.text()):
QMessageBox.information(self, "Error", "The typ/max Ratio value is not a number!")
self.typ_max_input.setText("0.6")
return
if float(self.typ_max_input.text()) > 1 or float(self.typ_max_input.text()) < 0.1:
QMessageBox.information(self, "Error", "The typ/max Ratio value must be 0.1 < X < 1 !")
self.typ_max_input.setText("0.6")
return
def power_change(self):
""" calculate the Imax """
if not self.is_number(self.power_input.text()):
QMessageBox.information(self, "Error", "The Power value is not a number!")
self.power_input.setText("1000")
return
if float(self.power_input.text()) <= 0:
QMessageBox.information(self, "Error", "The Power value must be > 0 !")
self.power_input.setText("1000")
return
element_type = self.element_selection_comboBox.currentIndex()
if element_type == 4 or element_type == 5: # Trafo only
power = float(self.power_input.text())
voltage = float(self.voltage_input.text())
imax = power * 1000/(3.0 * voltage) # kVA * 1000 /(3.0*220)
self.imax_input.setText(str(round(imax)))
typ_ratio = float(self.typ_max_input.text())
ityp = imax * typ_ratio
self.ityp_input.setText(str(round(ityp)))
def oil_trf(self):
self.d_input.setText("0.15")
def dry_trf(self):
self.d_input.setText("0.6")
def element_cng(self):
self.change_flag = True
element_type = self.element_selection_comboBox.currentIndex()
if element_type == 0:
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\Panel.jpg")
self.h_input.setText("1.8")
self.d_input.setText("0.15")
self.hc_input.setReadOnly(True)
self.dt_input.setReadOnly(True)
self.power_input.setReadOnly(True)
self.voltage_input.setReadOnly(True)
elif element_type == 1:
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\PanelCompact.jpg")
self.h_input.setText("1.8")
self.d_input.setText("0.15")
self.hc_input.setReadOnly(True)
self.dt_input.setReadOnly(True)
self.power_input.setReadOnly(True)
self.voltage_input.setReadOnly(True)
elif element_type == 2:
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\Cable4Wcompact.jpg")
self.h_input.setText("0")
self.d_input.setText("0.03")
self.power_input.setReadOnly(True)
self.voltage_input.setReadOnly(True)
elif element_type == 3:
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\Cable4Wflat.jpg")
self.h_input.setText("0")
self.d_input.setText("0.03")
self.power_input.setReadOnly(True)
self.voltage_input.setReadOnly(True)
elif element_type == 4:
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\TrafoLong.jpg")
self.power_input.setReadOnly(False)
self.voltage_input.setReadOnly(False)
self.hc_input.setReadOnly(False)
self.dt_input.setReadOnly(False)
self.h_input.setText("1.8")
self.hc_input.setText("1")
self.dt_input.setText("0.0")
self.length.setText("1.0")
if self.dry_radio.isChecked():
self.d_input.setText("0.6")
else:
self.d_input.setText("0.15")
elif element_type == 5:
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\TrafoBroad.jpg")
self.power_input.setReadOnly(False)
self.voltage_input.setReadOnly(False)
self.hc_input.setReadOnly(False)
self.dt_input.setReadOnly(False)
self.h_input.setText("1.8")
self.hc_input.setText("1")
self.dt_input.setText("0.0")
self.length.setText("1.0")
if self.dry_radio.isChecked():
self.d_input.setText("0.6")
else:
self.d_input.setText("0.15")
elif element_type == 6:
self.power_input.setReadOnly(True)
self.voltage_input.setReadOnly(True)
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\Cable2W.jpg")
self.d_input.setText("0.03")
elif element_type == 7:
self.power_input.setReadOnly(True)
self.voltage_input.setReadOnly(True)
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\Wire.jpg")
elif element_type == 8:
self.power_input.setReadOnly(True)
self.voltage_input.setReadOnly(True)
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\Cable2W.jpg")
elif element_type == 9:
self.power_input.setReadOnly(True)
self.voltage_input.setReadOnly(True)
self.dev_img = QtGui.QPixmap("C:\mfc\modelPic\Cable2W.jpg")
self.img.setPixmap(self.dev_img)
def OnSingleClick(self, item):
self.result = item.text()
def OnDoubleClick(self, item):
self.result = item.text()
self.close()
return self.result
def OnOk(self):
if self.result == "":
QMessageBox.information(self, "Error", "One item must be selected")
return
self.close()
return self.floor_data
# return self.result
def OnCancel(self):
self.close()
def GetValue(self):
# return self.result
return self.floor_data
def do_nothing(self):
print("nothing")
def is_number(self, s):
try:
float(s)
return True
except ValueError:
return False
The solution as you indicated is to use QButtonGroup, the problem is that your QButtonGroups is a local variable that will be eliminated when you finish executing the function, the solution is to pass a parent to the QButtonGroups so it will extend its scope.
...
direction_group = QtWidgets.QButtonGroup(self) # <--- pass the self as a parent
...
i_group = QtWidgets.QButtonGroup(self) # <--- pass the self as a parent
...
trafo_group = QtWidgets.QButtonGroup(self) # <--- pass the self as a parent
...