PyQt: как предотвратить увеличение QPushButton до размера длинного текстаPython

Программы на Python
Anonymous
 PyQt: как предотвратить увеличение QPushButton до размера длинного текста

Сообщение Anonymous »

У меня есть QPushButton, ширину которого я бы хотел сохранить на фиксированном проценте от ширины его родительского HBoxLayout, чтобы он не увеличивался, когда для его текста установлено что-то очень длинное.
Изображение

Сейчас, когда текст кнопки имеет очень длинный текст, кнопка расширяется, чтобы соответствовать этому длинному тексту, а также расширяет HBoxLayout и его предков до самого окна.
Изображение

Я планирую создать собственное вычеркивание с помощью QFontMetrics, чтобы попытаться создать вычеркнутый текст, соответствующий текущей ширине кнопки. Но я также хочу обработать случай, когда пользовательский результат elide немного шире, чем ожидалось: я не хочу, чтобы это приводило к увеличению ширины всего окна. Если текст слишком широкий, я бы предпочел просто обрезать его.
Итак: вот одна попытка, которая будет иметь смысл только в том случае, если размер окна не подлежит изменению:

Код: Выделить всё

self.ui.pushButton.setFixedWidth(self.ui.pushButton.width())
Добавление этой строки успешно предотвращает рост виджета — более длинный текст просто обрезается, — но также делает виджет более узким:
Изображение

В конечном приложении у меня есть 2 метки и поле со списком в этом же HBoxLayout - я тоже не хочу, чтобы они сжимались/уменьшались.
Вероятно, это связано с тем, что я не понимаю, как различные подсказки по размеру и политики размера работают вместе. Возвращаясь к исходному вопросу, как правильно сделать эту кнопку с «принудительным закрытием» с ее «полной» «нормальной» шириной?
Ниже приведен код:
guiTest.py (код верхнего уровня):

Код: Выделить всё

from widthTest_ui import Ui_Dialog
from PyQt5.QtWidgets import QDialog,QApplication
import sys

class widthTestDialog(QDialog,Ui_Dialog):
def __init__(self,parent):
QDialog.__init__(self)
self.parent=parent
self.ui=Ui_Dialog()
self.ui.setupUi(self)
# self.ui.pushButton.setFixedWidth(self.ui.pushButton.width())
self.txt=''

def onClick(self,e):
self.txt+='a'
self.ui.pushButton.setText(self.txt)

def main():
app = QApplication(sys.argv)
global w # so that eFilter can call methods of the top level widget
w = widthTestDialog(app)
w.show()
sys.exit(app.exec_())

if __name__ == "__main__":
main()
widthTest_ui.py — из pyuic5:

Код: Выделить всё

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(176, 87)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.pushButton = QtWidgets.QPushButton(Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
self.pushButton.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(12)
self.pushButton.setFont(font)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.verticalLayout.addLayout(self.horizontalLayout)

self.retranslateUi(Dialog)
self.pushButton.clicked.connect(Dialog.onClick) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)

def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton.setText(_translate("Dialog", "PushButton"))
ОБНОВЛЕНИЕ на основе комментариев:
Как было предложено, раскомментирование этой строки в init и использование sizeHint работает — виджет заполняет «первоначально ожидаемую» ширину и не увеличивается по мере того, как текст становится слишком длинным:

Код: Выделить всё

self.ui.pushButton.setFixedWidth(self.ui.pushButton.sizeHint().width())
ПРИМЕЧАНИЕ: завершает ответ на первоначальный вопрос; опубликую это как ответ; часть вопроса, приведенная ниже, на самом деле просто «становится жадной» и расширяет объем первоначального вопроса, поэтому ее не нужно рассматривать здесь. Чтобы избежать этого, я бы запретил изменение размера окна.

Теперь я хотел бы посмотреть, смогу ли я повторно применить эту логику при изменении размера окна: по мере роста окна виджет увеличивается пропорционально, но затем остается там с той же логикой фиксированной ширины. Похоже, вам нужно будет «освободить» фиксированный размер, чтобы он мог изменяться пропорционально, как обычно, а затем снова исправить размер, когда изменение размера будет выполнено. Я надеялся, что это поможет, но, увы, к моменту запуска resizeEvent уже слишком поздно:

Код: Выделить всё

def resizeEvent(self,e):
print('resized')
self.ui.pushButton.setMinimumSize(0,0)
self.ui.pushButton.setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
self.ui.pushButton.setFixedWidth(self.ui.pushButton.sizeHint().width())

Вероятно, есть способ добиться этого, обрабатывая нажатие мыши на край окна до того, как произойдет изменение размера, но это звучит немного неясно и хаотично. Интересно, есть ли лучший способ достичь общей цели - может быть, просто использовать более строгую пользовательскую логику elide и не пытаться использовать setFixedWidth.

Подробнее здесь: https://stackoverflow.com/questions/797 ... -long-text

Вернуться в «Python»