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))