问题描述
我正在尝试使用没有空格但用逗号分隔的文本制作多行 QLabel.例如:'猫、狗、兔子、火车、汽车、飞机、奶酪、肉、门、窗'
I am trying to make a multi line QLabel with a text without space but delimited by comma. ex : 'Cat,Dog,Rabbit,Train,Car,Plane,Cheese,Meat,Door,Window'
我发现使用 setWordWrap 可以实现多行,但它会根据空格中断.
I have found that multiline is possible with setWordWrap but it breaks based on spaces.
如何根据逗号换行?
这是一个代码示例:
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_()
推荐答案
一种方法是根据 QLabel 大小编辑文本.
One way of doing it would be to edit the text according to QLabel size.
以下触发器会触发每个行大小事件,因此这是一个成本高昂的解决方案.
The following triggers on every line size event, making this a costly solution.
首先我们添加一个信号:
First we add a signal :
class MainWindow(QMainWindow): resized = QtCore.pyqtSignal()
然后我们用一个方法连接信号,设置 wordwrap 为 False 并添加自定义调整大小事件,每次标签获得新大小时触发:
Then we connect signal with a method ,set wordwrap to False and add custom resize event that triggers every time label gets a new size:
self.line.setWordWrap(False) self.line.resizeEvent = self.on_resize_event self.resized.connect(self.add_spaces)
on_resize_event 处理大小变化并触发 add_spaces :
on_resize_event which handles size changes and triggers 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 方法,它计算最大行长度并以逗号分隔.
Lastly we have a add_spaces method which calculates maximum line length and splits on comma.
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 + " " 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 + " " temp_text = "" else: result_string += temp_text self.line.setText(result_string) if __name__ == '__main__': app = QApplication([]) window = MainWindow() app.exec_()