I’m doing an app in PyQt through Qt Designer and I’ve populated a (container widget inside a) Scroll Area with a list of cards (custom widgets that contains informations). I’ve put outside of the scroll area a QLineEdit and I want to use this QLineEdit to filter the cards based on specific attributes of each card (name, id, username). Is there any way to do this?
I know the question is a bit poorly written, but I’m a bit lost on how should I approach this problem. I tried to search for “searchbar” and “filter”, but nothing looks like what I need.
Here’s a sample of my current code (without any attempt of implementing the search function):
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# users_df: dataframe with users data
users_df, groups_df = extract_load_data()
# scrollArea
scroll_area = self.ui.scrollArea_cards_members
# we create a widget container
content_widget = QWidget()
# we set this container as the widget of the scroll area
scroll_area.setWidget(content_widget)
scroll_area.setWidgetResizable(True)
# set layout
self.scroll_layout = QVBoxLayout(content_widget)
# iterate in the dataframe
for idx in users_df.index:
member_series = users_df.iloc[idx]
self.member_card = MemberCard(member_series)
self.scroll_layout.addWidget(self.member_card)
# make the scroll area justified top
self.scroll_layout.addStretch()
self.show()
And the MemberCard looks like:
class MemberCard(QWidget):
'''
Member card widget class
'''
def __init__(self, member_series, parent=None):
'''
Parameters
----------
card_container:
member_series: pd.Series
series formed by the integer location of the ```users_df```
(member_series = users_df.iloc[x])
'''
super(MemberCard, self).__init__(parent)
self.dict = dict(member_series)
# Ui_MemberCard: class created by QtDesigner
self.card = Ui_MemberCard()
self.card.setupUi(self)
self.fill_card_info()
def fill_card_info(self,):
'''
Method that fills the informations of the Member Card
'''
self.card.name_label.setText(self.dict['name'])
self.card.username.setText(self.dict['username'])
self.card.id.setText(str(self.dict['id']))
self.card.joined_in.setText(self.dict['created_at'])
Advertisement
Answer
What @jfaccioni commented in the original post was really a clear, easy, and effective solution, so I will make this question as answered posting it here. To connect these fields you need to create one method to update the scrollArea and one function to verify the matches. For me it was something like this:
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# users_df: dataframe with users data
users_df, groups_df = extract_load_data()
# scrollArea
scroll_area = self.ui.scrollArea_cards_members
# we create a widget container
content_widget = QWidget()
# we set this container as the widget of the scroll area
scroll_area.setWidget(content_widget)
scroll_area.setWidgetResizable(True)
# set layout
self.scroll_layout = QVBoxLayout(content_widget)
# iterate in the dataframe
for idx in users_df.index:
member_series = users_df.iloc[idx]
self.member_card = MemberCard(member_series)
self.scroll_layout.addWidget(self.member_card)
# make the scroll area justified top
self.scroll_layout.addStretch()
self.show()
def update_members(self, string):
'''
Method that hides/shows member cards based on a search string
Parameters
----------
string: str
string input on the searchbar
'''
for member_card in self.member_cards:
visible = filter_members(string, member_card)
member_card.setVisible(visible)
And the auxiliary filter_members function:
def filter_members(string, member_card):
'''
Filter function that can filter a member_card based on a string
The member_card will be filtered by name, username, or id
Parameters
----------
string: str
string input in the QLineEdit searchbar
member_card: :obj: MemberCard
MemberCard object to be tested against the string
Returns
-------
bool
'''
member_id = str(member_card.dict['id'])
member_name = member_card.dict['name'].lower()
member_username = member_card.dict['username'].lower()
string = string.lower()
return ((string in member_id) or (string in member_name) or (string in member_username))
