[英]PySide2 doesn't behave like PySide when the slot function has a default argument=None
[英]PySide2 QTextEdit doesn't adjust to it's own content when using wrapping. (Making chat window)
PySide2 QTextEdit 在放置文本时不会改变它自己的大小。
我正在尝试创建类似聊天窗口的东西,其中每条消息 - OnlyRead 模式下的 QTextEdit。 放置在 QScrollArea 中的所有“消息”。 主要目标是让消息框(如下屏幕上的消息框)根据内容调整其大小。 错误的工作示例
这已经被复制粘贴了很多次。 但它没有做我想要的。 它创建一个固定的、不可调整大小的 QTextEdit 消息框。
例如我的实际意思是,如果我们有一个单字消息,QTextEdit 小部件必须成为一个单笔画框,具有消息的宽度。 如果我们有一个多句消息,QTextEdit 小部件必须成为一个多笔画框(已经扩展了高度,不需要在里面滚动),具有最大恒定长度(我将选择)。
接下来是显示正确消息的示例(很好的示例)
为了实现自调整消息,需要一些预防措施。
正如我对相关帖子的回答和评论中所解释的,您必须考虑布局尺寸与其要求之间的复杂而微妙的关系,由于文本布局没有固定的比例,这变得更加复杂。
根据文本设置宽度的主要问题是它可以改变显示它所需的高度,这可能会导致递归,并且由于大小是基于当前视口大小的,结果是minimumSizeHint()
将在一定数量的递归调用后总是返回最小的可能大小。
考虑到上述情况,我们必须对我的原始代码进行以下更改:
minimumSizeHint()
必须更改为:
idealWidth()
; 请注意,与您的链接的修改代码存在一些差异:最重要的是,重写样式表没有多大意义,并且设置边距会导致frameWidth()
返回的值出现问题(这就是为什么他们从文档高度中减去 100); 这当然不是一个好的选择,因为边距应该在布局中设置。
class WrapLabel(QtWidgets.QTextEdit):
def __init__(self, text=''):
super().__init__(text)
self.setReadOnly(True)
self.setSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Maximum)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.textChanged.connect(self.updateGeometry)
def minimumSizeHint(self):
margin = self.frameWidth() * 2
doc = self.document().clone()
doc.setTextWidth(self.maximumWidth())
idealWidth = doc.idealWidth()
idealHeight = doc.size().height()
doc.setTextWidth(self.viewport().width())
if doc.size().height() == idealHeight:
idealWidth = doc.idealWidth()
return QtCore.QSize(
max(50, idealWidth + margin),
doc.size().height() + margin)
def sizeHint(self):
return self.minimumSizeHint()
def resizeEvent(self, event):
super().resizeEvent(event)
self.updateGeometry()
class ChatTest(QtWidgets.QScrollArea):
def __init__(self):
super().__init__()
self.margin = 100
self.marginRatio = .8
self.messages = []
container = QtWidgets.QWidget()
self.setWidget(container)
self.setWidgetResizable(True)
layout = QtWidgets.QVBoxLayout(container)
layout.addStretch()
self.resize(480, 360)
letters = 'abcdefghijklmnopqrstuvwxyz '
for i in range(1, 11):
msg = ''.join(choice(letters) for i in range(randrange(10, 250)))
QtCore.QTimer.singleShot(500 * i, lambda msg=msg, i=i:
self.addMessage(msg, i & 1))
def addMessage(self, text, sent=False):
message = WrapLabel(text)
message.setStyleSheet('''
WrapLabel {{
border: 1px outset palette(dark);
border-radius: 8px;
background: {};
}}
'''.format(
'#fff8c7' if sent else '#ceffbd')
)
self.messages.append(message)
self.widget().layout().addWidget(message,
alignment=QtCore.Qt.AlignRight if sent else QtCore.Qt.AlignLeft)
QtCore.QTimer.singleShot(0, self.scrollToBottom)
def scrollToBottom(self):
QtWidgets.QApplication.processEvents()
self.verticalScrollBar().setValue(
self.verticalScrollBar().maximum())
def resizeEvent(self, event):
sb = self.verticalScrollBar()
atMaximum = sb.value() == sb.maximum()
maxWidth = max(self.width() * self.marginRatio,
self.width() - self.margin) - sb.sizeHint().width()
for message in self.messages:
message.setMaximumWidth(maxWidth)
super().resizeEvent(event)
if atMaximum:
sb.setValue(sb.maximum())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.