我有一个标签,有时包含没有空格的长文本(计算机中的路径)。
因此,自动换行会非常奇怪。
是否有一种方法可以使标签的自动换行在单词中间断开,而不仅仅是在空格处?
我有一个标签,有时包含没有空格的长文本(计算机中的路径)。
因此,自动换行会非常奇怪。
是否有一种方法可以使标签的自动换行在单词中间断开,而不仅仅是在空格处?
QLabel *thisLabel;
QString *pathName;
QString *pathNameClean;
当然,还需要在某个地方定义这个标签。 如果能简单点就更好了....
thisLabel->setWordWrap(true);
只有当单词有断点时,才能这样做(应避免哪些路径)。
因此,如果您以后需要用它进行QFile操作,请将实际路径保留在单独的字符串中。 然后手动为每行号定义一个字符,并将空格插入字符串中... 所以我们说50个字符是一个好的宽度...
pathNameClean = new QString(pathName);
int c = pathName->length();
if( c > 50)
{
for(int i = 1; i <= c/50; i++)
{
int n = i * 50;
pathName->insert(n, " ");
}
}
thisLabel->setText(pathName);
Shazam……没有原始空格的模拟WordWrap……
请记住,pathName字符串现在仅用于漂亮的QLabel显示目的,而pathNameClean字符串是实际路径。如果您尝试使用空格注入路径打开文件,则Qt程序将崩溃。
(如果没有简单的类方法,可能只需要几行代码即可解决问题......这就是问题解决是程序员最好的工具的原因!)
一种方法是使用QTextOption类和QTextDocument代替QLabel。这样可以使用QTextOption::WrapMode。 QTextOption::WrapAtWordBoundaryOrAnywhere
可以满足您的需求。
我在2021年也遇到了同样的问题,所以在这里我将与您分享到目前为止我发现的一些最佳答案。
子类化QLabel
并实现paintEvent
,在此处您可以设置文本对齐方式为TextWrapAnywhere
,当您使用drawItemText
时。
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QStyleOption, QVBoxLayout, QWidget, QStyle
class SuperQLabel(QLabel):
def __init__(self, *args, **kwargs):
super(SuperQLabel, self).__init__(*args, **kwargs)
self.textalignment = Qt.AlignLeft | Qt.TextWrapAnywhere
self.isTextLabel = True
self.align = None
def paintEvent(self, event):
opt = QStyleOption()
opt.initFrom(self)
painter = QPainter(self)
self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self)
self.style().drawItemText(painter, self.rect(),
self.textalignment, self.palette(), True, self.text())
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setFixedSize(100, 200)
self.label = QLabel()
self.label.setWordWrap(True)
self.label.setText("1111111111111111111111111111")
self.slabel = SuperQLabel()
self.slabel.setText("111111111111111111111111111")
self.centralwidget = QWidget()
self.setCentralWidget(self.centralwidget)
self.mainlayout = QVBoxLayout()
self.mainlayout.addWidget(self.label)
self.mainlayout.addWidget(self.slabel)
self.centralwidget.setLayout(self.mainlayout)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
根据 @ekhumoro 提供的 这个答案(在 op 的评论中),如果您想要基于逗号换行,可以在要换行的字符后插入零宽度空格并使用内置的换行函数。
以下是一个示例:
from PyQt5.QtCore import QRect, Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QStyleOption, QStylePainter, QVBoxLayout, QWidget, QStyle
class CommaWrapableQLabel(QLabel):
def __init__(self, *args, **kwargs):
super(CommaWrapableQLabel, self).__init__(*args, **kwargs)
def setWordWrapAtAnychar(self, char):
newtext = self.text().replace(char, f"{char}\u200b")
self.setText(newtext)
self.setWordWrap(True)
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setFixedSize(100, 200)
self.label = QLabel()
self.label.setWordWrap(True)
self.label.setText(
'Dog,Rabbit,Train,Car,Plane,Cheese,Meat,Door,Window')
self.slabel = CommaWrapableQLabel()
self.slabel.setText(
'Dog,Rabbit,Train,Car,Plane,Cheese,Meat,Door,Window')
self.slabel.setWordWrapAtAnychar(",")
self.centralwidget = QWidget()
self.setCentralWidget(self.centralwidget)
self.mainlayout = QVBoxLayout()
self.mainlayout.addWidget(self.label)
self.mainlayout.addWidget(self.slabel)
self.centralwidget.setLayout(self.mainlayout)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
正如其他答案所述,您可以重新实现 paintEvent()
以传递 Qt::TextWrapAnywhere
标志给 QLabel
。
但是,覆盖 paintEvent()
可能会导致意外的副作用,因为 paintEvent()
的默认实现除了绘制文本之外还包含很多额外的功能。
事实上,传递到 QStyle :: drawItemText
的对齐标志存储在私有成员 QLabelPrivate :: align
中。我想到了强制重写它的值并将其设置为 Qt::TextWrapAnywhere
标志,这有效。这种解决方法需要一些 C ++ 黑魔法。
class WorkaroundLabel: public QLabel {
Q_OBJECT
public:
WorkaroundLabel(QString text, QWidget* parent): QLabel(text, parent) {
setWordWrap(true);
ushort* p;
if (FindAlignAddr(&p)) {
*p = (*p | Qt::TextWrapAnywhere);
} else {
// workaround failed
}
}
virtual ~WorkaroundLabel() {}
protected:
// "ushort align;" in qtbase/src/widgets/widgets/qlabel_p.h
bool FindAlignAddr(ushort** out) {
Qt::Alignment align = alignment();
void* d_raw = (void*) d_ptr.data();
ushort* p = reinterpret_cast<ushort*>(d_raw);
for (int i = 0; i < 1024; i += 1) {
setAlignment(Qt::AlignLeft);
ushort a = *p;
setAlignment(Qt::AlignRight);
ushort b = *p;
if (a != b) {
*out = p;
setAlignment(align);
return true;
}
p++;
}
setAlignment(align);
return false;
}
};
在2020年,PySide2就是这样的:
tmp = QLabel()
tmp.setWordWrap(True)
ZWSP
(U+200A
)-零宽度空格。如果您使用该字符,则文本将在插入它的位置换行,但当它适合时仍将显示为无空格。 - MarSoft软连字符
(U+00AD
),则单词换行的位置将有连字符,但对于未换行的文本部分没有视觉效果。 - MarSoft