2

这是我看过很多文档的东西,但我无法得到关于我知识上的这个特定差距的确切答案,因此我一直在碰壁,在这个层面上似乎没有什么能真正涵盖它:

我有几个窗口,它们都应该是可拖动的,所以我正在构建一个实用程序文件。在这个文件中,我有这个:

def mouseMoveEvent(self, event):
    if self.moving: self.move(event.globalPos()-self.offset)

def mousePressEvent(self, event):
    if event.button() == QtCore.Qt.LeftButton:
        self.moving = True; self.offset = event.pos()


def mouseReleaseEvent(self, event):
    if event.button() == QtCore.Qt.LeftButton:
        self.moving = False

如果我将它放入带有实际窗口的单个文件中(并且不要从另一个文件中调用),这将起作用。

问题是,我如何从另一个文件(具有 UI 窗口的文件)调用它?

我打电话给它

 from utils import *

所以从技术上讲,这些功能都可以通过键入来访问

mouseReleaseEvent(x,x)

但我需要 UI 来导入这些功能,所以在主文件中放置“from utils import *”后我输入:

self.moving = False

但无论我做什么,都会出错。所以问题是封装首先列出的函数(第一个代码块)以便我可以从我的 UI 文件中调用它们的正确方法是什么?

这是我的用户界面代码:

    #!/usr/bin/env python

    import sys
    import os
    from PyQt4 import QtCore, QtGui
    from vibotCss import css
    from viUtils import *

    class viBadOSUI(QtGui.QDialog):
        def __init__(self):
            QtGui.QDialog.__init__(self)
            #setup window
            self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
            self.resize(300, 150)
            center(self)
            self.setMouseTracking(True)



            #additional code
            self.show()
            self.setStyleSheet(css)



    app = QtGui.QApplication(sys.argv)
    window = viBadOSUI()
    sys.exit(app.exec_())

由于长期以来仅在 Autodesk Maya 中学习和使用它,我的 Python 知识存在很大差距——我现在正试图弥合上述差距。感谢您的任何帮助。

4

2 回答 2

4

我认为您正在寻找的是混合:

例如,在viUtils.py中,您可以定义:

from PyQt4 import QtCore, QtGui

class Draggable(object):
    def mouseMoveEvent(self, event):
        try:
            if self.moving:
                self.move(event.globalPos()-self.offset)
        except AttributeError:
            pass

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.moving = True; self.offset = event.pos()

    def mouseReleaseEvent(self, event):   
        if event.button() == QtCore.Qt.LeftButton:
            self.moving = False

class Centerable(object):
    pass # add code here

class CountdownTimer(object):
    pass # add code here

通过将相关方法捆绑在 mixins 中,您可以通过简单地将 mixin(s) 添加到基类中来为类(窗口)添加功能:

import sys
import os
from PyQt4 import QtCore, QtGui
from vibotCss import css
import viUtils

class viBadOSUI(QtGui.QDialog, 
                viUtils.Draggable, viUtils.CountdownTimer):

    def __init__(self):            
        QtGui.QDialog.__init__(self)
        #setup window
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.resize(300, 150)
        center(self)  # You should probably make `center` a method instead of a function and call `self.center()` instead.
        self.setMouseTracking(True)

        #additional code
        self.show()
        self.setStyleSheet(css)

app = QtGui.QApplication(sys.argv)
window = viBadOSUI()
sys.exit(app.exec_())

我不喜欢我上面的代码的一件事是我无法弄清楚如何定义一个 mixin(例如Draggable),__init__它会被自动调用viBadOSUI.__init__。通常你会使用super它,但它QtGui.QDialog.__init__本身似乎并不调用super.

super (实际上,我认为如果您将 mixins 放在before 之前 可能会使用QtGui.QDialog,但这依赖于诡计,一旦有人忘记QtGui.QDialog必须出现在基础列表中的最后一个,就会破坏。)

因为我无法定义一种__init__可以稳健工作的方法:

class Draggable(object):
    def __init__(self):
        ...
        self.moving = False

我改为修改mouseMoveEvent为使用try..except. 这比self.moving = False直接添加要好,viBadOSUI.__init__因为此属性仅由 Draggable 使用,因此应该以某种方式与Draggable. 设置 mixin,然后必须记住初始化一个属性,以便 mixin 可以工作,这是丑陋的编程。

try..except在这里使用可能比使用稍微好一些,if hasattr(self, 'moving')因为只要不引发异常,try 会更快,并且只会在第一个 mousePressEvent 之前的开头引发异常。

尽管如此,仍有改进的余地,我希望这里有人能向我们展示更好的方法。

另一种方法是定义

class viBadOSUI(QtGui.QDialog):
    mouseMoveEvent = viUtils.mouseMoveEvent
    mousePressEvent = viUtils.mousePressEvent
    mouseReleaseEvent = viUtils.mouseReleaseEvent

这为您提供了很大的灵活性,可以将 viUtils 中所需的方法直接添加到您定义的任何类中。但是,我认为它有点过于灵活,因为 mouseMoveEvent、mousePressEvent 和 mouseReleaseEvent 对我来说似乎是“捆绑”的。它们一起工作以实现单个功能。这就是为什么我更喜欢 mixin 方法的原因。此外,viUtils.Draggable与将这 3 行添加到您希望可拖动的每个窗口子类相比,添加到基类的输入更少。

顺便说一句,我建议避开from viUtils import *import viUtils改用。从长远来看,它将使您的代码更有条理。

于 2012-06-13T18:17:50.753 回答
2

方法上的self(第一个)参数是指它所绑定的实例。self.moving = False外部方法的等价物是绑定Falsemoving实例的属性,例如obj.moving = False

于 2012-06-13T18:10:18.980 回答