python - 通过文本输入添加新项目时,阻止 QScrollArea 项目跳跃

标签 python qt pyqt qt5 pyqt5

我有一个简单的QScrollarea,它有一个QWidget,里面有一个垂直的框布局,其中包含很多小部件。我在鼠标单击后和在 QLineEdit 中输入文本后向其中添加新的小部件。

但是,滚动区域的行为有所不同,具体取决于导致插入新项目的原因。如果我的 addTestLabel()textChanged() 信号之后被调用,则整个内容会跳动一秒钟,但是如果相同的 addTestLabel()是从 mouseclick 事件调用的,它的工作方式完全符合预期,这对我来说没有意义。

Gif 示例,首先我通过单击插入项目,它工作得很好,然后我开始通过键入插入,它会跳转。然后我返回单击,它在第一次单击后跳转,但随后所有其他单击都插入而不会再次跳转

我可以做的最短的最小示例:

import sys

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplication, QScrollArea, QVBoxLayout, QSizePolicy, QLineEdit

from ui.tabdock.utils import *


class ChatView(QWidget):
    def __init__(self):
        super().__init__()

        #make the main window a vertical box layout
        self._boxLayout = QVBoxLayout()
        self._boxLayout.setAlignment(Qt.AlignTop)
        self.setLayout(self._boxLayout)


        # make a scroll area and put it at the top
        self._scrollArea =  QScrollArea()
        self._scrollArea.setWidgetResizable(True)
        self._boxLayout.addWidget(self._scrollArea)

        # add a text input below the scroll area
        self._textInput = QLineEdit()

        # make it add a new item every time textChange event fires
        #THIS RESULTS IN EVERYTHING JUMPING FOR A SECOND
        self._textInput.textChanged.connect(lambda t: self.addTestLabel("text change add")) 

        self._boxLayout.addWidget(self._textInput)

        # make a container view with a vertical box layout that will contain all the actual items
        self.listContainerView = QWidget()
        self.listContainerView.setLayout(QVBoxLayout())
        self.listContainerView.layout().setAlignment(Qt.AlignTop)

        # put the container view inside the scroll area
        self._scrollArea.setWidget(self.listContainerView)

        #some items to get started
        for i in range(10):
            self.addTestLabel("label %s"%i)

        #add new items whenever the mouse is pressed somewhere
        # THIS INSERTS CORRECTLY WITHOUT JUMPING
        self.mousePressEvent = lambda e:self.addTestLabel() 

    def addTestLabel(self, text = "complex widget goes here"):
        label = QLabel(text)
        label.setStyleSheet("border: 1px solid red;")
        label.setFixedHeight(50)
        self.listContainerView.layout().addWidget(label)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    cv = ChatView()
    cv.show()
    cv.setGeometry(400,400,1200,800)
    sys.exit(app.exec_())

如果从 textChanged 信号调用 addTestLabel() ,如何停止跳跃的瞬间,并使其表现得像从鼠标单击调用时一样?

最佳答案

事实证明,问题在于,每当滚动区域及其容器 View 没有获得焦点时,例如当我在文本框中键入内容并且获得焦点时,在向容器添加内容后,它不会立即更新几何形状和布局小部件,因此在它更新它之前它会看起来很奇怪。

只需在添加小部件后添加 self.listContainerView.updateGeometry() 即可强制布局刷新修复它。

关于python - 通过文本输入添加新项目时,阻止 QScrollArea 项目跳跃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45803839/

相关文章:

python - 将 CSV 加载到 Pandas MultiIndex DataFrame

python - 使用故意弱私钥解密消息无限期挂起

qt - Qt耦合信号/槽的无限递归

python - 如何从 GUI 停止 QThread

python - 如何在 VScode 和 PyCharm 等 PyGtk 应用程序中实现 Linux 终端?

qt - 何时使用deleteLater

python - QT4 (PyQt4) QTableWidget 信号在应该触发时没有触发

python - 使用 webengine 视频和音频编解码器

pyqt - 如何禁用/隐藏 pyQt QDockWidget 中的关闭按钮

python - 将 Python 文件中的 JSON 数据显示为 HTML