Решение @ S.Nick работает, но оно не является правильным, кроме того, что оно не объясняет проблему, а только указывает на сообщение об ошибке, которое вы должны были предоставить.
Первая ошибка, которую вы совершаете, заключается в том, что у вас нет согласованного дизайна, например, даже если виджет является визуальным элементом, он не только означает, что он является единственным, он также имеет связанные данные, поэтому я спрашиваю себя: почемуВы создали класс ImageWidget
, то же самое?для EffLengthInfo
и CheckInfo
?Что ж, кажется, что для создания макета необходимо ли создавать виджет для создания макета?Нет, потому что виджет - это ненужный ресурс, т. Е. Потраченная впустую память.Поэтому я отмечаю, что решение S.Nick неверно, поскольку он приглашает других перекрывать ошибки проектирования.
Если ваша цель - просто создать макеты, лучше использовать функцию:
import sys, os
from PyQt5 import QtCore, QtGui, QtWidgets
iconroot = os.path.dirname(__file__)
def create_image_layout():
hlay = QtWidgets.QHBoxLayout()
for icon_name in ("images/fixed-fixed.png",
"images/pinned-pinned.png",
"images/fixed-free.png",
"images/fixed-pinned.png"):
label = QtWidgets.QLabel()
pixmap = QtGui.QPixmap(os.path.join(iconroot, icon_name))
label.resize(150, 150)
label.setPixmap(pixmap.scaled(label.size(), QtCore.Qt.KeepAspectRatio))
hlay.addWidget(label)
return hlay
def create_EffLengthInfo_layout():
hlay = QtWidgets.QHBoxLayout()
for text in ('Ley = 1.0 L\nLec = 1.0 L',
'Ley = 0.699 L\nLec = 0.699 L',
'Ley = 2.0 L\nLec = 2.0 L',
'Ley = 0.5 L\nLec = 0.5 L'):
label = QtWidgets.QLabel(text)
hlay.addWidget(label)
return hlay
def create_checkInfo_layout():
hlay = QtWidgets.QHBoxLayout()
for _ in range(3):
checkbox = QtWidgets.QCheckBox()
hlay.addWidget(checkbox, alignment=QtCore.Qt.AlignCenter)
return hlay
class Grid(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Grid, self).__init__(parent)
image_lay = create_image_layout()
efflengthinfo_lay = create_EffLengthInfo_layout()
checkinfo_lay = create_checkInfo_layout()
vlay = QtWidgets.QVBoxLayout(self)
vlay.addLayout(image_lay)
vlay.addLayout(efflengthinfo_lay)
vlay.addLayout(checkinfo_lay)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
im = Grid()
im.show()
sys.exit(app.exec_())
Почему это было показано в случае EffLengthInfo и CheckInfo "работает"?
Я отмечаю, что это работает в кавычках, потому что это работает, ноэто не решение, переходя к сути, макет устанавливается в макете и является частью виджета, и после этого он не может быть помещен в другой виджет, и если мы проверим ImageWidget
, мы увидим, что вы установилидва раза макет для виджета:
class ImageWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ImageWidget, self).__init__(parent)
self.hlay = QtWidgets.QHBoxLayout(self) # 1.
...
self.setLayout(self.hlay) # 2.
Когда вы устанавливаете виджет при создании макета, он устанавливается в этом виджете.
Когда виджет устанавливает макет, используя метод setLayout()
Поэтому вы должны выбросить следующую ошибку в строке vlay.addLayout(self.imagewidget.hlay)
:
QLayout:: addChildLayout: макет "" уже имеет родителя
Другим решением является установка виджетов вместо макетов:
class ImageWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ImageWidget, self).__init__(parent)
self.hlay = QtWidgets.QHBoxLayout(self)
...
# self.setLayout(self.hlay) # comment this line
class EffLengthInfo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(EffLengthInfo, self).__init__(parent)
...
self.ilay = QtWidgets.QHBoxLayout(self) # <-- add self
class CheckInfo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(CheckInfo, self).__init__(parent)
...
self.checklay = QtWidgets.QHBoxLayout(self) # <-- add self
class Grid(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Grid, self).__init__(parent)
self.imagewidget = ImageWidget()
self.efflengthinfo = EffLengthInfo()
self.checkinfo = CheckInfo()
vlay = QtWidgets.QVBoxLayout(self)
vlay.addWidget(self.imagewidget) # <-- change addLayout() to addWidget()
vlay.addWidget(self.efflengthinfo) # <-- change addLayout() to addWidget()
vlay.addWidget(self.checkinfo) # <-- change addLayout() to addWidget()
...
Еще одна перспектива, которая может возникнуть, и это зависит от использования, которое вы хотите дать виджету, эточто вы хотите, чтобы информационный блок был изображением, текстом и флажком, поэтому, если правильно создать виджет:
import sys, os
from PyQt5 import QtCore, QtGui, QtWidgets
iconroot = os.path.dirname(__file__)
class FooWidget(QtWidgets.QWidget):
def __init__(self, path_icon, text, checked=False, parent=None):
super(FooWidget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, path_icon))
pixmap_label = QtWidgets.QLabel()
pixmap_label.resize(150, 150)
pixmap_label.setPixmap(pixmap.scaled(pixmap_label.size(), QtCore.Qt.KeepAspectRatio))
text_label = QtWidgets.QLabel(text)
checkbox = QtWidgets.QCheckBox(checked=checked)
lay.addWidget(pixmap_label)
lay.addWidget(text_label)
lay.addWidget(checkbox)
class Grid(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Grid, self).__init__(parent)
lay = QtWidgets.QHBoxLayout(self)
icons = ["images/fixed-fixed.png",
"images/pinned-pinned.png",
"images/fixed-free.png",
"images/fixed-pinned.png"]
texts = ["Ley = 1.0 L\nLec = 1.0 L",
"Ley = 0.699 L\nLec = 0.699 L",
"Ley = 2.0 L\nLec = 2.0 L",
"Ley = 0.5 L\nLec = 0.5 L"]
for path_icon, text in zip(icons, texts):
w = FooWidget(os.path.join(iconroot, path_icon), text)
lay.addWidget(w)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
im = Grid()
im.show()
sys.exit(app.exec_())