问题描述
你好,我在用python开发软件,我不是很好,到目前为止,我还没有在程序中使用任何类。 我想用鼠标做事件而不需要上课,而我发现的所有代码都使用了上课,在不破坏程序的情况下我很难使用它。
这是我的代码:
def init_tree(win):
tw = QTreeWidget(win)
tw.resize(500,500)
tw.setHeaderLabels(['TAGS'])
tw.setAlternatingRowColors(True)
tw = clear_tree(tw)
fill_tree(tw)
tw.show()
def main():
app = QApplication.instance()
if not app:
app = QApplication(argv)
window = widgets()
init_tree(window)
mouse_press_event(window)
exit(app.exec_())
main()
def contextMenuEvent(self,event):
contextMenu = QMenu(self)
newAct = contextMenu.addAction("New")
openAct = contextMenu.addAction("Open")
quitact = contextMenu.addAction("Quit")
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == quitact:
self.close()
OR
class MyWidget(QWidget):
def __init__(self):
super(MyWidget,self).__init__()
def mousepressEvent(self,QMouseEvent):
if QMouseEvent.button() == Qt.LeftButton:
print("Left Button Clicked")
elif QMouseEvent.button() == Qt.RightButton:
#do what you want here
print("Right Button Clicked")
对于自我,我将win作为参数传递
我遇到的麻烦是“ event / QMouseEvent”参数
解决方法
它可以部分完成,通常称为 monkey patching ,这是一段扩展或修改其他代码的Python代码。
但是,您无法像使用init_tree
函数那样对事件进行管理:这些函数是“静态的”,因为它们仅被调用一次,而事件驱动的函数应在相关事件被调用时被调用。发出。
然后的解决方案是使用对那些事件做出反应的函数“猴子补丁”类实例。这是一个简单的示例:
def mouse_press_event(event):
print('mouse pressed',event.pos())
some_widget.mousePressEvent = mouse_press_event
现在,有一个陷阱。 ALL 实例方法的第一个参数是对 instance 的引用,这就是self
的含义(请注意,“ self”只是一个约定,您可以随便命名)。这是因为实例方法通常需要对实例进行 或 操作。在您提供的contextMenuEvent
代码中,这很明显:self
对于设置菜单的父级非常重要,最重要的是要使用其mapToGlobal
。
当您使用上面的匿名函数进行猴子补丁时,您没有第一个实例参数(实际上,我们只有event
参数)。为了实现这一点,通过“匿名”猴子修补,我们必须人为地提供实例参数,我们可以为此使用lambda
:
def contextMenuEvent(self,event):
contextMenu = QMenu(self)
# ...
action = contextMenu.exec_(event.globalPos())
# ...
some_widget.contextMenuEvent = lambda event: contextMenuEvent(tw,event)
注意:我直接使用event.globalPos()
更改了您的代码;原因是所有QAbstractScrollArea子类(例如QTreeWidget的所有QAbstractItemView子类)都具有一个子“视口”,该子视口实际上显示了要滚动的内容,并且视口有时会被某些像素转换,例如在显示标题时。
原始功能应更改为此:
action = contextMenu.exec_(self.viewport().mapToGlobal(event.pos()))
但是我们显然不需要,因为所有鼠标事件还具有一个globalPos()
,它已经映射到全局坐标。
最后,虽然在某些情况下您的方法是理想的(通常使用临时实例在运行时非常简单地重新实现),但是如果您要为整个程序这样做,应该考虑四个方面:
- 这是个坏主意;
- 您不应那样做,而应使用子类;
- 除非您真的 知道自己在做什么以及为什么这样做,否则您真的不应该这样做;
- 这是一个真的坏主意;
如果您认为采用这种方法可以使事情变得轻松,对不起,但是您错了:有时您的程序会变得过于复杂,而所有匿名用户只会使您的程序非常很难进行读取和调试。
与其找到复杂且不合常规的方法来以一种不应该做的方式做某事,而要学习以正确的方式做这件事。
作为进一步的说明,猴子修补程序在PyQt中存在一个重要的问题:Qt使用函数缓存来加快处理速度并使用更少的资源,并且如果首先使用已经存在的基本方法调用函数,猴子修补程序将无法在所有,因为第一个原始方法将始终在之后被调用。
因此,花一些时间,学习如何创建子类,不仅会发现它们比看起来更简单,而且会大大改善您的编码。