如果QLabel中的文本太长,该如何自动换行?

4

是否有方法使QLabel在单词太长时自动换行?我看过一些...

q_label->setWordWrap(true)

虽然有空格时它能正常工作,但如果单词太长,就会出现溢出的问题...
我想要像 word-break: break-all 这样的 web 开发方案

我也看过 QTextDocument,但它不允许设置固定宽度和非固定高度


1
QTextDocument不允许具有固定宽度和非固定高度。那么QWidget::setSizePolicy怎么样? - scopchanov
您可以创建自己的标签,在 paintEvent() 方法中使用 drawText()Qt::TextWrapAnywhere 标志。 - thibsc
5个回答

2

只需要在每个字符之间加入零宽空格

from PySide2 import QtWidgets

app = QtWidgets.QApplication()
label = QtWidgets.QLabel()
text = "TheBrownFoxJumpedOverTheLazyDog"
label.setWordWrap(True)
label.setText("\u200b".join(text))  # The magic is here.
label.show()
app.exec_()

Or you can write your own QLabel

from PySide2 import QtWidgets


class HumanLabel(QtWidgets.QLabel):
    def __init__(self, text: str = "", parent: QtWidgets.QWidget = None):
        super().__init__("\u200b".join(text), parent)
        self.setWordWrap(True)

    def setText(self, arg__1: str) -> None:
        super().setText("\u200b".join(arg__1))

    def text(self) -> str:
        return super().text().replace("\u200b", "")


app = QtWidgets.QApplication()
text = "TheBrownFoxJumpedOverTheLazyDog"
label = HumanLabel(text)
assert label.text() == text
label.show()
app.exec_()

Wikipedia: Zero-width space


0

Qt 只支持不包含 word-breakHTML 子集。或者解决方案将非常简单。

但是,也可以使用 QTextBrowser 来解决问题。它继承自 QTextEdit,并处于只读模式。在 QTextBrowser 中的 QTextDocument 就能解决问题。

QTextBrowser tb = new QTextBrowser(parent);
QTextOption opt;
opt.setWrapMode(QTextOption::WrapAnywhere); // like word-break: break-all
tb->document()->setDefaultTextOption(opt);
tb->setStyleSheet("border: none;"); // no border
tb->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); // no vertical scroller bar
tb->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); // no horizontal scroller bar


0
据我所知,目前没有一种开箱即用的方法可以自动将单词分成数行来适应 QLabel
您可以编写代码或手动在文本中插入换行符或空格以达到固定长度,并使QLabel::setWordWrap()正常工作。
QLabel *pLabel = new QLabel(this);
pLabel->setText("first line\nsecond line\nthird line\n");
pLabel->setWordWrap(true);

你也可以使用QTextDocument。它的setDefaultTextOption方法允许你设置QTextOption。而QTextOption::setWrapMode(QTextOption::WrapAnywhere)则允许在一行的任何位置换行。


0
您可以编写一个函数,每当单词大于标签的最大大小时添加一个空格。如果您想限制字符计数中的单词长度,则此代码应该可行:
void wrapLabelByCharCount(QLabel *label, int characterCount)
{
    QString text = label->text();
    int wordLength = 0;
    bool insideWord = false;
    QFontMetrics fontMetrics(label->font());
    for (int i = 0; i < text.length(); i++)
    {
        if (text[i] == ' ' || text[i] == '\t' || text[i] == '\n')
            insideWord = false;
        else
        {
            if (!insideWord)
            {
                insideWord = true;
                wordLength = 0;
            }
            ++wordLength;
        }
        if (wordLength > characterCount)
        {
            text = text.left(i) + "\n" + text.right(text.length() - i);
            label->setFixedHeight(label->height() + fontMetrics.height());
            insideWord = false;
        }
    }
    label->setText(text);
}

如果你想根据固定像素宽度来换行,那么你应该使用这个:

void wrapLabelByTextSize(QLabel *label, int widthInPixels)
{
    QString text = label->text();
    QString word = "";
    bool insideWord = false;
    QFontMetrics fontMetrics(label->font());
    for (int i = 0; i < text.length(); i++)
    {
        if (text[i] == ' ' || text[i] == '\t' || text[i] == '\n')
            insideWord = false;
        else
        {
            if (!insideWord)
            {
                insideWord = true;
                word = "";
            }
            word += text[i];
        }
        if (fontMetrics.horizontalAdvance(word) > widthInPixels)
        {
            text = text.left(i) + "\n" + text.right(text.length() - i);
            label->setFixedHeight(label->height() + fontMetrics.height());
            insideWord = false;
        }
    }
    label->setText(text);
}

以下是如何使用它们的一些示例:

q_label->setWordWrap(true); //required for this to work
wrapLabelByCharCount(q_label, 15); // wraps all words that have more than 15 characters
wrapLabelByTextSize(q_label, q_label->width()); // wraps words that exceed the width of your label (this is probably the one you want)
wrapLabelByTextSize(q_label, 25); // wraps words that exceed 25 pixels

编辑: 需要注意的是,这些函数不会调整QLabel默认字词换行器包装的文本标签大小(这也需要重新实现它以计算换行数)。您应该确保标签足够大以适应所有文本。


0

TextWrapAnywhere QLabel

继承 QLabel 并实现 paintEvent,在其中使用 drawItemText 时将文本对齐方式设置为 TextWrapAnywhere

请参考 这个问题 中的 pyqt5 示例。


我已经在C++中实现了这个功能:style()->drawItemText(&p, rect(), Qt::AlignLeft | Qt::TextWrapAnywhere, palette(), true, text()); 但是它似乎没有改变任何东西。 - Jachdich
我还没有在 C++ 中实现它,但只要 PyQt 可以工作,它就应该能正常运行。 - Ted

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接