QLabel Wrap-text výšky není změna velikosti

0

Otázka

Jak mohu opravit QLabel není klip textu při změně velikosti? To je widget, který bude umístěn uvnitř QDialog nakonec. Takže změna velikosti Dialogu se stane, když uživatel změní velikost hlavní dialogové okno.

enter image description here

enter image description here

'''
Main Navigation bar
'''
################################################################################
# imports
################################################################################
import os
import sys
import inspect
from PySide2 import QtWidgets, QtCore, QtGui


################################################################################
# widgets
################################################################################
class Context(QtWidgets.QWidget):

    def __init__(self):
        super(Context, self).__init__()

        # controls
        self.uiThumbnail = QtWidgets.QLabel()
        self.uiThumbnail.setMinimumSize(QtCore.QSize(100, 75))
        self.uiThumbnail.setMaximumSize(QtCore.QSize(100, 75))
        self.uiThumbnail.setScaledContents(True)
        self.uiThumbnail.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        self.uiThumbnail.setObjectName('thumbnail')

        self.uiDetailsText = QtWidgets.QLabel()
        self.uiDetailsText.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        self.uiDetailsText.setWordWrap(True)
        self.uiDetailsText.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
        self.uiDetailsText.setOpenExternalLinks(True)

        self.uiMenuButton = QtWidgets.QPushButton()
        self.uiMenuButton.setFixedSize(QtCore.QSize(24, 24))
        self.uiMenuButton.setFocusPolicy(QtCore.Qt.NoFocus)

        # header layout
        self.headerLayout = QtWidgets.QHBoxLayout()
        self.headerLayout.setSpacing(6)
        self.headerLayout.setContentsMargins(6, 6, 6, 6)
        self.headerLayout.setAlignment(QtCore.Qt.AlignTop)
        self.headerLayout.addWidget(self.uiThumbnail)
        self.headerLayout.addWidget(self.uiDetailsText)
        self.headerLayout.addWidget(self.uiMenuButton)
        self.headerLayout.setAlignment(self.uiThumbnail, QtCore.Qt.AlignTop)
        self.headerLayout.setAlignment(self.uiMenuButton, QtCore.Qt.AlignTop)

        # frames
        self.headerFrame = QtWidgets.QFrame()
        self.headerFrame.setObjectName('panel')
        self.headerFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.headerFrame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.headerFrame.setLayout(self.headerLayout)
        
        # layout
        self.mainLayout = QtWidgets.QHBoxLayout()
        self.mainLayout.setSpacing(6)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.headerFrame)

        self.setLayout(self.mainLayout)

        self.setStyleSheet('''
            #thumbnail {
                background-color: rgb(70,70,70);
            }
            #panel { 
                background-color: rgb(120,120,120); 
                border-radius:3px;
            }
        ''')
        self.updateContext()


    # methods
    def updateContext(self):
        self.uiDetailsText.setText('''
            <span style="font-size:14px;">
                <b>A title goes here which can wrap</b>
            </span>
            <br>
            <span style="font-size:11px;">
                <b>Status:</b> Additional details go here
                <br>
                <b>User:</b>  
                User information goes here
                <br>
                <b>About:</b> Some more information
                <br>
                <b>Date:</b> 2021-07-03
                <br>
            </span>
        ''')



################################################################################
# main
################################################################################
if __name__ == '__main__':
    pass
    app = QtWidgets.QApplication(sys.argv)
    ex = Context()
    ex.resize(500,70)
    ex.show()
    sys.exit(app.exec_())

Snažil jsem se přidat to a to vůbec nepomohlo...

    # methods
    def resizeEvent(self, event):
        newHeight = self.uiDetailsText.heightForWidth(self.uiDetailsText.width())
        self.uiDetailsText.setMaximumHeight(newHeight)
        event.accept()
pyside2 python
2021-11-20 12:38:17
1

Nejlepší odpověď

0

Velikost politika je vždy QLabel Preferred (v obou směrech), a pokud zalamování nebo rich text se používá, text, uspořádání motoru se bude snažit najít optimální šířku podle obsahu. To bohužel vytváří určité problémy v rozvržení manažery, jak je vysvětleno v uspořádání dokumentace:

