python - 添加新小部件时,滚动区域无法扩展(滚动)

标签 python pyqt pyqt4 qscrollarea

我尝试制作一些简单的本地聊天应用程序来练习。我创建一个按钮来发送消息,每次按下按钮时都会显示消息,但滚动区域变得更窄并且不会扩展滚动区域。我是否在代码中遗漏了某些内容或添加了不应该添加的内容?我该如何解决这个问题?

这是我的代码:

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Bubble(QLabel):
    def __init__(self,text):
        super(Bubble,self).__init__(text)
        self.setContentsMargins(5,5,5,5)

    def paintEvent(self, e):

        p = QPainter(self)
        p.setRenderHint(QPainter.Antialiasing,True)
        p.drawRoundedRect(0,0,self.width()-1,self.height()-1,5,5)

        super(Bubble,self).paintEvent(e)        

class MyWidget(QWidget):

    def __init__(self,text,left=True):
        super(MyWidget,self).__init__()

        hbox = QHBoxLayout()

        label = Bubble(text)

        if not left:
            hbox.addSpacerItem(QSpacerItem(1,1,QSizePolicy.Expanding,QSizePolicy.Preferred))

        hbox.addWidget(label)

        if left:
            hbox.addSpacerItem(QSpacerItem(1,1,QSizePolicy.Expanding,QSizePolicy.Preferred))            

        hbox.setContentsMargins(0,0,0,0)

        self.setLayout(hbox)
        self.setContentsMargins(0,0,0,0)

class Chatting(QWidget):
    def __init__(self, parent=None):
        super(Chatting, self).__init__(parent)
        self.vbox = QVBoxLayout()
        for _ in range(20):
            self.vbox.addWidget(MyWidget("Left side"))

        widget = QWidget()
        widget.setLayout(self.vbox)

        scroll = QScrollArea()
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        scroll.setWidgetResizable(False)
        scroll.setWidget(widget)     

        #Scroll Area Layer add 
        vLayout = QVBoxLayout(self)
        vLayout.addWidget(scroll)

        send = QPushButton('')
        send.setIcon(QIcon('images/send.png'))
        send.setStyleSheet("background-color:#d00001; width: 44px")
        send.setIconSize(QSize(84,20))
        send.clicked.connect(self.send_messages)
        vLayout.addWidget(send)
        self.setLayout(vLayout)

    def send_messages(self):
        self.vbox.addWidget(MyWidget('testing'))

最佳答案

问题很简单,您必须将 widgetResizable 属性启用为 True,因为该属性允许 QScrollArea 计算内容的大小。

scroll.setWidgetResizable(True)

另一方面,我花时间改进了您的代码,如下所示:

from PyQt4 import QtGui, QtCore


class Bubble(QtGui.QLabel):
    def __init__(self, text):
        super(Bubble,self).__init__(text)
        self.setContentsMargins(5, 5, 5, 5)

    def paintEvent(self, e):
        p = QtGui.QPainter(self)
        p.setRenderHint(QtGui.QPainter.Antialiasing, True)
        p.drawRoundedRect(self.rect().adjusted(0, 0, -1, -1), 5, 5)
        super(Bubble, self).paintEvent(e)        

class MyWidget(QtGui.QWidget):
    def __init__(self, text, left=True):
        super(MyWidget,self).__init__()
        lay = QtGui.QVBoxLayout(self)
        lay.setContentsMargins(0, 0, 0, 0)
        self.setContentsMargins(0, 0, 0, 0)
        label = Bubble(text)
        lay.addWidget(label, alignment= QtCore.Qt.AlignLeft if left else QtCore.Qt.AlignRight)


class Chatting(QtGui.QWidget):
    def __init__(self, parent=None):
        super(Chatting, self).__init__(parent)

        widget = QtGui.QWidget()
        self.vbox = QtGui.QVBoxLayout(widget)
        self.vbox.addStretch()
        self.scroll = QtGui.QScrollArea(widgetResizable=True)
        self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.scroll.setWidget(widget)     

        #Scroll Area Layer add 
        send = QtGui.QPushButton(icon= QtGui.QIcon('images/send.png'))
        send.setStyleSheet("background-color:#d00001; width: 44px")
        send.setIconSize(QtCore.QSize(84,20))
        send.clicked.connect(self.on_clicked)

        vLayout = QtGui.QVBoxLayout(self)
        vLayout.addWidget(self.scroll)
        vLayout.addWidget(send)

    def send_message(self, text, direction=True):
        widget = MyWidget(text, direction)
        self.vbox.insertWidget(self.vbox.count()-1, widget)
        scroll_bar = self.scroll.verticalScrollBar()
        # move to end
        QtCore.QTimer.singleShot(10, lambda: scroll_bar.setValue(scroll_bar.maximum()))

    @QtCore.pyqtSlot()
    def on_clicked(self):
        self.send_message("testing") 


if __name__ == '__main__':
    import sys
    import random

    app = QtGui.QApplication(sys.argv)
    w = Chatting()

    def test():
        for _ in range(8):
            w.send_message("testing", random.choice((True, False)))
    QtCore.QTimer.singleShot(1000, test)

    w.resize(240, 480)
    w.show()
    sys.exit(app.exec_())

关于python - 添加新小部件时,滚动区域无法扩展(滚动),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52618980/

相关文章:

python - Django:为什么出现 KeyError: 'pk'

python - 通过文本 beautifulsoup 从第二个 div 中提取文本

python - 添加/删除包含多个小部件的布局 pyqt

python - 在QListView中选择一个项目的信号是什么?

python - (PyQt 和 PySide)QFileDialog.getExistingDirectory 在 Windows 上不起作用

java - 无法在 mesos 上运行测试框架

python - 类设计: methods that share a lot of the same code

python - 使用 QWebEngineView 显示大于 2MB 的内容?

python - PyQt5 中的 QTableView clicked.connect() 键盘滚动等效

qt - 使用 PyQt 和 Qt4,这是在 QTabWidget 选项卡中获取 throbber 的正确方法吗?