QLabel & Word Wrap:如何以逗号为基础换行(与空格)
Posted
技术标签:
【中文标题】QLabel & Word Wrap:如何以逗号为基础换行(与空格)【英文标题】:QLabel & Word Wrap : How to break line base on a comma (vs space) 【发布时间】:2021-05-20 18:38:09 【问题描述】:我正在尝试使用没有空格但用逗号分隔的文本创建多行 QLabel
。
例如:'猫、狗、兔子、火车、汽车、飞机、奶酪、肉、门、窗'
我发现setWordWrap
可以使用多行,但它会根据空格中断。
如何根据逗号换行?
这是一个代码示例:
from PySide2.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setGeometry(500,100,50,100)
line = QLabel()
line.setMaximumWidth(150)
line.setText('Cat,Dog,Rabbit,Train,Car,Plane,Cheese,Meat,Door,Window')
line.setWordWrap(True)
self.setCentralWidget(line)
self.show()
if __name__ == '__main__':
app = QApplication([])
window = MainWindow()
app.exec_()
【问题讨论】:
您需要将单词全部放在不同的行上,或者像自动换行一样适合容器? 我希望拥有与自动换行相同的机制。在这个例子中,它应该在 Car 之后中断, @Pythmalion 一个快速而肮脏的解决方法是在每个逗号之后插入一个 zero-width-space (\u200b
),因为在 any 类型的空格之后换行会中断。
@ekhumoro 谢谢,也许有点脏,但它使工作。在我看来,这是一个/解决方案!
【参考方案1】:
一种方法是根据QLabel
大小编辑文本。
在每个行大小事件上都会触发以下触发器,因此这是一个成本高昂的解决方案。
首先我们添加一个信号:
class MainWindow(QMainWindow):
resized = QtCore.pyqtSignal()
然后我们用一个方法连接信号,将 wordwrap 设置为 False 并添加自定义调整大小事件,每次标签获得新大小时触发:
self.line.setWordWrap(False)
self.line.resizeEvent = self.on_resize_event
self.resized.connect(self.add_spaces)
on_resize_event
处理大小变化并触发add_spaces
:
def on_resize_event(self, event):
if not self._flag:
self._flag = True
self.resized.emit()
QtCore.QTimer.singleShot(100, lambda: setattr(self, "_flag", False))
print(f"Resized line: self.line.size()")
return super(MainWindow, self).resizeEvent(event)
最后我们有一个add_spaces
方法,它计算最大行长度并以逗号分隔。
def add_spaces(self):
size = self.line.size()
text = self.mystring
result_string = ""
temp_label = QLabel()
temp_text = ""
#Split the chunks by delimiter
chunks = text.split(",")
for i,chunk in enumerate(chunks):
temp_text += chunk + ",";
if len(chunks) > i+1:
temp_label.setText(temp_text + chunks[i+1] + ",")
width = temp_label.fontMetrics().boundingRect(temp_label.text()).width()
if width >= size.width():
result_string += temp_text + "\n"
temp_text = ""
else:
result_string += temp_text
self.line.setText(result_string)
完整代码:
from PyQt5 import QtCore
from PyQt5.QtWidgets import QMainWindow, QLabel, QApplication
class MainWindow(QMainWindow):
resized = QtCore.pyqtSignal()
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self._flag = False
self.line = QLabel()
self.line.setStyleSheet("background-color: grey;color:white;")
self.line.setMaximumWidth(300)
self.line.setMinimumWidth(20)
self.mystring = 'Cat,Dog,Rabbit,Train,Car,Plane,Cheese,Meat,Door,Window,very,long,list of words,list of words,word,word,word,list of word,word,list of word,list of word'
self.line.setText(self.mystring)
self.setCentralWidget(self.line)
self.line.setWordWrap(False)
self.line.resizeEvent = self.on_resize_event
self.resized.connect(self.add_spaces)
self.show()
self.add_spaces()
def on_resize_event(self, event):
if not self._flag:
self._flag = True
self.resized.emit()
QtCore.QTimer.singleShot(100, lambda: setattr(self, "_flag", False))
print(f"Resized line: self.line.size()")
return super(MainWindow, self).resizeEvent(event)
def add_spaces(self):
size = self.line.size()
text = self.mystring
result_string = ""
temp_label = QLabel()
temp_text = ""
#Split the chunks by delimiter
chunks = text.split(",")
for i,chunk in enumerate(chunks):
temp_text += chunk + ",";
if len(chunks) > i+1:
temp_label.setText(temp_text + chunks[i+1] + ",")
width = temp_label.fontMetrics().boundingRect(temp_label.text()).width()
if width >= size.width():
result_string += temp_text + "\n"
temp_text = ""
else:
result_string += temp_text
self.line.setText(result_string)
if __name__ == '__main__':
app = QApplication([])
window = MainWindow()
app.exec_()
【讨论】:
不建议在resizeEvent
中更改几何图形,因为这很容易导致递归,特别是对于像 QLabel 这样具有自适应大小提示的小部件。
@musicamante 是的,这是真的。 resizeEvent
应该如何处理?目前我将其更改为有 100 毫秒的延迟以防止这种情况发生。
感谢您花时间回答问题。可能不是答案,但我学到了其他东西,它告诉我如何克服我的另一个问题:)
@BlueGhost 它根本不应该调用调整大小,并且一个好的(但远非简单)实现需要适当的 QLabel 子类,至少覆盖 resizeEvent
到计算正确的自动换行,hasHeightForWidth
和 heightForWidth
用于适当的“比率”提示,sizeHint
用于可能的“最终”提示,setText
用于最小尺寸甚至可能是paintEvent;如果保留一个内部 QTextDocument(这是 QLabel 实际所做的),所有这些显然会更好。以上是关于QLabel & Word Wrap:如何以逗号为基础换行(与空格)的主要内容,如果未能解决你的问题,请参考以下文章
CSS 换行知多少: word-wrap && word-break && white-space && word-spacing
我可以将 word-wrap:break-word 设置为提交类型的输入吗?