停止焦点陷入QTableView

问题描述

MRE:

from PyQt5.QtCore import QRect,Qt,QAbstractTableModel
from PyQt5.QtWidgets import QApplication,QMainWindow,QTableView,QWidget,QVBoxLayout,QLineEdit,QListWidget
import sys,types

class MyTableModel( QAbstractTableModel ):
    def __init__( self ):
        super(MyTableModel,self).__init__()
        data = [
              [4,9,2],[1,0],[3,5,]
        self._data = data

    def data(self,index,role):
        if role == Qt.displayRole:
            return self._data[index.row()][index.column()]

    def rowCount(self,index):
        return len(self._data)

    def columnCount(self,index):
        return len(self._data[0])

class Ui_MainWindow(object):
    def setupUi(self,MainWindow):
        MainWindow.resize(600,700 )
        self.centralwidget = QWidget(MainWindow)
        self.verticalLayoutWidget = QWidget(self.centralwidget)
        self.verticalLayoutWidget.setGeometry( QRect(20,20,500,500))
        self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget)
        self.comps = []
        
        self.title_line_edit = QLineEdit(self.verticalLayoutWidget)
        self.comps.append( self.title_line_edit )
        self.verticalLayout.addWidget(self.title_line_edit)

        self.tags_list = QListWidget(self.verticalLayoutWidget)
        self.comps.append( self.tags_list )
        self.verticalLayout.addWidget(self.tags_list)
        
        # UNCOMMENT THESE LInes:
#         self.table_view = QTableView(self.verticalLayoutWidget)
#         self.comps.append( self.table_view )
#         self.table_view.setGeometry(QRect(20,200,200))
#         self.verticalLayout.addWidget(self.table_view)
#         self.table_view.setModel( MyTableModel() )

        self.title_line_edit2 = QLineEdit(self.verticalLayoutWidget)
        self.comps.append( self.title_line_edit2 )
        self.verticalLayout.addWidget(self.title_line_edit2)
        
        MainWindow.setCentralWidget(self.centralwidget)

class MyWindow(QMainWindow):
    def __init__(self):
        super(MyWindow,self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        def focus_in_event( self,event ):
            self.original_stylesheet = self.styleSheet()
            self.setStyleSheet( 'border:1px solid rgb(0,255,0);' )
        def focus_out_event( self,event ):
            self.setStyleSheet( self.original_stylesheet )
        for comp in self.ui.comps:
            comp.focusInEvent = types.MethodType( focus_in_event,comp )
            comp.focusOutEvent = types.MethodType( focus_out_event,comp )

app = QApplication(sys.argv)
application = MyWindow()
application.show()
sys.exit(app.exec())

按原样,焦点选项卡可以很好地浏览各个组件。

但是当您取消添加QTableView的注释时,使用Tab键进入该组件意味着您无法再次使用Tab键。我尝试了Shift-Tab(在相反的循环方向上切换,但仍在表格单元格内),并尝试了Ctrl-Tab / Ctrl-Shift-Tab(似乎可以移动当前单元格)。

我根本不希望使用Tab键来浏览这些单元格(箭头导航键做同样的事情),只是希望这种“缠身”不会发生,所以我可以通过Tab / Shift-Tab键浏览所有组件像以前一样以循环方式。

我尝试了几件事,将这些行添加MyWindow.__init__的末尾:

    # seemingly no effect:
    def focus_next_prev_child( self,next ):
        return False
    self.ui.table_view.focusNextPrevChild = types.MethodType( focus_next_prev_child,comp )
    # just omits the table view from the focus cycle:
    self.ui.table_view.setFocusPolicy( Qt.NoFocus )

我还尝试拦截到达表视图的击键(再次将这些行添加MyWindow.__init__

    def keypress_event( self,key_event ):
        modifs = key_event.modifiers()
        key = key_event.key()
        def unmodified_not_keypad():
            print( f'unmodified,key: {hex( key )} text: {key_event.text()}' )
            # strangely,if you press Shift-Tab,this gets to here (i.e. unmodified)
            if key == Qt.Key_Tab or key == Qt.Key_Backtab:
                # what might I do here? 
                # how might I find the next component in the cycle (forwards or backwards)?
                return True
        switcher = {
            0x00000000: unmodified_not_keypad,}
        def print_invalid():
            print( f'invalid,hex( modifs): {hex(modifs)}' )
        # if any called function returns True this means skip the default action...
        if switcher.get( int( modifs ),print_invalid )():
            return
        # execute default action:
        QTableView.keyPressEvent( self,key_event )
    self.ui.table_view.keyPressEvent = types.MethodType( keypress_event,self.ui.table_view )

这确实拦截了Tab和Shift-Tab,并阻止了认操作,但是我不知道如何在焦点循环中找到合适的组件。似乎也像是大锤子,要打破螺母:大概有一种更优雅的方式来获得我想要的行为...

解决方法

如果您根本不想在所有单元格之间切换,请添加using Microsoft.Win32; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace ConsoleApp1 { class Program { static void Main(string[] args) { string EdgeVersion = string.Empty; //open the registry and parse through the keys until you find Microsoft.MicrosoftEdge RegistryKey reg = Registry.ClassesRoot.OpenSubKey(@"Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\PackageRepository\Packages"); if (reg != null) { foreach (string subkey in reg.GetSubKeyNames()) { if (subkey.StartsWith("Microsoft.MicrosoftEdge")) { //RegEx: (Microsoft.MicrosoftEdge_)(\d +\.\d +\.\d +\.\d +)(_neutral__8wekyb3d8bbwe]) Match rxEdgeVersion = null; rxEdgeVersion = Regex.Match(subkey,@"(Microsoft.MicrosoftEdge_)(?<version>\d+\.\d+\.\d+\.\d+)(_neutral__8wekyb3d8bbwe)"); //just after that value,you need to use RegEx to find the version number of the value in the registry if (rxEdgeVersion.Success) EdgeVersion = rxEdgeVersion.Groups["version"].Value; } } } Console.WriteLine("Edge Version(empty means not found): {0}",EdgeVersion); Console.ReadLine(); } } }

https://doc.qt.io/qt-5/qabstractitemview.html#tabKeyNavigation-prop