Python 如何将所有小部件设置复制到PyQt5中的其他小部件设置?
下面的代码使用QtDesigner中的.ui。如果您使用Python 如何将所有小部件设置复制到PyQt5中的其他小部件设置?,python,pyqt5,Python,Pyqt5,下面的代码使用QtDesigner中的.ui。如果您使用REPLACE\u LISTVIEW\u CLASS=False运行它,您将得到“原始”布局-因此,如果您单击按钮,您将得到如下结果: 但是,我不喜欢上次选中项目周围的虚线选择线,只要单击列表视图中的空白区域以清除任何选择 因此,我从实现了这个类,并且由于我想保留.ui,我必须通过替换小部件来更改\uuuu init\uuuu中的列表视图类。这在原则上是有效的,如果使用REPLACE\u LISTVIEW\u CLASS=True运行代码
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 patchmousePressEvent
,这是因为Qt绑定使用函数缓存:如果已经为实例调用了基实现,从那一刻起,它将一直被使用;另一方面,只有在函数之前已经被覆盖的情况下,才能再次覆盖该方法。回答得很好,非常感谢!我会花一点时间来弄清楚什么是对我来说最好的选择,但是在上下文中有我的选择真的很棒-再次感谢!