0

I am creating a tool that that will have a search option. After searching I am creating a dataframe and displaying it in QTableView. 1- I need to show a radio button against each row in table view. Radio button will be the first column in Table view. I have found table view method setIndexWidget() but not sure how to implement it.

2- I have 3 columns in tableview MemberNumber,FirstName,LastName once I will select radio button against my 1st row and click on show Data Button it should show member number in msg box.

Below is the code which I have written till now-

import sys
import pandas as pd
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QAbstractTableModel, Qt
from PyQt5.QtWidgets import (QWidget, QLabel, QPushButton, QGridLayout, QDesktopWidget, 
                             QApplication, QTableView,QGroupBox,QLineEdit,QRadioButton,QModelIndex)
 
class Radio_button(QWidget):
  
    def __init__(self):
        super().__init__()
        
        self.initUI()

    def initUI(self):
        # set window title
        self.setWindowTitle('Search Window')
        self.show()  
#        self.setFixedSize(650, 450)
        
        window_layout = QGridLayout()
        rect = QtCore.QRect(10, 10, 300, 200)
        window_layout.setGeometry(rect)
        self.setLayout(window_layout)
        
        # Radio button for male
        self.radioButton_male = QRadioButton('R1')
        
        self.table=QTableView()
        window_layout.addWidget(self.table)       
        
 
        # adding signal and slot
        self.radioButton_male.toggled.connect(lambda: self.maleselected('Male'))
        
        # Radio button for female
        self.radioButton_female = QRadioButton('R2')
         
        # adding signal and slot
        self.radioButton_female.toggled.connect(lambda: self.maleselected('Female'))
        
        # Add label
        self.label = QLabel()
        
        # Add button
        self.show_data=QPushButton('Show Data',clicked = lambda : self.showData())
                
        window_layout.addWidget(self.label,3,0)
        window_layout.addWidget(self.radioButton_male,1,0)
        window_layout.addWidget(self.radioButton_female,2,0)
        window_layout.addWidget(self.table,0,0)
        window_layout.addWidget(self.show_data,4,0)
        self.radioButton=QRadioButton()
        self.index=0
        self.table.setIndexWidget(QModelIndex,self.radioButton)

     
    def maleselected(self, gender):
            self.label.setText("You are "+gender)
            
    def createdf(self):
        data = {'Name':['Tom', 'nick', 'krish', 'jack'],
        'Age':[20, 21, 19, 18]}
        df=pd.DataFrame(data)
        return df
    
    def showData(self):
        
        model = pandasModel(self.createdf())
        self.table.setModel(model)
        
                

     
