python - QScrollArea,如何使我的中央小部件可滚动?
问题描述
我正在尝试将小部件变成可滚动窗口。然而,我所做的只是打开一个完全独立于我的中央小部件的 QScrollarea。
class Ui_MainWindow(object):
def mainscreen(self, MainWindow):
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.scrollArea = QtWidgets.QScrollArea()
self.scrollArea.setWidget(self.centralwidget)
MainWindow.setCentralWidget(self.centralwidget)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.mainscreen(MainWindow)
MainWindow.show()
app.exec_()
这只是自行打开我的 MainWindow,打开滚动区域的唯一方法是执行 self.scrollarea.show 。我不知道 QScrollArea 是如何工作的,我应该怎么做?
解决方案
简单解释:滚动区域与主窗口无关,然后在主窗口时不显示。
永远不要修改(或模仿)由pyuic
您对对象结构、Qt 父/所有权以及如何设置滚动区域感到困惑。
这也是由于您显然是在尝试模仿 pyuic 生成的文件的结构和行为,而这绝不应该这样做。这些文件旨在按原样直接使用,无需任何修改,并在程序的主脚本中导入。
它们的特殊结构仅用于此目的,并且它们的构建方式不能被模拟,因为通过代码创建 UI 只能通过继承 QWidget 子类(QMainWindow、QDialog 等)来完成;试图模仿他们所做的不仅是不必要的,而且大多数时候会导致混乱、错误和意外行为,就像你的情况一样。
打开的唯一正当理由(只需阅读)由 pyuic 生成的一个文件是用来setupUi
学习如何在) 是构建 ui 的主要小部件。setupUi
MainWindow
Form
Dialog
只有当一个人真的知道她/他在做什么时,才应该手动编辑这些文件。很少有非常罕见的情况需要这样做,通常是为了解决 uic 模块中非常具体的已知错误,这些错误通常会在非常特定的条件和情况下出现。
怎么了?
然后,当使用现有小部件作为参数创建 QWidget 实例时,结果是新小部件成为现有小部件的子级。
然后可以通过各种方式重新设置小部件:通过使用 为滚动区域setWidget()
设置小部件,或者通过将小部件设置为QMainWindow的中央小部件。
您的代码发生的情况是您创建了一个新的 QWidget,它成为 QMainWindow 的子级,其中包含以下行:
self.centralwidget = QtWidgets.QWidget(MainWindow)
然后创建一个滚动区域(没有任何父级):
self.scrollArea = QtWidgets.QScrollArea()
未使用父级创建的小部件通常被视为顶级窗口,除非它们被添加到布局中(或使用手动重新设置父级setParent()
,但这是另一回事),这会导致父级(设置布局的小部件)采用新子小部件的所有权。否则,如果您尝试显示“无父”小部件,它将显示为顶级小部件,这意味着它将有自己的窗口,并且作为任何顶级小部件,它们只能通过手动调用show()
或setVisible(True)
(这就是你的情况)。
然后您尝试设置centralwidget
滚动区域的,这将导致重新设置它:
self.scrollArea.setWidget(self.centralwidget)
最后,您将该小部件设置为中央小部件,它将再次将其重新设置回主窗口,结果滚动区域将不再有小部件(QWidget 继承自的 QObjects 只能有一个父母)。
MainWindow.setCentralWidget(self.centralwidget)
正确的做法
解决方案是正确创建一个 QWidget (或 QMainWindow 在你的情况下)子类,将滚动区域设置为中央小部件(如果你想要它)并为其内容创建一个新的小部件:
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.scrollArea = QtWidgets.QScrollArea()
self.setCentralWidget(self.scrollArea)
self.scrollArea.setWidgetResizable(True)
self.contents = QtWidgets.QWidget()
self.scrollArea.setWidget(self.contents)
# create a layout for the scroll area contents; using the target widget
# as argument of the layout constructor automatically sets the layout on
# the specified widget
layout = QtWidgets.QVBoxLayout(self.contents)
# the same as:
# layout = QtWidgets.QVBoxLayout()
# self.contents.setLayout(layout)
for row in range(20):
button = QtWidgets.QPushButton('button {}'.format(row + 1))
layout.addWidget(button)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
推荐阅读
- django - 电子邮件正文显示 html 代码代替 django 中的模板
- python - 函数值存储在 python.how 上的 int 中?
- .net - 在 .NET Windows 应用程序中使用 Windows 凭据登录
- mips - MIPS FPU 编程 - 操作数类型不正确
- python - 字典列表
- git - Git:如何删除已删除的忽略文件?
- java - Java中的Android Studio Code接受用户输入和显示输出
- javascript - setTimeout() 倒计时不工作 Discord JS
- php - 无法修改主机上的标头信息错误
- powershell - 在一行中交换字符串顺序或在powershell中交换行顺序