我有一个小部件,它想要显示带有QLabel
和QCheckBox
的图像。创建4个类,每个类包含一些要放在最终屏幕上的信息。
Class Grid
对齐并对齐图像,文本和复选框。
脚本运行后,显示当前屏幕。当前的小部件中没有图像。
图像在哪里?
所需屏幕
代码
import sys, os
from PyQt5 import QtCore, QtGui, QtWidgets
iconroot = os.path.dirname(__file__)
class ImageWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ImageWidget, self).__init__(parent)
self.hlay = QtWidgets.QHBoxLayout(self)
buckling_ilabel = QtWidgets.QLabel(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, "images/fixed-fixed.png"))
buckling_ilabel.resize(150, 150)
buckling_ilabel.setPixmap(pixmap.scaled(buckling_ilabel.size(), QtCore.Qt.KeepAspectRatio))
self.hlay.addWidget(buckling_ilabel)
buckling_blabel = QtWidgets.QLabel(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, "images/pinned-pinned.png"))
buckling_blabel.resize(150, 150)
buckling_blabel.setPixmap(pixmap.scaled(buckling_blabel.size(), QtCore.Qt.KeepAspectRatio))
self.hlay.addWidget(buckling_blabel)
buckling_clabel = QtWidgets.QLabel(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, "images/fixed-free.png"))
buckling_clabel.resize(150, 150)
buckling_clabel.setPixmap(pixmap.scaled(buckling_clabel.size(), QtCore.Qt.KeepAspectRatio))
self.hlay.addWidget(buckling_clabel)
buckling_dlabel = QtWidgets.QLabel(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, "images/fixed-pinned.png"))
buckling_dlabel.resize(150, 150)
buckling_dlabel.setPixmap(pixmap.scaled(buckling_dlabel.size(), QtCore.Qt.KeepAspectRatio))
self.hlay.addWidget(buckling_dlabel)
self.setLayout(self.hlay)
class EffLengthInfo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(EffLengthInfo, self).__init__(parent)
ilabel = QtWidgets.QLabel('Ley = 1.0 L\nLec = 1.0 L')
blabel = QtWidgets.QLabel('Ley = 0.699 L\nLec = 0.699 L')
clabel = QtWidgets.QLabel('Ley = 2.0 L\nLec = 2.0 L')
dlabel = QtWidgets.QLabel('Ley = 0.5 L\nLec = 0.5 L')
self.ilay = QtWidgets.QHBoxLayout()
self.ilay.addWidget(ilabel)
self.ilay.addWidget(blabel)
self.ilay.addWidget(clabel)
self.ilay.addWidget(dlabel)
class CheckInfo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(CheckInfo, self).__init__(parent)
icheck = QtWidgets.QCheckBox()
bcheck = QtWidgets.QCheckBox()
ccheck = QtWidgets.QCheckBox()
dcheck = QtWidgets.QCheckBox()
self.checklay = QtWidgets.QHBoxLayout()
self.checklay.addWidget(icheck, alignment=QtCore.Qt.AlignCenter)
self.checklay.addWidget(bcheck, alignment=QtCore.Qt.AlignCenter)
self.checklay.addWidget(ccheck, alignment=QtCore.Qt.AlignCenter)
self.checklay.addWidget(dcheck, alignment=QtCore.Qt.AlignCenter)
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.addLayout(self.imagewidget.hlay)
vlay.addLayout(self.efflengthinfo.ilay)
vlay.addLayout(self.checkinfo.checklay)
self.setLayout(vlay)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
im = Grid()
im.show()
sys.exit(app.exec_())
答案 0 :(得分:1)
The @S.Nick's solution有用,但它不是正确的,除了不能解释问题,它仅指示您应提供的错误消息。
您遇到的第一个错误是您没有一个一致的设计,例如,即使小部件是视觉元素,它不仅意味着它是唯一的,而且还具有关联的数据,所以我问自己:为什么同样创建ImageWidget
类? EffLengthInfo
和CheckInfo
?好吧,似乎只是创建一个布局,是否有必要创建一个小部件来创建一个布局?否,因为窗口小部件是不必要的资源,即浪费的内存。因此,我指出S.Nick's solution是不正确的,因为他邀请其他人重叠设计错误。
如果您的目标只是创建布局,那么最好使用函数:
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_())
答案 1 :(得分:0)
行:vlay.addLayout (self.imagewidget.hlay)
错误是:QLayout :: addChildLayout: layout "" already has a parent
尝试一下:
import sys, os
from PyQt5 import QtCore, QtGui, QtWidgets
iconroot = os.path.dirname(__file__)
class ImageWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ImageWidget, self).__init__(parent)
# self.hlay = QtWidgets.QHBoxLayout(self)
self.hlay = QtWidgets.QHBoxLayout() # < --- -self
buckling_ilabel = QtWidgets.QLabel(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, "images/logo.png"))
buckling_ilabel.resize(150, 150)
buckling_ilabel.setPixmap(pixmap.scaled(buckling_ilabel.size(), QtCore.Qt.KeepAspectRatio))
self.hlay.addWidget(buckling_ilabel)
buckling_blabel = QtWidgets.QLabel(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, "images/logo.png"))
buckling_blabel.resize(150, 150)
buckling_blabel.setPixmap(pixmap.scaled(buckling_blabel.size(), QtCore.Qt.KeepAspectRatio))
self.hlay.addWidget(buckling_blabel)
buckling_clabel = QtWidgets.QLabel(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, "images/logo.png"))
buckling_clabel.resize(150, 150)
buckling_clabel.setPixmap(pixmap.scaled(buckling_clabel.size(), QtCore.Qt.KeepAspectRatio))
self.hlay.addWidget(buckling_clabel)
buckling_dlabel = QtWidgets.QLabel(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, "images/logo.png"))
buckling_dlabel.resize(150, 150)
buckling_dlabel.setPixmap(pixmap.scaled(buckling_dlabel.size(), QtCore.Qt.KeepAspectRatio))
self.hlay.addWidget(buckling_dlabel)
# self.setLayout(self.hlay) # < ---
class EffLengthInfo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(EffLengthInfo, self).__init__(parent)
ilabel = QtWidgets.QLabel('Ley = 1.0 L\nLec = 1.0 L')
blabel = QtWidgets.QLabel('Ley = 0.699 L\nLec = 0.699 L')
clabel = QtWidgets.QLabel('Ley = 2.0 L\nLec = 2.0 L')
dlabel = QtWidgets.QLabel('Ley = 0.5 L\nLec = 0.5 L')
self.ilay = QtWidgets.QHBoxLayout()
self.ilay.addWidget(ilabel)
self.ilay.addWidget(blabel)
self.ilay.addWidget(clabel)
self.ilay.addWidget(dlabel)
class CheckInfo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(CheckInfo, self).__init__(parent)
icheck = QtWidgets.QCheckBox()
bcheck = QtWidgets.QCheckBox()
ccheck = QtWidgets.QCheckBox()
dcheck = QtWidgets.QCheckBox()
self.checklay = QtWidgets.QHBoxLayout()
self.checklay.addWidget(icheck, alignment=QtCore.Qt.AlignCenter)
self.checklay.addWidget(bcheck, alignment=QtCore.Qt.AlignCenter)
self.checklay.addWidget(ccheck, alignment=QtCore.Qt.AlignCenter)
self.checklay.addWidget(dcheck, alignment=QtCore.Qt.AlignCenter)
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.addLayout(self.imagewidget.hlay) # < ---
# Error: QLayout::addChildLayout: layout "" already has a parent # < ---
vlay.addLayout(self.efflengthinfo.ilay)
vlay.addLayout(self.checkinfo.checklay)
self.setLayout(vlay)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
im = Grid()
im.show()
sys.exit(app.exec_())