QWidget Geometry() 不更新
Posted
技术标签:
【中文标题】QWidget Geometry() 不更新【英文标题】:QWidget Geometry() not updating 【发布时间】:2014-06-04 16:43:39 【问题描述】:我将QWidget
s 排在QVBoxLayout
内的QScrollArea
和setWidgetResizable(True)
中
当我调整QWidget
s 之一的大小时,QWidget
s 在图形用户界面中相应地重新定位,但它们的geometry()
属性并没有反映这一点,geometry().x()
和geometry().y()
仍然是搬家前后一样。
到目前为止,我发现更新x()
和y()
坐标的唯一方法是hide()
和show()
QScrollArea
。
我尝试了update()
、updateGeometry()
和repaint()
,但都没有成功。
这是我为总结问题而制作的示例测试代码:
import sys
from PySide import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.showMaximized()
self.widget_window = QtGui.QWidget()
self.scrollarea = QtGui.QScrollArea()
self.v_layout = QtGui.QVBoxLayout()
self.test_1 = QtGui.QPushButton('Test 1')
self.test_2 = QtGui.QPushButton('Test 2')
self.v_layout.addWidget(self.test_1)
self.v_layout.addWidget(self.test_2)
self.widget_window.setLayout(self.v_layout)
self.scrollarea.setWidgetResizable(True)
self.scrollarea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollarea.setAlignment(QtCore.Qt.AlignCenter)
self.scrollarea.setWidget(self.widget_window)
self.setCentralWidget(self.scrollarea)
print(self.test_2.geometry().x())
print(self.test_2.geometry().y())
self.test_1.setFixedHeight(1000)
#uncommenting the following next two lines, solves the problem
#self.scrollarea.hide()
#self.scrollarea.show()
print(self.test_2.geometry().x())
print(self.test_2.geometry().y())
def main():
app = QtGui.QApplication(sys.argv)
main = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
我的问题是:
-
有更好的解决方案吗?
updateGeometry()
不应该实际更新geometry()
吗?
为什么会发生这种行为? (即为什么它以图形方式而不是以编程方式更新?)
可以连续使用hide()
和show()
在其他上下文中导致一些问题(窗口闪烁或其他...)?
【问题讨论】:
本例中QScrollArea是如何添加到VLayout中的? 其实布局是针对一个QWidget,它是QScrollArea的内部小部件。 QScrollArea 不是任何布局的一部分。 【参考方案1】:当您更新 GUI 时,它不是即时的。它在您将控制权交给事件循环时执行。在这种情况下,它在__init__
完成之后 完成,这显然是在你的print
s 之后。因此,您将看到旧位置。
hide/show
在那个时候强制更新。这就是你得到正确值的原因。但是,这不是最好的方法,因为您可能会在 hide/show
工作时观察到闪烁。
更好的方法是告诉事件循环在继续之前处理事件。这将确保 GUI 得到更新:
#...
print(self.test_2.geometry().x())
print(self.test_2.geometry().y())
self.test_1.setFixedHeight(1000)
QtGui.QApplication.processEvents()
print(self.test_2.geometry().x())
print(self.test_2.geometry().y())
#...
PS:我假设,你有充分的理由这样做。大多数情况下,您不会关心 GUI 何时更新。
【讨论】:
谢谢,这解决了我的问题。还有一件事我不明白,GUI 如何在不更新geometry().x()
和 geometry().y()
值的情况下自行更新?一般来说,情况正好相反(即代码更新但不是 GUI)?
@IlyesFerchiou:当您调用self.test_1.setFixedHeight(1000)
时,GUI 和geometry
都不会更新。 geometry
的视觉更新或重新计算不是即时的。这是“排队”。一旦 Qt 事件循环有机会处理这些事件,就会执行更新。 .processEvents()
基本上“暂停”__init__
并让 Qt 事件循环处理那些更新事件。
换句话说,在您的原始版本中,GUI 没有在这些打印调用之间更新。它发生在之后。以上是关于QWidget Geometry() 不更新的主要内容,如果未能解决你的问题,请参考以下文章
java.lang.ClassCastException:com.google.android.gms.maps.model.LatLng 无法转换为 com.mapbox.mapboxsdk.geo