Building on to an awesome answer from here by eyllanesc, I have added QListWidget to the collapsible box.
There is a text box below where user will provide search string and my aim is to highlight that item in the QListWidget (if present).
The current code works fine ie it will highlight the text and scroll it to top if the QToolButton is already expanded but it will just open and highlight the item but wont scroll it to top if it is not already expanded. (So the user now doesn't know if he has found the item or not as he cant see it highlighted.) Strange thing is if I press enter again then it will scroll it to top.
I tried various things like making the QlistWidget active, in focus etc but didnt help.
Please tell me what I am missing so that I dont need to press Enter twice in case the QToolButton is not expanded already.
EDIT: Removing the animation part from code as suggested.
import time
from PyQt5 import QtCore
from PyQt5.QtWidgets import QMainWindow, QListWidget, QLabel, QApplication, QVBoxLayout, \
QWidget, QSizePolicy, QToolButton, QScrollArea, QFrame, QDockWidget, QLineEdit, QHBoxLayout, QAbstractItemView
collapsed_list = ['What', 'should', 'be', 'done', 'to', 'fix', 'this', 'issue?', 'I', 'am', 'confused']
class CollapsibleDemo(QWidget):
def __init__(self, title="", parent=None):
super(CollapsibleDemo, self).__init__(parent)
self.toggle_button = QToolButton(
text=title, checkable=True, checked=False
)
self.toggle_button.setSizePolicy(
QSizePolicy.Expanding, QSizePolicy.Fixed
)
self.toggle_button.setToolButtonStyle(
QtCore.Qt.ToolButtonTextBesideIcon
)
self.toggle_button.setArrowType(QtCore.Qt.RightArrow)
self.toggle_button.pressed.connect(self.on_pressed)
self.content_area = QScrollArea(
maximumHeight=0, minimumHeight=0
)
self.content_area.setSizePolicy(
QSizePolicy.Expanding, QSizePolicy.Fixed
)
self.content_area.setFrameShape(QFrame.NoFrame)
lay = QVBoxLayout(self)
lay.setSpacing(0)
lay.setContentsMargins(10, 10, 1, 1)
lay.addWidget(self.toggle_button)
lay.addWidget(self.content_area)
@QtCore.pyqtSlot()
def on_pressed(self):
checked = self.toggle_button.isChecked()
self.toggle_button.setArrowType(
QtCore.Qt.DownArrow if not checked else QtCore.Qt.RightArrow
)
if not checked:
self.content_area.setMaximumHeight(self.content_height + self.collapsed_height)
else:
self.content_area.setMaximumHeight(0)
def setContentLayout(self, layout):
self.content_area.setLayout(layout)
self.collapsed_height = (
self.sizeHint().height() - self.content_area.maximumHeight()
)
self.content_height = layout.sizeHint().height()
def set_text(self, title):
self.toggle_button.setText(title)
class Try(QMainWindow):
def __init__(self, ):
super().__init__()
self.width = 800
self.height = 800
self.init_ui()
def init_ui(self):
self.resize(self.width, self.height)
self.create_background()
self.add_collapsed_list_box()
self.add_find_text_box()
self.vlay.addStretch()
self.find_text_box.setFocus()
def create_background(self):
dock = QDockWidget()
self.setCentralWidget(dock)
dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
scroll = QScrollArea()
dock.setWidget(scroll)
content = QWidget()
scroll.setWidget(content)
scroll.setWidgetResizable(True)
self.vlay = QVBoxLayout(content)
self.vlay.setSpacing(10)
def add_collapsed_list_box(self):
self.box = CollapsibleDemo(f"Whats inside here!")
self.vlay.addWidget(self.box)
lay_diff = QVBoxLayout()
self.qlist = QListWidget()
self.qlist.addItems(collapsed_list)
lay_diff.addWidget(self.qlist)
self.box.setContentLayout(lay_diff)
def add_find_text_box(self):
self.find_text_box = QLineEdit("am")
find_label = QLabel(" Search text: ")
enter_label = QLabel(" (Press Enter)")
hlayout = QHBoxLayout()
hlayout.addWidget(find_label)
hlayout.addWidget(self.find_text_box)
hlayout.addWidget(enter_label)
hlayout.addStretch(3)
self.vlay.addLayout(hlayout)
self.find_text_box.returnPressed.connect(self.find_selected)
def find_selected(self):
user_text = self.find_text_box.text()
if user_text in collapsed_list:
if not self.box.toggle_button.isChecked():
self.box.on_pressed()
self.box.toggle_button.setChecked(True)
item = self.qlist.findItems(user_text, QtCore.Qt.MatchRegExp)[0]
item.setSelected(True)
self.qlist.scrollToItem(item, QAbstractItemView.PositionAtTop)
if __name__ == "__main__":
app = QApplication([])
window = Try()
window.show()
app.exec()