0
votes

I have created student data entry dialog using PyQt5 QTableWidget, QLineEdit, QComboBox.

Here is the PyQt5 code

import sys
from PyQt5.QtWidgets import (QDialog,
                               QApplication,
                               QGridLayout,
                               QPushButton,
                               QLabel,
                               QLineEdit,
                               QComboBox,
                               QTableWidget,
                               QTableWidgetItem,
                               QAbstractItemView)
from PyQt5.QtCore import Qt

class MyWindow(QDialog):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('Student Data Entry')

        grdLayout = QGridLayout()           

        self.lblStudentId = QLabel('Student Id')
        self.cboStudentId = QComboBox(self)
        self.cboStudentId.addItems(['1000','6001','5000','5002','9000','1004'])
        self.cboStudentId.setCurrentIndex(1)

        self.lblStudentName = QLabel('Student name',self)
        self.ledStudentName = QLineEdit(self)
        
        self.lblAge = QLabel('Age',self)
        self.ledAge = QLineEdit(self)
        self.ledAge.setAlignment(Qt.AlignCenter) 
        self.ledAge.setPlaceholderText('0')

        self.lblAdd = QLabel('Add',self)
        self.btnAdd = QPushButton('Add',self)
        self.btnAdd.clicked.connect(self.addFeeRow)        

        # student data table
        self.tblStudent = QTableWidget(self)
        self.tblStudent.setColumnCount(3)
        self.tblStudent.setShowGrid(True)
        self.tblStudent.setHorizontalHeaderLabels(('Student Id', 'Student name','Age'))
        self.tblStudent.verticalHeader().hide()
        self.tblStudent.setEditTriggers(QTableWidget.NoEditTriggers)
        self.tblStudent.setSelectionBehavior(QAbstractItemView.SelectRows) 
        self.tblStudent.setColumnWidth(0, 50)
        self.tblStudent.setColumnWidth(1, 150)
        self.tblStudent.setColumnWidth(2, 25)         

        # Add Label, LineEdit and ComboBox
        grdLayout.addWidget(self.lblStudentId,0,0)
        grdLayout.addWidget(self.lblStudentName,0,1,1,2)
        grdLayout.addWidget(self.lblAge,0,3)
        grdLayout.addWidget(self.lblAdd,0,4)

        grdLayout.addWidget(self.cboStudentId,1,0)
        grdLayout.addWidget(self.ledStudentName,1,1,1,2)
        grdLayout.addWidget(self.ledAge,1,3)
        grdLayout.addWidget(self.btnAdd,1,4)
        
        # Add table
        grdLayout.addWidget(self.tblStudent,2,0,1,4)

        grdLayout.setColumnStretch(0,1)
        grdLayout.setColumnStretch(1,1)
        grdLayout.setColumnStretch(2,1)    

        self.setLayout(grdLayout)
        
    def addFeeRow(self):
        rowCount = self.tblStudent.rowCount()
        self.tblStudent.insertRow(rowCount)
        # insert into table
        self.tblStudent.setItem(rowCount,0, QTableWidgetItem(self.cboStudentId.currentText()))
        self.tblStudent.setItem(rowCount,1, QTableWidgetItem(self.ledStudentName.text()))
        self.tblStudent.setItem(rowCount,2, QTableWidgetItem(self.ledAge.text()))
       
if __name__ == '__main__':
    app = QApplication()
    window = MyWindow()
    window.show()

enter image description here

My requirements are,

  1. when user clicks Add QPushButton or Press Enter key when Age QLineEdit is focused, Data (student id, student name, and student age) should be entered into table. Data should be entered into the table when user presses Enter key in Age QLineEdit or Add QPushButton.

  2. Also when user press Enter key in Student Id QComboBox, focus should move to next widget (Student Name). When user presses Enter key in Student Name QLineEdit, focus should move to next widget (Student Age)

In the current scenario, when user presses Enter Key in any widgets like student id, student name, Data is entering into table, which I don't want. Please provide the solution to restrict this behaviour.

1

1 Answers

0
votes

The issue about the return key triggering from everywhere is that when using a QDialog and at least a button with the autoDefault() property set, that button's clicked signal is triggered whenever the return key is pressed.

In order to disable that, the following is required:

        self.btnAdd.setAutoDefault(False)

Since you also want to control the focus using that key, then you can implement the keyPressEvent instead, ensuring that it doesn't get processed in those situations (in this case, the setAutoDefault above is theoretically not necessary anymore):

    def keyPressEvent(self, event):
        if event.key() in (Qt.Key_Return, Qt.Key_Enter):
            current = QApplication.focusWidget()
            if current == self.cboStudentId:
                self.ledStudentName.setFocus()
                return
            elif current == self.ledStudentName:
                self.ledAge.setFocus()
                return
            elif current == self.ledAge:
                self.addFeeRow()
                self.cboStudentId.setFocus()
                return
        super().keyPressEvent(event)

Finally, if you want to also change the focus when the user presses enter on the popup of the combobox, an event filter must be used:

class MyWindow(QDialog):
    def __init__(self):
        # ...
        self.cboStudentId.view().installEventFilter(self)

    def eventFilter(self, source, event):
        if (event.type() == QEvent.KeyPress and 
            event.key() in (Qt.Key_Return, Qt.Key_Enter)):
                self.ledStudentName.setFocus()
        return super().eventFilter(source, event)