It is not possible to make the text crossed out in a separate cell. It turns out only to apply to everyone. Tried changing in model methods. Also applies to everyone. I looked for an example on the Internet, but it didn't work. The bottom line is for the user to select a cell, click on the button and the text in the cell becomes checked out.
My code
import sys
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
STRIKE_ROLE = Qt.UserRole + 1
import pandas as pd
class StrikeDelegate(QStyledItemDelegate):
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
font = QFont(option.font)
font.setStrikeOut(index.data(STRIKE_ROLE))
option.font = font
class MyDelegate(QItemDelegate):
def setEditorData(self, editor, index):
text = index.data(Qt.EditRole) or index.data(Qt.DisplayRole)
editor.setText(text)
# def initStyleOption(self,option,index):
#
# QtWidgets.QStyledItemDelegate.initStyleOption(option,index)
# option.font().setStrikeOut(True)
class TableModel(QAbstractTableModel):
def __init__(self, data):
super(TableModel, self).__init__()
self._data = data
def setData(self, index, value, role):
self._data.iloc[index.row(), index.column()] = value
self.dataChanged.emit(index, index)
return True
def flags(self, index):
return Qt.ItemIsEnabled | Qt.ItemIsEditable |Qt.ItemIsSelectable | Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled
def data(self, index, role):
if role == Qt.DisplayRole:
value = self._data.iloc[index.row(), index.column()]
return str(value)
def rename_column(self, index, new_name):
self._data.rename(index={self._data.index[index]: new_name}, inplace=True)
return True
def rowCount(self, index):
return self._data.shape[0]
def columnCount(self, index):
return self._data.shape[1]
def headerData(self, section, orientation, role):
# section is the index of the column/row.
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
return str(self._data.columns[section])
if orientation == Qt.Vertical:
return str(self._data.index[section])
def add_empty_row(self):
self.beginResetModel()
try:
self._data = self._data.append(
pd.DataFrame(columns=self._data.columns, data=([[0] * len(self._data.columns)]),
index=['Пусто']))
except IndexError:
self._data = self._data.append(
pd.DataFrame(columns=self._data.columns, data=([[None] * len(self._data.columns)]),
index=[0]))
self.layoutChanged.emit()
self.endResetModel()
# self.inp_.add_delete_row.emit(self.createIndex(self._data.index[-1], 0), 'add_empty_row')
def delete_row(self, index):
self._data.drop(self._data.index[index.row()], inplace=True)
# self._data.reset_index(inplace=True, drop=True)
self.layoutChanged.emit()
class TaskModel(TableModel):
def add_empty_row(self):
self.beginResetModel()
try:
self._data = self._data.append(
pd.DataFrame(columns=self._data.columns, data=([['Новая задача'] * len(self._data.columns)]),
index=[self._data.index[-1] + 1]))
except IndexError:
self._data = self._data.append(
pd.DataFrame(columns=self._data.columns, data=([[None] * len(self._data.columns)]),
index=[0]))
self.layoutChanged.emit()
self.endResetModel()
def data(self, index, role):
value = self._data.iloc[index.row(), index.column()]
if role == Qt.DisplayRole:
return str(value)
if role == STRIKE_ROLE:
font=QFont('Calibri',13)
return font
def setData(self, index, value, role):
self._data.iloc[index.row(), index.column()] = value
self.dataChanged.emit(index, index)
return True
class Ui_Form(object):
def setupUi(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
Form.resize(586, 683)
self.Form=Form
self.horizontalLayout_2 = QHBoxLayout(Form)
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.dock_task_calendar = QDockWidget(Form)
self.dock_task_calendar.setObjectName(u"dock_task_calendar")
self.dock_task_calendar.setFeatures(QDockWidget.DockWidgetClosable|QDockWidget.DockWidgetMovable)
self.dockWidgetContents_task = QWidget()
self.dockWidgetContents_task.setObjectName(u"dockWidgetContents_task")
self.verticalLayout_3 = QVBoxLayout(self.dockWidgetContents_task)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.scrollArea_task = QScrollArea(self.dockWidgetContents_task)
self.scrollArea_task.setObjectName(u"scrollArea_task")
self.scrollArea_task.setWidgetResizable(True)
self.scrollAreaWidgetContents_task_2 = QWidget()
self.scrollAreaWidgetContents_task_2.setObjectName(u"scrollAreaWidgetContents_task_2")
self.scrollAreaWidgetContents_task_2.setGeometry(QRect(0, 0, 548, 623))
self.horizontalLayout = QHBoxLayout(self.scrollAreaWidgetContents_task_2)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.gridLayout = QGridLayout()
self.gridLayout.setObjectName(u"gridLayout")
self.verticalLayout_2 = QVBoxLayout()
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.gridLayout.addLayout(self.verticalLayout_2, 4, 0, 1, 1)
self.tasklistView = QListView(self.scrollAreaWidgetContents_task_2)
self.tasklistView.setObjectName(u"tasklistView")
self.tasklistView.setDragEnabled(True)
self.tasklistView.setDragDropOverwriteMode(True)
self.tasklistView.setWordWrap(True)
self.tasklistView.setItemAlignment(Qt.AlignLeading)
self.gridLayout.addWidget(self.tasklistView, 4, 1, 1, 1)
self.model=TaskModel(pd.DataFrame([],columns=['a']))
self.delegater=MyDelegate()
self.tasklistView.setModel(self.model)
self.tasklistView.setItemDelegate(self.delegater)
self.label_task = QLabel(self.scrollAreaWidgetContents_task_2)
self.label_task.setObjectName(u"label_task")
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_task.sizePolicy().hasHeightForWidth())
self.label_task.setSizePolicy(sizePolicy)
self.label_task.setMaximumSize(QSize(16777215, 20))
self.label_task.setAlignment(Qt.AlignCenter)
self.gridLayout.addWidget(self.label_task, 2, 1, 1, 1)
self.calendar = QCalendarWidget(self.scrollAreaWidgetContents_task_2)
self.calendar.setObjectName(u"calendar")
sizePolicy1 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.calendar.sizePolicy().hasHeightForWidth())
self.calendar.setSizePolicy(sizePolicy1)
self.calendar.setMaximumSize(QSize(16777215, 400))
self.gridLayout.addWidget(self.calendar, 1, 1, 1, 1)
self.verticalLayout = QVBoxLayout()
self.verticalLayout.setObjectName(u"verticalLayout")
self.add_task = QPushButton(self.scrollAreaWidgetContents_task_2)
self.add_task.setObjectName(u"add_task")
sizePolicy2 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
sizePolicy2.setHorizontalStretch(0)
sizePolicy2.setVerticalStretch(0)
sizePolicy2.setHeightForWidth(self.add_task.sizePolicy().hasHeightForWidth())
self.add_task.setSizePolicy(sizePolicy2)
self.add_task.setMaximumSize(QSize(40, 40))
self.verticalLayout.addWidget(self.add_task)
self.del_task = QPushButton(self.scrollAreaWidgetContents_task_2)
self.del_task.setObjectName(u"del_task")
self.del_task.setMaximumSize(QSize(40, 40))
self.verticalLayout.addWidget(self.del_task)
self.check_task = QPushButton(self.scrollAreaWidgetContents_task_2)
self.check_task.setObjectName(u"check_task")
self.check_task.setMaximumSize(QSize(40, 40))
self.verticalLayout.addWidget(self.check_task)
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.verticalLayout.addItem(self.verticalSpacer)
self.gridLayout.addLayout(self.verticalLayout, 4, 2, 1, 1)
self.horizontalLayout.addLayout(self.gridLayout)
self.scrollArea_task.setWidget(self.scrollAreaWidgetContents_task_2)
self.verticalLayout_3.addWidget(self.scrollArea_task)
self.dock_task_calendar.setWidget(self.dockWidgetContents_task)
self.horizontalLayout_2.addWidget(self.dock_task_calendar)
self.add_task.pressed.connect(self.model.add_empty_row)
self.retranslateUi(Form)
self.Form.show()
# setupUi
def retranslateUi(self, Form):
Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
self.dock_task_calendar.setWindowTitle("")
self.label_task.setText(QCoreApplication.translate("Form", u"C\u043f\u0438\u0441\u043e\u043a \u0434\u0435\u043b/\u0437\u0430\u0434\u0430\u0447", None))
self.add_task.setText(QCoreApplication.translate("Form", u"PushButton", None))
self.del_task.setText(QCoreApplication.translate("Form", u"PushButton", None))
self.check_task.setText(QCoreApplication.translate("Form", u"PushButton", None))
# retranslateUi
if __name__ == '__main__':
app = QApplication(sys.argv)
translator = QTranslator()
if len(sys.argv) > 1:
locale = sys.argv[1]
else:
locale = QLocale.system().name()
translator.load('qt_%s' % locale,
QLibraryInfo.location(QLibraryInfo.TranslationsPath))
app.installTranslator(translator)
form=Ui_Form()
form.setupUi(QWidget())
app.exec_()
Since the OP has not provided an MRE then my solution will only limit the general logic which is:
Create a new role for each item where a boolean (or any other variable) is stored if the strike is applied.
Use a delegate to set the strike in the font.
With the clicked signal change the value stored in the role strike for selected rows.
from functools import cached_property
from PyQt5 import QtCore, QtGui, QtWidgets
STRIKE_ROLE = QtCore.Qt.UserRole + 1
class StrikeDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
font = QtGui.QFont(option.font)
font.setStrikeOut(index.data(STRIKE_ROLE))
option.font = font
def createEditor(self, parent, option, index):
editor = super().createEditor(parent, option, index)
font = QtGui.QFont(editor.font())
font.setStrikeOut(index.data(STRIKE_ROLE))
editor.setFont(font)
return editor
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
hlay = QtWidgets.QHBoxLayout(central_widget)
vlay = QtWidgets.QVBoxLayout()
vlay.addWidget(self.add_button)
vlay.addWidget(self.remove_button)
vlay.addWidget(self.strike_button)
vlay.addStretch()
hlay.addWidget(self.view)
hlay.addLayout(vlay)
self.add_button.clicked.connect(self.add)
self.remove_button.clicked.connect(self.remove)
self.strike_button.clicked.connect(self.strike)
#cached_property
def model(self):
return QtGui.QStandardItemModel()
#cached_property
def view(self):
view = QtWidgets.QListView()
delegate = StrikeDelegate()
view.setItemDelegate(delegate)
view.setModel(self.model)
return view
#cached_property
def add_button(self):
return QtWidgets.QPushButton("Add")
#cached_property
def remove_button(self):
return QtWidgets.QPushButton("Remove")
#cached_property
def strike_button(self):
return QtWidgets.QPushButton("Strike")
def add(self):
text, ok = QtWidgets.QInputDialog.getText(self, "Title", "Text:")
if not ok:
return
item = QtGui.QStandardItem(text)
item.setData(True, STRIKE_ROLE)
self.model.appendRow(item)
def remove(self):
rows = [index.row() for index in self.view.selectedIndexes()]
for row in sorted(rows, reverse=True):
self.model.takeRow(row)
def strike(self):
for index in self.view.selectedIndexes():
strike = self.model.data(index, STRIKE_ROLE)
self.model.setData(index, not strike, STRIKE_ROLE)
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Having three classes. Class Table QTableWidget and a signal and a function to get row numbers with click event. which transmit and send to two other classes. This part of script works as promising.
class Table(QtWidgets.QWidget):
rownumber = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(Table, self).__init__(parent)
self.tableWidget = QtWidgets.QTableWidget(0, 3)
self.tableWidget.cellClicked.connect(self.cellClick)
def cellClick(self, row, column):
self.rownumber.emit(row)
def currentrow(self):
return self.tableWidget.currentRow()
Second Combo class with QComboBox and a signal and two functions to send and transfer information to third class, that value in QComboBox is changed. To check if the signal is emitting, printing Signal emitted . This part of script seems also working fine, since print code is executed.
class Combo(QtWidgets.QWidget):
Toupdatedata = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(Combo, self).__init__(parent)
self.combo = QtWidgets.QComboBox()
self.combo.addItems(["1","2","3","4"])
self.combo.activated.connect(self.setdatastrength)
#QtCore.pyqtSlot(int)
def setdatastrength(self, index):
value = self.combo[index]
self.dataupdate()
def dataupdate(self):
self.Toupdatedata.emit()
print('Signal emitted')
def get_data(self):
return tuple([self.combo.currentText()])
Third class Tab with QTabWidget and two functions and a connection, first function recieves numbers of row from first class Table, second function should and supposed to run and execute, when index of combobox from second class Combo changes. Checking to see if it works printing a string text I am executing. But it does not work as expected?! When values of QComboBox changes, function updatedata() never runs!
class Tab(QtWidgets.QWidget):
def __init__(self, parent=None):
super( Tab, self).__init__()
self.tab = QtWidgets.QTabWidget()
self.Table = Table()
self.combo = [Combo(), Combo()]
self.datacombo = []
self.Row = 0
self.tab.addTab( self.Table, 'Tables')
self.Table.rownumber.connect(self.rowselected_tables)
self.combo[self.Row].Toupdatedata.connect(self.updatedata)
# Alternative calling function currentrow.
# self.combo[self.Table.currentrow()].Toupdatedata.connect(self.updatedata)
#QtCore.pyqtSlot(int)
def rowselected_tables(self, row):
self.Row = row
if row > 0:
self.Tab.addTab(self.combo[row], 'Combo')
a1 = self.combo[row].get_data()
self.datacombo[row] = a1
#QtCore.pyqtSlot()
def updatedata(self):
self.datacombo[self.Table.currentrow()] = self.combo[self.Table.currentrow()].get_data()
print('I am executing', self.datagroup)
I wonder, what's it I'm doing wrong?
UPDATE:
import sys
from PyQt5 import QtCore, QtWidgets, QtGui
class Table(QtWidgets.QWidget):
rownumber = QtCore.pyqtSignal(int)
rowCount = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(Table, self).__init__(parent)
self.tableWidget = QtWidgets.QTableWidget(3, 3)
self.lay = QtWidgets.QHBoxLayout(self)
self.lay.addWidget(self.tableWidget)
self.tableWidget.cellClicked.connect(self.cellClick)
def cellClick(self, row, column):
self.rownumber.emit(row)
def currentrow(self):
return self.tableWidget.currentRow()
def getrow(self):
count = self.tableWidget.rowCount()
self.rowCount.emit(count)
class Combo(QtWidgets.QWidget):
Toupdatedata = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(Combo, self).__init__(parent)
self.combo = QtWidgets.QComboBox()
self.combo.addItems(["1","2","3","4"])
self.hbox = QtWidgets.QHBoxLayout()
self.con = QtWidgets.QLabel("Number: ")
self.hbox.addWidget(self.con)
self.hbox.addWidget(self.combo)
self.setLayout(self.hbox)
self.combo.activated.connect(self.setdatastrength)
#QtCore.pyqtSlot(int)
def setdatastrength(self, index):
self.dataupdate()
def dataupdate(self):
self.Toupdatedata.emit()
print('Signal emitted')
def get_data(self):
return tuple([self.combo.currentText()])
class Tab(QtWidgets.QWidget):
def __init__(self, parent=None):
super( Tab, self).__init__()
self.tab = QtWidgets.QTabWidget()
self.Table = Table()
self.combo = []
self.datacombo = []
self.Row = 0
self.tab.addTab( self.Table, 'Tables')
self.Table.rowCount.connect(self.addrow)
self.Table.getrow()
self.Table.rownumber.connect(self.rowselected_tables)
self.combo[self.Row].Toupdatedata.connect(self.updatedata)
self.lay = QtWidgets.QHBoxLayout(self)
self.lay.addWidget(self.tab)
# Alternative calling function currentrow.
# self.combo[self.Table.currentrow()].Toupdatedata.connect(self.updatedata)
#QtCore.pyqtSlot(int)
def addrow(self, count):
for row in range(count):
self.combo.append(Combo())
self.datacombo.append(Combo().get_data())
#QtCore.pyqtSlot(int)
def rowselected_tables(self, row):
self.Row = row
if row > 0:
while self.tab.count() > 1:
self.tab.removeTab( self.tab.count()-1 )
self.tab.addTab(self.combo[row], 'Combo')
a1 = self.combo[row].get_data()
self.datacombo[row] = a1
else:
for n in [1]:
self.tab.removeTab( n )
#QtCore.pyqtSlot()
def updatedata(self):
self.datacombo[self.Table.currentrow()] = self.combo[self.Table.currentrow()].get_data()
print('I am executing', self.datagroup)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Tab()
w.show()
sys.exit(app.exec_())
In my opinion, you are connecting the signal self.combo[self.Row].Toupdatedata.connect (self.updatedata) in the wrong place.
I noted the text where the changes were made. Try it:
import sys
from PyQt5 import QtCore, QtWidgets, QtGui
class Table(QtWidgets.QWidget):
rownumber = QtCore.pyqtSignal(int)
rowCount = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(Table, self).__init__(parent)
self.tableWidget = QtWidgets.QTableWidget(3, 3)
self.lay = QtWidgets.QHBoxLayout(self)
self.lay.addWidget(self.tableWidget)
self.tableWidget.cellClicked.connect(self.cellClick)
def cellClick(self, row, column):
self.rownumber.emit(row)
def currentrow(self):
return self.tableWidget.currentRow()
def getrow(self):
count = self.tableWidget.rowCount()
self.rowCount.emit(count)
class Combo(QtWidgets.QWidget):
Toupdatedata = QtCore.pyqtSignal(int) # + int
def __init__(self, rowTable, parent=None): # + rowTable
super(Combo, self).__init__(parent)
self.rowTable = rowTable # +
## print(rowTable, '------')
self.combo = QtWidgets.QComboBox()
self.combo.addItems(["item1", "item2", "item3", "item4"])
self.hbox = QtWidgets.QHBoxLayout()
self.con = QtWidgets.QLabel("Number: ")
self.hbox.addWidget(self.con)
self.hbox.addWidget(self.combo)
self.setLayout(self.hbox)
self.combo.activated.connect(self.setdatastrength)
#QtCore.pyqtSlot(int)
def setdatastrength(self, index):
self.dataupdate()
def dataupdate(self):
print('+ Signal emitted ->', self.rowTable)
self.Toupdatedata.emit(self.rowTable) # + self.rowTable
def get_data(self):
return tuple([self.combo.currentText()])
class Tab(QtWidgets.QWidget):
def __init__(self, parent=None):
super( Tab, self).__init__()
self.tab = QtWidgets.QTabWidget()
self.Table = Table()
self.combo = []
self.datacombo = []
self.Row = 0
self.tab.addTab( self.Table, 'Tables')
self.Table.rowCount.connect(self.addrow)
self.Table.getrow()
self.Table.rownumber.connect(self.rowselected_tables)
#- self.combo[self.Row].Toupdatedata.connect(self.updatedata)
self.lay = QtWidgets.QHBoxLayout(self)
self.lay.addWidget(self.tab)
# Alternative calling function currentrow.
# ? self.combo[self.Table.currentrow()].Toupdatedata.connect(self.updatedata)
#QtCore.pyqtSlot(int)
def addrow(self, count):
for row in range(count):
cb = Combo(row) # + row
self.combo.append(cb)
self.datacombo.append(cb.get_data()[0]) # get_data()[0]
self.combo[row].Toupdatedata.connect(lambda rowTable=row: self.updatedata(rowTable)) # <===== !!!
#QtCore.pyqtSlot(int)
def rowselected_tables(self, row):
self.Row = row
if row > 0:
while self.tab.count() > 1:
self.tab.removeTab( self.tab.count()-1 )
self.tab.addTab(self.combo[row], 'Combo')
a1 = self.combo[row].get_data()[0] # + [0]
self.datacombo[row] = a1
else:
for n in [1]:
self.tab.removeTab( n )
#QtCore.pyqtSlot()
def updatedata(self, rowTable): # + rowTable
# self.datacombo[self.Table.currentrow()] = self.combo[self.Table.currentrow()].get_data()
self.datacombo[rowTable] = self.combo[rowTable].get_data()[0] # [0]
print('I am executing', self.datacombo ) # ? self.datagroup
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Tab()
w.show()
sys.exit(app.exec_())
I am trying to build a layout using PySide and I have run into a situation where I would like to keep a widget group in a separate class and call it dynamically.
I looked at few examples from this site which sort of gives me an idea but still I am not able to resolve this issue on my own. Here is the sample code of the layout I am building and it will be very helpful if someone can help me solve this issue.
-Thanks in advance
import PySide2.QtCore as QtCore
import PySide2.QtGui as QtGui
import PySide2.QtWidgets as QtGuiWidgets
class TabDialog(QtGuiWidgets.QDialog):
def __init__(self, parent=None):
super(TabDialog, self).__init__(parent)
argument = "Temp"
calldisplay = display_elements()
tabWidget = QtGuiWidgets.QTabWidget()
tabWidget.addTab(tab1(argument), "tab1")
tabWidget.addTab(tab2(argument), "tab2")
buttonBox = QtGuiWidgets.QDialogButtonBox(
QtGuiWidgets.QDialogButtonBox.Ok | QtGuiWidgets.QDialogButtonBox.Cancel)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
mainLayout = QtGuiWidgets.QVBoxLayout()
mainLayout.addWidget(tabWidget)
mainLayout.addWidget(buttonBox)
self.setLayout(mainLayout)
self.setWindowTitle("Load All Elements")
self.show()
class tab1(QtGuiWidgets.QWidget):
def __init__(self, calldisplay, parent=None):
super(tab1, self).__init__(parent)
self.layerfilterGroup = QtGuiWidgets.QLabel("Filter 1")
self.peopleGroup = QtGuiWidgets.QGroupBox("Filter 2")
self.dateGroup = QtGuiWidgets.QGroupBox("Filter 3")
self.loadGroup = QtGuiWidgets.QLabel("Load elements")
self.filterGroup = QtGuiWidgets.QGroupBox("Filters")
self.filterGroup.setGeometry(100, 100, 700, 550)
self.filterLayout = QtGuiWidgets.QVBoxLayout()
for key in range(15):
self.btn = QtGuiWidgets.QCheckBox(str(key))
self.btn.setChecked(True)
self.filterLayout.addWidget(self.btn)
self.filterGroup.setLayout(self.filterLayout)
self.filterscroll = QtGuiWidgets.QScrollArea()
self.fslayout = QtGuiWidgets.QVBoxLayout()
self.filterscroll.setWidget(self.filterGroup)
self.fslayout.addWidget(self.filterscroll)
self.artist = ["All", "N/A", "N/A", "N/A"]
self.acombos = QtGuiWidgets.QComboBox()
self.acombos.addItems(self.artist)
self.all_label = QtGuiWidgets.QLabel()
self.all_label.setText('All')
self.all_label.setGeometry(160, 40, 80, 30)
self.late_label = QtGuiWidgets.QLabel()
self.late_label.setText('Latest')
self.late_label.setGeometry(160, 40, 80, 30)
self.dslider = QtGuiWidgets.QSlider(QtCore.Qt.Horizontal, self)
self.artistlayout = QtGuiWidgets.QVBoxLayout()
self.artistlayout.addWidget(self.acombos)
self.peopleGroup.setLayout(self.artistlayout)
self.datelayout = QtGuiWidgets.QHBoxLayout()
self.datelayout.addWidget(self.all_label)
self.datelayout.addWidget(self.dslider)
self.datelayout.addWidget(self.late_label)
self.dateGroup.setLayout(self.datelayout)
self.rgroup = QtGuiWidgets.QGroupBox("Elements")
self.rgroup.setGeometry(100, 100, 700, 750)
self.rlayout = QtGuiWidgets.QVBoxLayout()
########## This is Working###############
for key in range(15):
self.btn = QtGuiWidgets.QCheckBox(str(key))
self.btn.setChecked(True)
self.rlayout.addWidget(self.btn)
self.rgroup.setLayout(self.rlayout)
############ want to do it this way############
#self.rlayout.addWidget(calldisplay)
#self.rgroup.setLayout(self.rlayout)
self.rscroll = QtGuiWidgets.QScrollArea()
self.rlayout = QtGuiWidgets.QVBoxLayout()
self.rscroll.setWidget(self.rgroup)
self.rlayout.addWidget(self.rscroll)
self.mainLayout = QtGuiWidgets.QVBoxLayout()
self.mainLayout.addWidget(self.layerfilterGroup)
self.mainLayout.addWidget(self.filterscroll)
self.mainLayout.addWidget(self.peopleGroup)
self.mainLayout.addWidget(self.dateGroup)
self.mainLayout.addWidget(self.loadGroup)
self.mainLayout.addWidget(self.rscroll)
self.setLayout(self.mainLayout)
##### call this class dynamically######
class display_elements(QtGuiWidgets.QWidget):
def __init__(self, parent=None):
super(display_elements, self).__init__(parent)
self.rgroup = QtGuiWidgets.QGroupBox("Available Elements")
self.rgroup.setGeometry(400, 400, 700, 750)
self.rlayout = QtGuiWidgets.QVBoxLayout()
for key in range(15):
self.btn = QtGuiWidgets.QCheckBox(str(key))
self.btn.setChecked(True)
self.rlayout.addWidget(self.btn)
self.rgroup.setLayout(self.rlayout)
class tab2(QtGuiWidgets.QWidget):
def __init__(self, fileInfo, parent=None):
super(tab2, self).__init__(parent)
ex = TabDialog()
One of the errors I see is that you point as the first argument of tab1 to calldisplay that I guess is the widget you want to set but you are passing it as an argument to "argument" which is a string, so a first change is to change it .
On the other hand if you are going to use layouts forget about setGeometry() since now the geometry is handled by the QLayouts.
And finally, your display_elements class is not implemented correctly since the rgroup is not added to the widget and for this you must use a layout.
Considering the above, the solution is the following:
import PySide2.QtCore as QtCore
import PySide2.QtGui as QtGui
import PySide2.QtWidgets as QtGuiWidgets
class TabDialog(QtGuiWidgets.QDialog):
def __init__(self, parent=None):
super(TabDialog, self).__init__(parent)
argument = "Temp"
calldisplay = display_elements()
tabWidget = QtGuiWidgets.QTabWidget()
tabWidget.addTab(tab1(calldisplay), "tab1")
tabWidget.addTab(tab2(argument), "tab2")
buttonBox = QtGuiWidgets.QDialogButtonBox(
QtGuiWidgets.QDialogButtonBox.Ok | QtGuiWidgets.QDialogButtonBox.Cancel)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
mainLayout = QtGuiWidgets.QVBoxLayout()
mainLayout.addWidget(tabWidget)
mainLayout.addWidget(buttonBox)
self.setLayout(mainLayout)
self.setWindowTitle("Load All Elements")
self.show()
class tab1(QtGuiWidgets.QWidget):
def __init__(self, calldisplay, parent=None):
super(tab1, self).__init__(parent)
self.layerfilterGroup = QtGuiWidgets.QLabel("Filter 1")
self.peopleGroup = QtGuiWidgets.QGroupBox("Filter 2")
self.dateGroup = QtGuiWidgets.QGroupBox("Filter 3")
self.loadGroup = QtGuiWidgets.QLabel("Load elements")
self.filterGroup = QtGuiWidgets.QGroupBox("Filters")
self.filterGroup.setGeometry(100, 100, 700, 550)
self.filterLayout = QtGuiWidgets.QVBoxLayout()
for key in range(15):
self.btn = QtGuiWidgets.QCheckBox(str(key))
self.btn.setChecked(True)
self.filterLayout.addWidget(self.btn)
self.filterGroup.setLayout(self.filterLayout)
self.filterscroll = QtGuiWidgets.QScrollArea()
self.fslayout = QtGuiWidgets.QVBoxLayout()
self.filterscroll.setWidget(self.filterGroup)
self.fslayout.addWidget(self.filterscroll)
self.artist = ["All", "N/A", "N/A", "N/A"]
self.acombos = QtGuiWidgets.QComboBox()
self.acombos.addItems(self.artist)
self.all_label = QtGuiWidgets.QLabel()
self.all_label.setText('All')
self.all_label.setGeometry(160, 40, 80, 30)
self.late_label = QtGuiWidgets.QLabel()
self.late_label.setText('Latest')
self.late_label.setGeometry(160, 40, 80, 30)
self.dslider = QtGuiWidgets.QSlider(QtCore.Qt.Horizontal, self)
self.artistlayout = QtGuiWidgets.QVBoxLayout()
self.artistlayout.addWidget(self.acombos)
self.peopleGroup.setLayout(self.artistlayout)
self.datelayout = QtGuiWidgets.QHBoxLayout()
self.datelayout.addWidget(self.all_label)
self.datelayout.addWidget(self.dslider)
self.datelayout.addWidget(self.late_label)
self.dateGroup.setLayout(self.datelayout)
self.rgroup = QtGuiWidgets.QGroupBox("Elements")
self.rlayout = QtGuiWidgets.QVBoxLayout()
self.rlayout.addWidget(calldisplay)
self.rgroup.setLayout(self.rlayout)
self.rscroll = QtGuiWidgets.QScrollArea()
self.rlayout = QtGuiWidgets.QVBoxLayout()
self.rscroll.setWidget(self.rgroup)
self.rlayout.addWidget(self.rscroll)
self.mainLayout = QtGuiWidgets.QVBoxLayout()
self.mainLayout.addWidget(self.layerfilterGroup)
self.mainLayout.addWidget(self.filterscroll)
self.mainLayout.addWidget(self.peopleGroup)
self.mainLayout.addWidget(self.dateGroup)
self.mainLayout.addWidget(self.loadGroup)
self.mainLayout.addWidget(self.rscroll)
self.setLayout(self.mainLayout)
class display_elements(QtGuiWidgets.QWidget):
def __init__(self, parent=None):
super(display_elements, self).__init__(parent)
self.rgroup = QtGuiWidgets.QGroupBox("Available Elements")
lay = QtGuiWidgets.QVBoxLayout()
for key in range(15):
btn = QtGuiWidgets.QCheckBox(str(key))
btn.setChecked(True)
lay.addWidget(btn)
rlayout = QtGuiWidgets.QVBoxLayout(self)
rlayout.setContentsMargins(0, 0, 0, 0)
rlayout.addWidget(self.rgroup)
self.rgroup.setLayout(lay)
class tab2(QtGuiWidgets.QWidget):
def __init__(self, fileInfo, parent=None):
super(tab2, self).__init__(parent)
if __name__ == '__main__':
import sys
app = QtGuiWidgets.QApplication(sys.argv)
ex = TabDialog()
ex.show()
sys.exit(app.exec_())
I've created a widget with contents of 3 QGroupbox, I am trying to place and align them respectively with QGridLayout. Strange behaviour of QGroupboxsmakes this question.
What looks like currently.
As shown above figure when Qwidget screen stretchs in and out, Every group overlap each other and by outstretching replaces strangely and unwanted.
What I want to be....
By stretching in want all groups keeping its own position Fixed and scrollbar would appear instead.
The code is:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class ClassWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ClassWidget, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 670, 360))
self.A = ClassA()
self.B = ClassB()
self.C = ClassC()
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.A, 0, 0)
grid.addWidget(self.B, 0, 1, 1, 2)
grid.addWidget(self.C, 1, 0, 1, 2)
class ClassA(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ClassA, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.c_lay = QtWidgets.QHBoxLayout()
fctd = "One\n\nTwo\n\nThree"
con_strength = QtWidgets.QLabel(fctd)
self.value = QtWidgets.QLineEdit('Test')
self.c_lay.addWidget(con_strength)
self.c_lay.addWidget(self.value, alignment=QtCore.Qt.AlignRight)
self.combo = QtWidgets.QComboBox()
self.combo.addItems(["10","12","14","16"])
self.hbox = QtWidgets.QHBoxLayout()
self.con = QtWidgets.QLabel("Number: ")
self.hbox.addWidget(self.con)
self.hbox.addWidget(self.combo)
self.vlay = QtWidgets.QVBoxLayout()
self.vlay.addLayout(self.hbox)
self.vlay.addLayout(self.c_lay)
self.vlay.addStretch()
Concrete_Group = QtWidgets.QGroupBox(self)
Concrete_Group.setTitle("&GroupA")
Concrete_Group.setLayout(self.vlay)
self.comth = ["10","12","14","16"]
self.combo.activated.connect(self.setdatastrength)
#QtCore.pyqtSlot(int)
def setdatastrength(self, index):
value = self.comth[index]
self.display_data(value)
def display_data(self, value):
try:
f = value
f_value = "{}"
self.value.setText(f_value.format(f))
except ValueError:
print("Error")
class ClassB(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ClassB, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.combo_exclass = QtWidgets.QComboBox()
self.combo_exclass.addItems([" Very dry area"," Dry or permanently
wet"," Wet, rarely dry"," Moderate humidity"," Tidal splash & spray
zones"])
self.combo_lclass = QtWidgets.QComboBox()
self.combo_lclass.addItems(["L2","L4","L6","L8"])
self.combo_vct = QtWidgets.QComboBox()
self.combo_vct.addItems(["0.10","0.20","0.30","0.40",
"0.50","0.60","0.70"])
self.combo_in = QtWidgets.QComboBox()
self.combo_in.addItems(["Class1","Class2","Class3"])
self.tbox = QtWidgets.QHBoxLayout()
self.exclass = QtWidgets.QLabel("Class1: ")
self.tbox.addWidget(self.exclass)
self.tbox.addWidget(self.combo_exclass)
self.mtbox = QtWidgets.QHBoxLayout()
self.lclass = QtWidgets.QLabel("Class2: ")
self.mtbox.addWidget(self.lclass)
self.mtbox.addWidget(self.combo_lclass)
self.mbbox = QtWidgets.QHBoxLayout()
self.vct = QtWidgets.QLabel("Class3: ")
self.mbbox.addWidget(self.vct)
self.mbbox.addWidget(self.combo_vct)
self.bbox = QtWidgets.QHBoxLayout()
self.inl = QtWidgets.QLabel("Class4: ")
self.bbox.addWidget(self.inl)
self.bbox.addWidget(self.combo_in)
self.grid = QtWidgets.QGridLayout()
self.grid.addLayout(self.tbox, 0, 0, 1, 2)
self.grid.addLayout(self.mtbox, 1, 0)
self.grid.addLayout(self.mbbox, 2, 0)
self.grid.addLayout(self.bbox, 3, 0)
Environment_Group = QtWidgets.QGroupBox(self)
Environment_Group.setTitle("&Group2")
Environment_Group.setLayout(self.grid)
class ClassC(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ClassC, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.topone = QtWidgets.QComboBox()
self.topone.addItems(["One","Two","Three","four"])
self.longitudinalone = QtWidgets.QComboBox()
self.longitudinalone.addItems(["One","Two","Three","four"])
self.bottomone = QtWidgets.QComboBox()
self.bottomone.addItems(["One","Two","Three","four"])
self.stirrupone = QtWidgets.QComboBox()
self.stirrupone.addItems(["One","Two","Three","four"])
self.toprebar = QtWidgets.QComboBox()
self.toprebar.addItems(["1","2","3","4","5","6","7","8","9"])
self.longitudinalrebar = QtWidgets.QComboBox()
self.longitudinalrebar.addItems(["1","2","3","4","5","6",
"7","8","9"])
self.bottomrebar = QtWidgets.QComboBox()
self.bottomrebar.addItems(["1","2","3","4","5","6","7","8","9"])
self.stirruprebar = QtWidgets.QComboBox()
self.stirruprebar.addItems(["1","2","3","4","5","6","7","8","9"])
self.rebarbox = QtWidgets.QVBoxLayout()
self.topvoid = QtWidgets.QLabel(" ")
self.top = QtWidgets.QLabel("One: ")
self.longitudinal = QtWidgets.QLabel("Two: ")
self.bottom = QtWidgets.QLabel("Three: ")
self.stirrup = QtWidgets.QLabel("Four: ")
self.rebarbox.addWidget(self.topvoid)
self.rebarbox.addWidget(self.top)
self.rebarbox.addWidget(self.longitudinal)
self.rebarbox.addWidget(self.bottom)
self.rebarbox.addWidget(self.stirrup)
self.typebox = QtWidgets.QVBoxLayout()
self.type = QtWidgets.QLabel("Type ")
self.typebox.addWidget(self.type, alignment=QtCore.Qt.AlignCenter)
self.typebox.addWidget(self.topone)
self.typebox.addWidget(self.longitudinalone)
self.typebox.addWidget(self.bottomone)
self.typebox.addWidget(self.stirrupone)
self.Reinforcebox = QtWidgets.QVBoxLayout()
self.Reinforcement = QtWidgets.QLabel("One, One")
self.Reinforcebox.addWidget(self.Reinforcement)
self.Reinforcebox.addWidget(self.toprebar)
self.Reinforcebox.addWidget(self.longitudinalrebar)
self.Reinforcebox.addWidget(self.bottomrebar)
self.Reinforcebox.addWidget(self.stirruprebar)
self.designstrengthbox = QtWidgets.QVBoxLayout()
self.designsteelstrength = QtWidgets.QLabel("Four")
self.topsteelstrength = QtWidgets.QLabel("")
self.longsteelstrength = QtWidgets.QLabel("")
self.bottompsteelstrength = QtWidgets.QLabel("")
self.stirrupsteelstrength = QtWidgets.QLabel("")
self.designstrengthbox.addWidget(self.designsteelstrength)
self.designstrengthbox.addWidget(self.topsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.designstrengthbox.addWidget(self.longsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.designstrengthbox.addWidget(self.bottompsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.designstrengthbox.addWidget(self.stirrupsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.sbox = QtWidgets.QVBoxLayout()
self.anytext = QtWidgets.QLabel("Any text")
self.value = QtWidgets.QLabel("Any")
self.value1 = QtWidgets.QLabel("Any")
self.value2 = QtWidgets.QLabel("Any")
self.value3 = QtWidgets.QLabel("Any")
self.sbox.addWidget(self.anytext)
self.sbox.addWidget(self.value)
self.sbox.addWidget(self.value1)
self.sbox.addWidget(self.value2)
self.sbox.addWidget(self.value3)
self.hlay = QtWidgets.QHBoxLayout()
self.hlay.addStretch()
self.hlay.addLayout(self.rebarbox)
self.hlay.addLayout(self.typebox)
self.hlay.addLayout(self.Reinforcebox)
self.hlay.addLayout(self.designstrengthbox)
self.hlay.addLayout(self.sbox)
self.hlay.addStretch()
Concrete_Group = QtWidgets.QGroupBox(self)
Concrete_Group.setTitle("&GroupC")
Concrete_Group.setLayout(self.hlay)
self.rebarstrength = ["1","2","3","4"]
self.topone.activated.connect(self.setdatatopstrength)
#QtCore.pyqtSlot(int)
def setdatatopstrength(self, index):
value = self.rebarstrength[index]
self.display_topsteeldata(value)
#QtCore.pyqtSlot(int)
def display_topsteeldata(self, value):
try:
gammas = 1.15
fyd = int(float(value)/gammas)
fmt = "{}"
self.topsteelstrength.setText(fmt.format(str(fyd)))
except ValueError:
print("Error")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = ClassWidget()
w.show()
sys.exit(app.exec_())
The problem is simple, the groupboxes that are inside ClassA, ClassB and ClassC are just children and therefore the minimunSizeHint() of ClassA, ClassB and ClassC is (0, 0). For example, we show classA:
So there are 2 solutions:
1. The first is to establish a layout for ClassA, ClassB and ClassC classes, for example:
...
Concrete_Group = QtWidgets.QGroupBox()
Concrete_Group.setTitle("&GroupA")
Concrete_Group.setLayout(self.vlay)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(Concrete_Group)
...
Complete code:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class ClassWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ClassWidget, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 670, 360))
self.A = ClassA()
self.B = ClassB()
self.C = ClassC()
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.A, 0, 0)
grid.addWidget(self.B, 0, 1, 1, 2)
grid.addWidget(self.C, 1, 0, 1, 2)
class ClassA(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ClassA, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.c_lay = QtWidgets.QHBoxLayout()
fctd = "One\n\nTwo\n\nThree"
con_strength = QtWidgets.QLabel(fctd)
self.value = QtWidgets.QLineEdit('Test')
self.c_lay.addWidget(con_strength)
self.c_lay.addWidget(self.value, alignment=QtCore.Qt.AlignRight)
self.combo = QtWidgets.QComboBox()
self.combo.addItems(["10","12","14","16"])
self.hbox = QtWidgets.QHBoxLayout()
self.con = QtWidgets.QLabel("Number: ")
self.hbox.addWidget(self.con)
self.hbox.addWidget(self.combo)
self.vlay = QtWidgets.QVBoxLayout()
self.vlay.addLayout(self.hbox)
self.vlay.addLayout(self.c_lay)
self.vlay.addStretch()
Concrete_Group = QtWidgets.QGroupBox()
Concrete_Group.setTitle("&GroupA")
Concrete_Group.setLayout(self.vlay)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(Concrete_Group)
self.comth = ["10","12","14","16"]
self.combo.activated.connect(self.setdatastrength)
#QtCore.pyqtSlot(int)
def setdatastrength(self, index):
value = self.comth[index]
self.display_data(value)
def display_data(self, value):
try:
f = value
f_value = "{}"
self.value.setText(f_value.format(f))
except ValueError:
print("Error")
class ClassB(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ClassB, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.combo_exclass = QtWidgets.QComboBox()
self.combo_exclass.addItems([" Very dry area"," Dry or permanently wet"," Wet, rarely dry"," Moderate humidity"," Tidal splash & spray zones"])
self.combo_lclass = QtWidgets.QComboBox()
self.combo_lclass.addItems(["L2","L4","L6","L8"])
self.combo_vct = QtWidgets.QComboBox()
self.combo_vct.addItems(["0.10","0.20","0.30","0.40",
"0.50","0.60","0.70"])
self.combo_in = QtWidgets.QComboBox()
self.combo_in.addItems(["Class1","Class2","Class3"])
self.tbox = QtWidgets.QHBoxLayout()
self.exclass = QtWidgets.QLabel("Class1: ")
self.tbox.addWidget(self.exclass)
self.tbox.addWidget(self.combo_exclass)
self.mtbox = QtWidgets.QHBoxLayout()
self.lclass = QtWidgets.QLabel("Class2: ")
self.mtbox.addWidget(self.lclass)
self.mtbox.addWidget(self.combo_lclass)
self.mbbox = QtWidgets.QHBoxLayout()
self.vct = QtWidgets.QLabel("Class3: ")
self.mbbox.addWidget(self.vct)
self.mbbox.addWidget(self.combo_vct)
self.bbox = QtWidgets.QHBoxLayout()
self.inl = QtWidgets.QLabel("Class4: ")
self.bbox.addWidget(self.inl)
self.bbox.addWidget(self.combo_in)
self.grid = QtWidgets.QGridLayout()
self.grid.addLayout(self.tbox, 0, 0, 1, 2)
self.grid.addLayout(self.mtbox, 1, 0)
self.grid.addLayout(self.mbbox, 2, 0)
self.grid.addLayout(self.bbox, 3, 0)
Environment_Group = QtWidgets.QGroupBox()
Environment_Group.setTitle("&Group2")
Environment_Group.setLayout(self.grid)
vlay = QtWidgets.QVBoxLayout(self)
vlay.addWidget(Environment_Group)
class ClassC(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ClassC, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.topone = QtWidgets.QComboBox()
self.topone.addItems(["One","Two","Three","four"])
self.longitudinalone = QtWidgets.QComboBox()
self.longitudinalone.addItems(["One","Two","Three","four"])
self.bottomone = QtWidgets.QComboBox()
self.bottomone.addItems(["One","Two","Three","four"])
self.stirrupone = QtWidgets.QComboBox()
self.stirrupone.addItems(["One","Two","Three","four"])
self.toprebar = QtWidgets.QComboBox()
self.toprebar.addItems(["1","2","3","4","5","6","7","8","9"])
self.longitudinalrebar = QtWidgets.QComboBox()
self.longitudinalrebar.addItems(["1","2","3","4","5","6",
"7","8","9"])
self.bottomrebar = QtWidgets.QComboBox()
self.bottomrebar.addItems(["1","2","3","4","5","6","7","8","9"])
self.stirruprebar = QtWidgets.QComboBox()
self.stirruprebar.addItems(["1","2","3","4","5","6","7","8","9"])
self.rebarbox = QtWidgets.QVBoxLayout()
self.topvoid = QtWidgets.QLabel(" ")
self.top = QtWidgets.QLabel("One: ")
self.longitudinal = QtWidgets.QLabel("Two: ")
self.bottom = QtWidgets.QLabel("Three: ")
self.stirrup = QtWidgets.QLabel("Four: ")
self.rebarbox.addWidget(self.topvoid)
self.rebarbox.addWidget(self.top)
self.rebarbox.addWidget(self.longitudinal)
self.rebarbox.addWidget(self.bottom)
self.rebarbox.addWidget(self.stirrup)
self.typebox = QtWidgets.QVBoxLayout()
self.type = QtWidgets.QLabel("Type ")
self.typebox.addWidget(self.type, alignment=QtCore.Qt.AlignCenter)
self.typebox.addWidget(self.topone)
self.typebox.addWidget(self.longitudinalone)
self.typebox.addWidget(self.bottomone)
self.typebox.addWidget(self.stirrupone)
self.Reinforcebox = QtWidgets.QVBoxLayout()
self.Reinforcement = QtWidgets.QLabel("One, One")
self.Reinforcebox.addWidget(self.Reinforcement)
self.Reinforcebox.addWidget(self.toprebar)
self.Reinforcebox.addWidget(self.longitudinalrebar)
self.Reinforcebox.addWidget(self.bottomrebar)
self.Reinforcebox.addWidget(self.stirruprebar)
self.designstrengthbox = QtWidgets.QVBoxLayout()
self.designsteelstrength = QtWidgets.QLabel("Four")
self.topsteelstrength = QtWidgets.QLabel()
self.longsteelstrength = QtWidgets.QLabel()
self.bottompsteelstrength = QtWidgets.QLabel()
self.stirrupsteelstrength = QtWidgets.QLabel()
self.designstrengthbox.addWidget(self.designsteelstrength)
self.designstrengthbox.addWidget(self.topsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.designstrengthbox.addWidget(self.longsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.designstrengthbox.addWidget(self.bottompsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.designstrengthbox.addWidget(self.stirrupsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.sbox = QtWidgets.QVBoxLayout()
self.anytext = QtWidgets.QLabel("Any text")
self.value = QtWidgets.QLabel("Any")
self.value1 = QtWidgets.QLabel("Any")
self.value2 = QtWidgets.QLabel("Any")
self.value3 = QtWidgets.QLabel("Any")
self.sbox.addWidget(self.anytext)
self.sbox.addWidget(self.value)
self.sbox.addWidget(self.value1)
self.sbox.addWidget(self.value2)
self.sbox.addWidget(self.value3)
self.hlay = QtWidgets.QHBoxLayout()
self.hlay.addStretch()
self.hlay.addLayout(self.rebarbox)
self.hlay.addLayout(self.typebox)
self.hlay.addLayout(self.Reinforcebox)
self.hlay.addLayout(self.designstrengthbox)
self.hlay.addLayout(self.sbox)
self.hlay.addStretch()
Concrete_Group = QtWidgets.QGroupBox()
Concrete_Group.setTitle("&GroupC")
Concrete_Group.setLayout(self.hlay)
self.rebarstrength = ["1","2","3","4"]
self.topone.activated.connect(self.setdatatopstrength)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(Concrete_Group)
#QtCore.pyqtSlot(int)
def setdatatopstrength(self, index):
value = self.rebarstrength[index]
self.display_topsteeldata(value)
#QtCore.pyqtSlot(int)
def display_topsteeldata(self, value):
try:
gammas = 1.15
fyd = int(float(value)/gammas)
fmt = "{}"
self.topsteelstrength.setText(fmt.format(str(fyd)))
except ValueError:
print("Error")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = ClassWidget()
w.show()
sys.exit(app.exec_())
2. Or classA, class and class are inherited from QGroubBox, for this you can, for example, do the following:
class ClassA(QtWidgets.QGroupBox):
def __init__(self, parent=None):
super(ClassA, self).__init__(parent)
...
self.setTitle("&GroupA")
self.setLayout(self.vlay)
...
Complete code:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class ClassWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ClassWidget, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 670, 360))
self.A = ClassA()
self.B = ClassB()
self.C = ClassC()
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.A, 0, 0)
grid.addWidget(self.B, 0, 1, 1, 2)
grid.addWidget(self.C, 1, 0, 1, 2)
class ClassA(QtWidgets.QGroupBox):
def __init__(self, parent=None):
super(ClassA, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.c_lay = QtWidgets.QHBoxLayout()
fctd = "One\n\nTwo\n\nThree"
con_strength = QtWidgets.QLabel(fctd)
self.value = QtWidgets.QLineEdit('Test')
self.c_lay.addWidget(con_strength)
self.c_lay.addWidget(self.value, alignment=QtCore.Qt.AlignRight)
self.combo = QtWidgets.QComboBox()
self.combo.addItems(["10","12","14","16"])
self.hbox = QtWidgets.QHBoxLayout()
self.con = QtWidgets.QLabel("Number: ")
self.hbox.addWidget(self.con)
self.hbox.addWidget(self.combo)
self.vlay = QtWidgets.QVBoxLayout()
self.vlay.addLayout(self.hbox)
self.vlay.addLayout(self.c_lay)
self.vlay.addStretch()
self.setTitle("&GroupA")
self.setLayout(self.vlay)
self.comth = ["10","12","14","16"]
self.combo.activated.connect(self.setdatastrength)
#QtCore.pyqtSlot(int)
def setdatastrength(self, index):
value = self.comth[index]
self.display_data(value)
def display_data(self, value):
try:
f = value
f_value = "{}"
self.value.setText(f_value.format(f))
except ValueError:
print("Error")
class ClassB(QtWidgets.QGroupBox):
def __init__(self, parent=None):
super(ClassB, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.combo_exclass = QtWidgets.QComboBox()
self.combo_exclass.addItems([" Very dry area"," Dry or permanently wet"," Wet, rarely dry"," Moderate humidity"," Tidal splash & spray zones"])
self.combo_lclass = QtWidgets.QComboBox()
self.combo_lclass.addItems(["L2","L4","L6","L8"])
self.combo_vct = QtWidgets.QComboBox()
self.combo_vct.addItems(["0.10","0.20","0.30","0.40",
"0.50","0.60","0.70"])
self.combo_in = QtWidgets.QComboBox()
self.combo_in.addItems(["Class1","Class2","Class3"])
self.tbox = QtWidgets.QHBoxLayout()
self.exclass = QtWidgets.QLabel("Class1: ")
self.tbox.addWidget(self.exclass)
self.tbox.addWidget(self.combo_exclass)
self.mtbox = QtWidgets.QHBoxLayout()
self.lclass = QtWidgets.QLabel("Class2: ")
self.mtbox.addWidget(self.lclass)
self.mtbox.addWidget(self.combo_lclass)
self.mbbox = QtWidgets.QHBoxLayout()
self.vct = QtWidgets.QLabel("Class3: ")
self.mbbox.addWidget(self.vct)
self.mbbox.addWidget(self.combo_vct)
self.bbox = QtWidgets.QHBoxLayout()
self.inl = QtWidgets.QLabel("Class4: ")
self.bbox.addWidget(self.inl)
self.bbox.addWidget(self.combo_in)
self.grid = QtWidgets.QGridLayout()
self.grid.addLayout(self.tbox, 0, 0, 1, 2)
self.grid.addLayout(self.mtbox, 1, 0)
self.grid.addLayout(self.mbbox, 2, 0)
self.grid.addLayout(self.bbox, 3, 0)
self.setTitle("&Group2")
self.setLayout(self.grid)
class ClassC(QtWidgets.QGroupBox):
def __init__(self, parent=None):
super(ClassC, self).__init__(parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
self.topone = QtWidgets.QComboBox()
self.topone.addItems(["One","Two","Three","four"])
self.longitudinalone = QtWidgets.QComboBox()
self.longitudinalone.addItems(["One","Two","Three","four"])
self.bottomone = QtWidgets.QComboBox()
self.bottomone.addItems(["One","Two","Three","four"])
self.stirrupone = QtWidgets.QComboBox()
self.stirrupone.addItems(["One","Two","Three","four"])
self.toprebar = QtWidgets.QComboBox()
self.toprebar.addItems(["1","2","3","4","5","6","7","8","9"])
self.longitudinalrebar = QtWidgets.QComboBox()
self.longitudinalrebar.addItems(["1","2","3","4","5","6",
"7","8","9"])
self.bottomrebar = QtWidgets.QComboBox()
self.bottomrebar.addItems(["1","2","3","4","5","6","7","8","9"])
self.stirruprebar = QtWidgets.QComboBox()
self.stirruprebar.addItems(["1","2","3","4","5","6","7","8","9"])
self.rebarbox = QtWidgets.QVBoxLayout()
self.topvoid = QtWidgets.QLabel(" ")
self.top = QtWidgets.QLabel("One: ")
self.longitudinal = QtWidgets.QLabel("Two: ")
self.bottom = QtWidgets.QLabel("Three: ")
self.stirrup = QtWidgets.QLabel("Four: ")
self.rebarbox.addWidget(self.topvoid)
self.rebarbox.addWidget(self.top)
self.rebarbox.addWidget(self.longitudinal)
self.rebarbox.addWidget(self.bottom)
self.rebarbox.addWidget(self.stirrup)
self.typebox = QtWidgets.QVBoxLayout()
self.type = QtWidgets.QLabel("Type ")
self.typebox.addWidget(self.type, alignment=QtCore.Qt.AlignCenter)
self.typebox.addWidget(self.topone)
self.typebox.addWidget(self.longitudinalone)
self.typebox.addWidget(self.bottomone)
self.typebox.addWidget(self.stirrupone)
self.Reinforcebox = QtWidgets.QVBoxLayout()
self.Reinforcement = QtWidgets.QLabel("One, One")
self.Reinforcebox.addWidget(self.Reinforcement)
self.Reinforcebox.addWidget(self.toprebar)
self.Reinforcebox.addWidget(self.longitudinalrebar)
self.Reinforcebox.addWidget(self.bottomrebar)
self.Reinforcebox.addWidget(self.stirruprebar)
self.designstrengthbox = QtWidgets.QVBoxLayout()
self.designsteelstrength = QtWidgets.QLabel("Four")
self.topsteelstrength = QtWidgets.QLabel()
self.longsteelstrength = QtWidgets.QLabel()
self.bottompsteelstrength = QtWidgets.QLabel()
self.stirrupsteelstrength = QtWidgets.QLabel()
self.designstrengthbox.addWidget(self.designsteelstrength)
self.designstrengthbox.addWidget(self.topsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.designstrengthbox.addWidget(self.longsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.designstrengthbox.addWidget(self.bottompsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.designstrengthbox.addWidget(self.stirrupsteelstrength, alignment=QtCore.Qt.AlignCenter)
self.sbox = QtWidgets.QVBoxLayout()
self.anytext = QtWidgets.QLabel("Any text")
self.value = QtWidgets.QLabel("Any")
self.value1 = QtWidgets.QLabel("Any")
self.value2 = QtWidgets.QLabel("Any")
self.value3 = QtWidgets.QLabel("Any")
self.sbox.addWidget(self.anytext)
self.sbox.addWidget(self.value)
self.sbox.addWidget(self.value1)
self.sbox.addWidget(self.value2)
self.sbox.addWidget(self.value3)
self.hlay = QtWidgets.QHBoxLayout()
self.hlay.addStretch()
self.hlay.addLayout(self.rebarbox)
self.hlay.addLayout(self.typebox)
self.hlay.addLayout(self.Reinforcebox)
self.hlay.addLayout(self.designstrengthbox)
self.hlay.addLayout(self.sbox)
self.hlay.addStretch()
self.setTitle("&GroupC")
self.setLayout(self.hlay)
self.rebarstrength = ["1","2","3","4"]
self.topone.activated.connect(self.setdatatopstrength)
#QtCore.pyqtSlot(int)
def setdatatopstrength(self, index):
value = self.rebarstrength[index]
self.display_topsteeldata(value)
#QtCore.pyqtSlot(int)
def display_topsteeldata(self, value):
try:
gammas = 1.15
fyd = int(float(value)/gammas)
fmt = "{}"
self.topsteelstrength.setText(fmt.format(str(fyd)))
except ValueError:
print("Error")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = ClassWidget()
w.show()
sys.exit(app.exec_())
I'm developing an app with PyQt5, and can't find out how to translate the position of a right click on a QTableView into a row number. The way I implemented it, which is by using the rowAt method on the QPoint cursor position, I get row numbers that look like having an offset with the real row number that was clicked. I've been looking around but couldn't get any clear solution. Sounds like there's something to do with the scrolling area. An example of my code is below.
The UI code generated with Qt Designer:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowModality(QtCore.Qt.NonModal)
MainWindow.resize(941, 767)
MainWindow.setMinimumSize(QtCore.QSize(922, 767))
MainWindow.setMaximumSize(QtCore.QSize(1900, 1200))
MainWindow.setAutoFillBackground(False)
MainWindow.setAnimated(False)
self.MyWindows = QtWidgets.QWidget(MainWindow)
self.MyWindows.setEnabled(True)
self.MyWindows.setMinimumSize(QtCore.QSize(921, 726))
self.MyWindows.setMaximumSize(QtCore.QSize(1900, 1200))
self.MyWindows.setObjectName("MyWindows")
self.layoutWidget = QtWidgets.QWidget(self.MyWindows)
self.layoutWidget.setGeometry(QtCore.QRect(10, 0, 911, 441))
self.layoutWidget.setObjectName("layoutWidget")
self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.tableView = QtWidgets.QTableView(self.layoutWidget)
self.tableView.setEnabled(True)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(1)
sizePolicy.setVerticalStretch(1)
sizePolicy.setHeightForWidth(self.tableView.sizePolicy().hasHeightForWidth())
self.tableView.setSizePolicy(sizePolicy)
self.tableView.setMinimumSize(QtCore.QSize(900, 400))
font = QtGui.QFont()
font.setPointSize(10)
self.tableView.setFont(font)
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.tableView.setAlternatingRowColors(True)
self.tableView.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableView.setGridStyle(QtCore.Qt.NoPen)
self.tableView.setSortingEnabled(False)
self.tableView.setObjectName("tableView")
self.tableView.horizontalHeader().setCascadingSectionResizes(True)
self.tableView.horizontalHeader().setSortIndicatorShown(False)
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.verticalHeader().setVisible(True)
self.tableView.verticalHeader().setCascadingSectionResizes(True)
self.tableView.verticalHeader().setHighlightSections(True)
self.tableView.verticalHeader().setSortIndicatorShown(False)
self.tableView.verticalHeader().setStretchLastSection(True)
self.gridLayout.addWidget(self.tableView, 1, 1, 1, 1)
MainWindow.setCentralWidget(self.MyWindows)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Thib Imave Smoother V0.2"))
The main code:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QMainWindow, QSizePolicy, QHeaderView, QFileSystemModel, QMenu, QAction
# QtDesigner generated code imports
from UI import *
class ShowTableView:
def __init__(self, guiObject):
self._gui = guiObject # store QWidget from Gui class
#initialize fake data for testing
self.my_data = [["test" for x in range(7)] for x in range(5000)]
self.tm = MyTableModel(self.my_data)
self._gui.tableView.setModel(self.tm)
header = self._gui.tableView.horizontalHeader()
header.setSectionResizeMode(QHeaderView.ResizeToContents) # have columns width adjusted to content
class MyTableModel(QAbstractTableModel):
def __init__(self, my_data, parent=None, *args):
QAbstractTableModel.__init__(self, parent)
self.my_data = my_data
self.title_list = ["on","two","three","four","five","six","seven"]
def rowCount(self, parent):
return len(self.my_data)
def columnCount(self, parent):
return len(self.my_data[0])
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
else: #
return QVariant(self.my_data[index.row()][index.column()])
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return QVariant(self.title_list[col])
elif orientation == Qt.Vertical and role == Qt.DisplayRole:
return QVariant(col + 1)
class Gui(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Gui, self).__init__(parent)
self.setupUi(self)
self.myTable = ShowTableView(self)
def contextMenuEvent(self, QContextMenuEvent):
self.menu = QMenu(self)
removeAction = QAction('Remove', self)
self.menu.addAction(removeAction)
removeAction.triggered.connect(lambda: self.remove_row_from_rigth_click(QtGui.QCursor.pos()))
self.menu.popup(QtGui.QCursor.pos())
def remove_row_from_rigth_click(self, event,q_point):
row = self.tableView.rowAt(q_point.y())
print("row =" + str(row)) # HERE I GET WRONG VALUE WITH AN "RANDOM" OFFSET - IF I CLICK ROW 10 I GET 16 !
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
ui = Gui()
ui.show()
sys.exit(app.exec_())
The rowAt method uses local coordinates, whereas you are using global coordinates. So you must use mapFromGlobal to get the correct y value:
class Gui(QMainWindow, Ui_MainWindow):
...
def contextMenuEvent(self, event):
...
pos = event.globalPos()
removeAction.triggered.connect(
lambda: self.remove_row_from_rigth_click(pos))
self.menu.popup(pos)
def remove_row_from_rigth_click(self, q_point):
row = self.tableView.rowAt(
self.tableView.viewport().mapFromGlobal(q_point).y())
print("row =" + str(row))
Note that the returned row is zero-based, unlike the vertical header labels.