Как сделать расширяемый по нажатию кнопки виджет?
Ситуация такая:
Имеется QScrollArea c установленным Layout Vertically.
Внутри находятся несколько QWidget с установленными значениями minimumSize-Height.
Последним в scrollAreaWidgetContents находится Vertical Spacer, который не дает виджетам расширяться, если их суммарная высота будет меньше высоты самого QScrollArea.
Сами виджеты имеют Layout in Grid и представляют собой несколько QLabel и одну QPushButton с установленной icon1:
После нажатия на кнопку в виджете должно появиться еще несколько строк Label, а кнопка должна сменить icon1 на icon2:
Как это реализовать? Можно ли это реализовать с какой-то анимацией, а не скачком из состояния 1 в состояние 2?
Или может быть имеется способ сделать это как-то иначе и с умом?
Спасибо, что уделили время!
UPD: Реализовал какими-то костылями. ИМХО.
Предположил, что можно создать виджеты заранее в состоянии 2, а потом ненужные QLabels скрыть, через hide(), по нажатию соответствующей кнопки. Обозвал все скрываемые QLabels по шаблону more_info_{}.
Логично было бы делать hide() при создании QLabel в виджете, однако, почему-то в этот момент hide() не меняет размер виджета, в котором он находится, поэтому пришлось написать еще скрипт, который проходится по всем виджетам и их закрывает.
# Тут привязываем функции к кнопкам
self.pushButton.clicked.connect(self.click_button_down)
self.pushButton_2.clicked.connect(self.click_button_down)
self.pushButton_3.clicked.connect(self.click_button_down)
# А тут обновляем чтобы виджеты появились сразу со скрытыми QLabel
self.close_opened_widgets()
Далее функция для открытия:
def click_button_down(self):
button = self.sender()
widget = button.parent()
children = widget.children()
for child in children:
if type(child) == QtWidgets.QPushButton:
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("components/icons/ArrowTop.png"),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
child.setIcon(icon)
child.setIconSize(QtCore.QSize(50, 50))
if child.objectName().find('more_info') != -1:
child.show()
button.clicked.connect(self.click_button_up) # Перепривязываем к другой функции, чтобы виджет можно было вернуть в предыдущее состояние
widget.setMinimumSize(QtCore.QSize(0, 238))
Функция для закрытия:
def click_button_up(self):
button = self.sender()
widget = button.parent()
children = widget.children()
for child in children:
if type(child) == QtWidgets.QPushButton:
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("components/icons/ArrowBottom.png"),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
child.setIcon(icon)
child.setIconSize(QtCore.QSize(50, 50))
if child.objectName().find('more_info') != -1:
child.hide()
button.clicked.connect(self.click_button_down)
widget.setMinimumSize(QtCore.QSize(0, 126))
И функция для первоначального обновления:
def close_opened_widgets(self):
for child_scroll in self.scrollAreaWidgetContents.children():
if type(child_scroll) == QtWidgets.QFrame:
child_scroll.setMinimumSize(QtCore.QSize(0, 126))
for child in child_scroll.children():
if child.objectName().find('more_info') != -1:
child.hide()
Собственно, вроде как-то работает, но я думаю, что можно лучше и проще. Если есть замечания, пишите. Спасибо.
UPD2:
ТО, что я придумал выше, работает отвратительно и после 6-7 нажатий туда-сюда программа замедляется после каждого нажатия, вплоть до полного зависания.
Ответы (1 шт):
Код, который вы предоставили, воспроизвести невозможно. Ориентируясь на ваше второе и третье изображения, один из возможных вариантов может выглядеть примерно так:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *
class CustomWidget(QWidget):
def __init__(self, item, *args, **kwargs):
super(CustomWidget, self).__init__(*args, **kwargs)
self.item = item
self.setMaximumHeight(100)
layout = QtWidgets.QGridLayout(self)
layout.addWidget(QtWidgets.QLabel('6'), 0, 0)
layout.addWidget(QtWidgets.QLabel('7'), 0, 1)
layout.addWidget(QtWidgets.QLabel('8'), 0, 2)
layout.addWidget(QtWidgets.QLabel('9'), 1, 0)
layout.addWidget(QtWidgets.QLabel('10'), 1, 1)
layout.addWidget(QtWidgets.QLabel('11'), 1, 2)
class FirstWidget(QWidget):
def __init__(self, item, *args, **kwargs):
super(FirstWidget, self).__init__(*args, **kwargs)
self.item = item
self.button = QPushButton()
self.button.setCheckable(True)
self.button.setFixedSize(90, 70)
self.button.setIcon(QIcon("head3.png"))
self.button.setIconSize(QSize(90, 70))
layout = QtWidgets.QGridLayout(self)
layout.addWidget(QtWidgets.QLabel('1'), 0, 0)
layout.addWidget(QtWidgets.QLabel('2'), 0, 1)
layout.addWidget(self.button, 0, 2)
layout.addWidget(QtWidgets.QLabel('4'), 1, 0)
layout.addWidget(QtWidgets.QLabel('5'), 1, 1)
layout.addWidget(QtWidgets.QLabel('3'), 1, 2)
def resizeEvent(self, event):
super(FirstWidget, self).resizeEvent(event)
self.item.setSizeHint(QSize(self.minimumWidth(), self.height()))
class Window(QListWidget):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
item = QListWidgetItem(self)
self.firstWidget = FirstWidget(item, self)
self.firstWidget.button.toggled.connect(self.hideChild)
self.setItemWidget(item, self.firstWidget)
self.item = QListWidgetItem(self)
self.customWidget = CustomWidget(self.item, self)
self.setItemWidget(self.item, self.customWidget)
self.state = False
QtCore.QTimer.singleShot(100, lambda: self.hideChild(self.state))
def hideChild(self, state):
self.state = state
if state:
self.firstWidget.button.setIcon(QIcon("cat.jpg"))
else:
self.firstWidget.button.setIcon(QIcon("head3.png"))
self.item.setHidden(not state)
def resizeEvent(self, event):
super(Window, self).resizeEvent(event)
self.hideChild(self.state)
self.item.setSizeHint(QSize(self.minimumWidth(), self.height()))
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Window()
w.resize(310, 200)
w.show()
sys.exit(app.exec_())




