There are two main ways to fix this.
The first, and simplest, way is to use setTabKeyNavigation to completely disable moving between cells using the tab-key. The arrow keys must then be used to navigate between cells in the table.
The second way is to modify the keypress event handing for the table, so that Tab in the last cell and ShiftTab in the first cell moves the focus to the next/previous widget.
The demo script below demonstrates both these approaches:
import sys
from PyQt5 import QtCore, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableWidget(3, 3)
self.button = QtWidgets.QPushButton('Disable Table Tabbing', self)
self.button.clicked.connect(self.handleButton)
layout = QtWidgets.QGridLayout(self)
layout.addWidget(self.edit, 0, 0)
layout.addWidget(self.combo, 0, 1)
layout.addWidget(self.table, 1, 0, 1, 2)
layout.addWidget(self.button, 2, 0, 1, 2)
self.table.installEventFilter(self)
self.edit.setFocus()
def handleButton(self):
if self.table.tabKeyNavigation():
self.button.setText('Enable Table Tabbing')
self.table.setTabKeyNavigation(False)
else:
self.button.setText('Disable Table Tabbing')
self.table.setTabKeyNavigation(True)
def eventFilter(self, source, event):
if (event.type() == QtCore.QEvent.KeyPress and
source is self.table and source.isEnabled() and
source.tabKeyNavigation()):
index = self.table.currentIndex()
if event.key() == QtCore.Qt.Key_Backtab:
if index.row() == index.column() == 0:
QtWidgets.QAbstractScrollArea.focusNextPrevChild(
self.table, False)
return True
elif event.key() == QtCore.Qt.Key_Tab:
model = self.table.model()
if (index.row() == model.rowCount() - 1 and
index.column() == model.columnCount() - 1):
QtWidgets.QAbstractScrollArea.focusNextPrevChild(
self.table, True)
return True
return super(Window, self).eventFilter(source, event)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 100, 400, 250)
window.show()
sys.exit(app.exec_())