Python 如何将所有小部件设置复制到PyQt5中的其他小部件设置?

Python 如何将所有小部件设置复制到PyQt5中的其他小部件设置?,python,pyqt5,Python,Pyqt5,下面的代码使用QtDesigner中的.ui。如果您使用REPLACE\u LISTVIEW\u CLASS=False运行它,您将得到“原始”布局-因此,如果您单击按钮,您将得到如下结果: 但是,我不喜欢上次选中项目周围的虚线选择线,只要单击列表视图中的空白区域以清除任何选择 因此,我从实现了这个类,并且由于我想保留.ui,我必须通过替换小部件来更改\uuuu init\uuuu中的列表视图类。这在原则上是有效的,如果使用REPLACE\u LISTVIEW\u CLASS=True运行代码

下面的代码使用QtDesigner中的.ui。如果您使用
REPLACE\u LISTVIEW\u CLASS=False运行它,您将得到“原始”布局-因此,如果您单击按钮,您将得到如下结果:

但是,我不喜欢上次选中项目周围的虚线选择线,只要单击列表视图中的空白区域以清除任何选择

因此,我从实现了这个类,并且由于我想保留.ui,我必须通过替换小部件来更改
\uuuu init\uuuu
中的列表视图类。这在原则上是有效的,如果使用
REPLACE\u LISTVIEW\u CLASS=True运行代码,就可以看到:

。。。但是,从上面的屏幕截图可以清楚地看到,Qt designer中列表视图小部件上设置的所有设置现在都丢失了:不仅是字体,还有ExtendedSelection设置(小部件恢复为SingleSelection)

所以我的问题是-在删除原始小部件之前,是否有一种简单的方法将所有设置从原始小部件复制到子类小部件

test.py

导入系统 从PyQt5导入QtCore、QtWidgets、QtGui、uic 从PyQt5.QtCore导入pyqtlot 替换_LISTVIEW_CLASS=True#False#True 类MyListView(qtwidts.QListView):#https://stackoverflow.com/q/8516163 def按键事件(自身,事件): if(event.key()==QtCore.Qt.key_转义和 event.modifiers()==QtCore.Qt.NoModifier): self.selectionModel().clear()文件 其他: 超级(MyListView,自我)。按键事件(事件) def鼠标压力事件(自身、事件): 如果不是self.indexAt(event.pos()).isValid(): self.selectionModel().clear()文件 超级(MyListView,self).mousePressEvent(事件) 类MyMainWindow(QtWidgets.QMainWindow): 定义初始化(自): 超级(MyMainWindow,self)。\uu初始化 uic.loadUi('test.ui',self) self.listview_model=QtGui.QStandardItemModel() self.listView.setModel(self.listView\u模型) self.button.clicked.connect(self.on_button_click) 如果替换\u列表视图\u类: #要更改小部件类-替换小部件,请执行以下操作: list\u view\u real=MyListView() listView\u parent\u layout=self.listView.parent().layout() listView\u parent\u layout.replaceWidget(self.listView、list\u view\u real) self.listView.deleteLater()#必须手动删除旧的,否则它在replaceWidget之后仍然显示! #不错-像这样的重新分配工作,但所有旧的样式都丢失了! self.listView=list\u view\u real self.listView.setModel(self.listView\u模型) self.show() @pyqtSlot() def on_按钮_点击(自身): self.listview_model.appendRow(QtGui.QStandardItem(“Lorem ipsum”)) self.listview_model.appendRow(QtGui.QStandardItem(“dolor-sit-amet”)) self.listview_model.appendRow(QtGui.QStandardItem(“concertetur”)) self.listview_model.appendRow(QtGui.QStandardItem(“adipising elit,…)) def main(): app=qtwidts.QApplication(sys.argv) window=MyMainWindow() sys.exit(app.exec_()) 如果名称=“\uuuuu main\uuuuuuuu”: main()
test.ui


主窗口
0
0
400
300
主窗口
帕拉蒂诺型
75
真的
QBStractItemView::ExtendedSelection
你好
0
0
800
21
复制小部件的“设置”非常困难,因为每个小部件都有非常特定的属性,但在任何情况下,都完全没有必要,因为您不需要“替换”小部件

使用升级的小部件 最好的解决方案是使用:概念是您在designer中创建GUI,添加一个小部件,该小部件与您将要子类化的类相同,并对其进行升级;这将导致Qt使用您在ui中设置的所有属性,但应用于子类

  • 在Designer中,右键单击已添加的QListView并选择“升级到…”
  • 确保“基类名称”是正确的(应自动选择)
  • 在“提升的类名”字段中键入“MyListView”(子类的名称)
  • 在“头文件”中,键入定义子类的文件名,不带扩展名(在您的示例中,
    test
    );如果文件在子文件夹中,则应该使用点分隔符:如果子类在“提升器”文件夹中的文件“MyListVIEW”中,则需要编写“代码> Advest.MyListVIEW < /Calp>
  • 单击“添加”将新升级添加到已知升级小部件的列表中,单击“升级”并再次保存文件
现在,您的UI将使用MyListView子类而不是默认的QListView(显然,您不再需要整个
REPLACE\u LISTVIEW\u CLASS
块)

使用事件过滤器 对于像您这样的简单情况,您只需要对键盘/鼠标事件作出反应,您可以在小部件上安装,并相应地作出反应:

class MyMainWindow(QtWidgets.QMainWindow):
  def __init__(self):
    super(MyMainWindow, self).__init__()
    uic.loadUi('test.ui', self)
    # ...
    self.listView.installEventFilter(self)

  def eventFilter(self, source, event):
    if source == self.listView:
      if (event.type() == QtCore.QEvent.KeyPress and 
        event.key() == QtCore.Qt.Key_Escape and
        event.modifiers() == QtCore.Qt.NoModifier):
          self.listView.selectionModel().clear()
      elif (event.type() == QtCore.QEvent.MouseButtonPress and
        not self.listView.indexAt(event.pos()).isValid()):
          self.listView.selectionModel().clear()
    return super(MyMainWindow, self).eventFilter(source, event)
猴子修补术 一个更简单的替代方法(应小心使用)是“猴子补丁”小部件方法:

class MyMainWindow(QtWidgets.QMainWindow):
  def __init__(self):
    super(MyMainWindow, self).__init__()
    uic.loadUi('test.ui', self)
    # ...
    self.listView.keyPressEvent = self.listKeyPress
    self.listView.mousePressEvent = self.listMousePress

  def listKeyPress(self, event):
    if (event.key() == QtCore.Qt.Key_Escape and
      event.modifiers() == QtCore.Qt.NoModifier):
      self.listView.selectionModel().clear()
    else:
      QtWidgets.QListView.keyPressEvent(self.listView, event)

  def listMousePress(self, event):
    if not self.listView.indexAt(event.pos()).isValid():
      self.listView.selectionModel().clear()
    QtWidgets.QListView.mousePressEvent(self.listView, event)

请注意,Qt对象的monkey patch只能在调用重写的方法之前完成:例如,在按下鼠标之后,您不能monkey patch
mousePressEvent
,这是因为Qt绑定使用函数缓存:如果已经为实例调用了基实现,从那一刻起,它将一直被使用;另一方面,只有在函数之前已经被覆盖的情况下,才能再次覆盖该方法。

回答得很好,非常感谢!我会花一点时间来弄清楚什么是对我来说最好的选择,但是在上下文中有我的选择真的很棒-再次感谢!