Použití formátovaného textu v popisku widgetu lze zavést některé problémy rozložení jeho rodič widget. Problémy se vyskytují v důsledku jak bohatý text je zpracována Qt layout manažerů, když na štítku je slovo zabalené.

Také zvažte následující řádek:

self.headerLayout.setAlignment(QtCore.Qt.AlignTop)

to bude sladit rozvržení položku (headerLayout) na vrchol headerFrame, což vytváří problémy s velikostí náznak štítku, jelikož velikost politika je Preferred. To je obvykle zbytečné (a často i odradit) nastavit zarovnání rozvržení, pokud je to nejvyšší úroveň uspořádání widget.

Bohužel, neexistuje žádné jednoduché řešení pro tyto situace, protože:

  • aby "zdarma", změna velikosti, označení nemůže mít žádné omezení velikosti;
  • jakmile widget je mapována, velikost náznak je právě to: náznak; pokud uživatel změní velikost okna, které obsahuje zalomený text, velikost vybrán uživatelem je dodržena i v případě, že výsledky v částečně skrývání textu;
  • velikost náznak považuje heightForWidth dětí pouze tehdy, když rozložení je aktivován, po té nejvyšší úrovně okno, bude to ignorovat jakýkoli náznak a bude ctí pouze na volbě uživatele, omezena minimální velikost (nebo minimální velikost náznak) widgety;
  • heightForWidth() se nazývá pouze pro widgety, které nemají dispozice, jinak rozvržení položky heightForWidth() bude povolán;

Tam jsou řešení, ale ne vždy jsou spolehlivé.

Možným řešením je změnit velikost na nejvyšší úrovni okna kdykoli výška nerespektuje widget heightForWidth(). Všimněte si, že to není zcela spolehlivé, a to není 100% bezpečné, protože to vyžaduje, aby volání resize uvnitř na událost resize. Pokud některý z rodičů má některé funkce, které působí na opožděné volání týkající se rozvržení (včetně změny geometrie), to by mohlo způsobit rekurze problémy.

class Context(QtWidgets.QWidget):
    resizing = False
    # ...
    def resizeEvent(self, event):
        super().resizeEvent(event)
        if self.resizing:
            return
        diff = self.heightForWidth(event.size().width()) - self.height()
        if diff > 0:
            self.resizing = True
            target = self
            while not target.windowFlags() & (QtCore.Qt.Window | QtCore.Qt.SubWindow):
                target = target.parent()
            target.resize(target.width(), target.height() + diff)
            self.resizing = False

Všimněte si, že pro tuto práci budete muset ještě nastavit Expanding vertikální rozměr politiky nebo odstranit řádek pro rozvržení zarovnání.

A co je nejdůležitější, to může jen být používán pouze pro jeden widget v okně, takže byste měli zvážit implementaci v nejvyšší úrovni widget.

2021-11-20 17:38:04

To způsobí, že mnoho blikání při změně velikosti. Je to úmyslné, že dialog nemůže být upravována volněji? Pro mě, jen nastavení rozšiřující vertikální rozměr politiky se zdá fungovat dobře - ale možná jsem špatně pochopil OP požadavků.
ekhumoro

@ekhumoro sakra, to bylo to čeho jsem se bál. Udělal jsem nějaké testy, včetně použití MDI oblasti a QGraphicsProxyWidget, ale moje výchozí systém nechce používat neprůhledné změna velikosti, takže rekurze, problém stále vzniká v ostatních případech, pro které systém geometrie má přednost v obraze. Jediné řešení, které jsem mohl najít byl použít pre-existující QTimer připojen k funkci, která by volání lambda (set v resizeEvent), snižuje blikání, ale pořád je to hrozné. Já vím, na skutečnost, že, alespoň na Linuxu, je možné dát pouta na změnu velikosti (mpv může dělat, že, když se snaží ->
musicamante

@ekhumoro -> respektovat poměr stran), ale stále nevím, jak to udělat, že od pythonu. Kromě toho, že, tak daleko, jak jsem pochopil, OP chce, aby bylo zajištěno, že označení je vždy správně zobrazí, pokud se snaží změnit velikost okna (zda Context je nejvyšší úrovně okno, nebo ne). To je zatím není jasné, jestli tento problém má být vyřešen cross-platform, nebo ne, ale měl jsem kontakty s ním v minulosti a věřím, že tomu tak je.
musicamante

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................