通过 textinput 添加新项目时,阻止 QScrollArea 项目跳来跳去

Posted

技术标签:

【中文标题】通过 textinput 添加新项目时,阻止 QScrollArea 项目跳来跳去【英文标题】:Stop QScrollArea items from jumping around when adding new items through textinput 【发布时间】:2017-08-21 18:50:17 【问题描述】:

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

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

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_())

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

【问题讨论】:

【参考方案1】:

所以问题在于,每当滚动区域及其容器视图不在焦点上时,例如当我在文本框中输入并且焦点位于焦点时,它不会在向容器添加内容后立即更新几何和布局小部件,所以它看起来很奇怪,直到它有时间更新它。

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

【讨论】:

以上是关于通过 textinput 添加新项目时,阻止 QScrollArea 项目跳来跳去的主要内容,如果未能解决你的问题,请参考以下文章

vue项目实践-添加axios封装api请求

vue中qs插件的使用

React Native 和处理 TextInput 数据的正确方法?

由于某种原因,向 TextInput 添加值会更改字体粗细

如何在kivy python中添加标签,TextInput

如何实现textinput控制和识别