class pandasModel(QAbstractTableModel):

    def __init__(self, data):
        QAbstractTableModel.__init__(self)
        self._data = data

    def rowCount(self, parent=None):
        return self._data.shape[0]

    def columnCount(self, parnet=None):
        return self._data.shape[1]

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if role == Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
        return None

    def headerData(self, col, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self._data.columns[col]
        return None  
             
def main():
    app = QApplication(sys.argv)
    mc = Radio_button()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
musicamante
  • 41,230
  • 6
  • 33
  • 58
atiwari
  • 19
  • 2
  • `self.setIndexWidget(self.table.model().index(row, 0, self.radioButton)`. Obviously, it will only work as long as there's a model already set on the table, so you can only do that *after* calling `self.table.setModel()`. Also note that an index widget covers the whole index, so the data for that cell will be partially or completely hidden by the radio button. – musicamante Dec 17 '21 at 11:47
  • @musicamate I have updated my code something like ```def showData(self): model = pandasModel(self.createdf()) self.table.setModel(model) self.table.setIndexWidget(self.table.model().index(row, 0), self.radioButton)``` but this is not working. I want a extra column in my table that will have a Widget radio button. – atiwari Dec 20 '21 at 06:12
  • You didn't say that you wanted *another* column. If with "it is not working" you mean that it doesn't show in that column, that does *not* mean that it's not working. If you want another column, you have to implement it in the model by *shifting* all columns. – musicamante Dec 20 '21 at 09:19
  • It's not working that mean radio button is not showing in table. Either way it will work. If I am able to show radio button in first column or in a separate column , which should be first column. Kindly check my code and give me some sample code if possible. I am new to python – atiwari Dec 20 '21 at 09:35
  • I *have* checked your code, adding `self.table.setIndexWidget(self.table.model().index(0, 0), self.radioButton)` (or `self.table.setIndexWidget(model.index(0, 0), self.radioButton)`) **does** show the radio. Obviously, `row` has to be specified (I used `row` as I don't know the row at which you want the radio), and you cannot use `setIndexWidget()` multiple times with the *same* widget: you need to use a different radio for each row. – musicamante Dec 20 '21 at 11:57
  • I am able to create a radio button for all the rows showing in Table using given pice of code ```def showData(self): data=self.createdf() model = pandasModel(data) self.table.setModel(model) for idx, value in enumerate(data['Employee ID'].unique()): self.idx =QRadioButton(str(value)) # self.idx.toggled.connect(lambda: self.showRadioData(value)) # self.radioButton.setText(str(value)) self.table.setIndexWidget(self.table.model().index(idx, 0), self.idx)``` – atiwari Dec 21 '21 at 09:24
  • If you want, you can provide your own answer. Note that since you're in the same function, you already have a reference to the model: just use `self.table.setIndexWidget(model.index(idx, 0), self.idx)`. Also note that: 1. creating instance attributes in a for loop is useless, as the attribute is always overwritten at every iteration of the loop; 2. `value` is a local scope in the loop and will always be the *last* of the loop, so you must use `radioButton.toggled.connect(lambda toggled, value=value: self.showRadioData(value))`. – musicamante Dec 21 '21 at 09:38

1 Answers1

0

Please find the answer below-

import pandas as pd
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QAbstractTableModel, Qt
from PyQt5.QtWidgets import (QWidget, QLabel, QPushButton, QGridLayout, QDesktopWidget, 
                             QApplication, QTableView,QGroupBox,QLineEdit,QRadioButton,QButtonGroup)
 
class Radio_button(QWidget):
  
    def __init__(self):
        super().__init__()
        
        self.initUI()

    def initUI(self):
        # set window title
        self.setWindowTitle('Search Window')
        self.show()  
#        self.setFixedSize(650, 450)
        
        window_layout = QGridLayout()
        rect = QtCore.QRect(10, 10, 300, 200)
        window_layout.setGeometry(rect)
        self.setLayout(window_layout)
        
        # Radio button for male
        self.radioButton_male = QRadioButton('R1')
        
        self.table=QTableView()
        window_layout.addWidget(self.table)       
        
 
        # adding signal and slot
        self.radioButton_male.toggled.connect(lambda: self.maleselected('Male'))
        
        # Radio button for female
        self.radioButton_female = QRadioButton('R2')
         
        # adding signal and slot
        self.radioButton_female.toggled.connect(lambda: self.maleselected('Female'))
        
        # Add label
        self.label = QLabel()
        
        # Add button
        self.show_data=QPushButton('Show Data',clicked = lambda : self.showData())
        
        self.showRadio_data=QPushButton('Show Radio Data',clicked = lambda : self.showRadioData())
        
         
       # Add Widgets to layout 
        window_layout.addWidget(self.label,3,0)
        window_layout.addWidget(self.radioButton_male,1,0)
        window_layout.addWidget(self.radioButton_female,2,0)
        window_layout.addWidget(self.table,0,0)
        window_layout.addWidget(self.show_data,4,0)
        window_layout.addWidget(self.showRadio_data,5,0)
        
        
        
    def showRadioData(self,value):
#        self.label.setText(self.radioButton.text())
        self.label.setText(str(value))
        
        

     
    def maleselected(self, gender):
            self.label.setText("You are "+gender)
            
    def createdf(self):
        data = {'Select':['','','',''],
                'Employee ID':[12,13,14,15],
                'Name':['Tom', 'nick', 'krish', 'jack'],
                'Age':[20, 21, 19, 18]}
        df=pd.DataFrame(data)
        return df
    
    def showData(self):
        data=self.createdf()
        model = pandasModel(data)
        self.table.setModel(model)
        for idx, value in enumerate(data['Employee ID'].unique()):
            self.radioButton =QRadioButton(str(value))
            self.radioButton.toggled.connect(lambda toggled, _value=value: self.showRadioData(_value)) 
            self.table.setIndexWidget(self.table.model().index(idx, 0), self.radioButton)
             

     
class pandasModel(QAbstractTableModel):

    def __init__(self, data):
        QAbstractTableModel.__init__(self)
        self._data = data

    def rowCount(self, parent=None):
        return self._data.shape[0]

    def columnCount(self, parnet=None):
        return self._data.shape[1]

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if role == Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
        return None

    def headerData(self, col, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self._data.columns[col]
        return None  
             
def main():
    app = QApplication(sys.argv)
    mc = Radio_button()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

thank you @musicamate

atiwari
  • 19
  • 2