Skip to content
Advertisement

Is there a way to filter widgets in a ScrollArea with a QLineEdit based on specific attributes?

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?

my app

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

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement