使用子目录时PyQt4的SIGNAL/SLOT问题

2 投票
1 回答
681 浏览
提问于 2025-04-16 04:47

感谢你花时间来阅读这个内容。抱歉有点啰嗦,但希望能完全解释清楚问题。下面有一些简化的代码示例来展示这个问题。

我在使用 PyQt4 的信号和槽时遇到了一些问题。当我在一个文件中写代码时,一切都能正常工作,但如果我把一些想用的函数移动到子目录或类中,就无法正常工作了。

我查看了Python 绑定文档,我明白了在单个文件中是怎么工作的。但我想做的是这样的:

  • 在根目录下有一个 main.py 文件,里面包含 MainWindow 的 __init__ 代码。
  • 这个文件导入了多个小部件。每个小部件都存放在自己的子目录中。所有子目录里都有一个 __init__.py 文件。这些子目录在一个叫 'bin' 的目录下,而这个 'bin' 目录又在根目录里。
  • 这些小部件之间需要有信号和槽的连接,这就是我遇到问题的地方。

所以文件结构是:

 - main.py
 - bin/textEditor/__init__.py
 - bin/textEditor/plugin.py
 - bin/logWindow/__init__.py
 - bin/logWindow/plugin.py

以下代码展示了问题。这段代码创建了一个非常基本的主窗口,里面有一个中央的 QTextEdit() 小部件和一个可停靠的 QTextEdit() 小部件。发生的事情是,当中央小部件中的文本改变时,停靠的小部件中也会显示相同的文本。这个例子是可以工作的。但它是通过在 bin/textEditor/plugin.py 文件中连接中央 QTextEdit() 的信号 textChanged() 和 main.py 中的一个函数来实现的。我希望它能做同样的事情,但连接到 bin/textEditor/plugin.py 中的 updateUi 函数。

如果有人能对此提供一些帮助,我将非常感激。我相信这很简单。但如果能指引我找到相关的教程,或者告诉我我做错了什么,我也会很感激!再次感谢你的时间:

### main.py
import os
import sys
# Import PyQT modules
from PyQt4.QtCore import *
from PyQt4.QtGui import *

# Start the main class
class MainWindow(QMainWindow):

    # Initialise
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # Name and size the main window
        self.setWindowTitle("EDITOR/LOG")
        self.resize(800, 600)

        import bin.logWindow.plugin as logWindow
        logWindow.create(self)

        import bin.textEditor.plugin as textEditor
        textEditor.create(self)

    def updateUi(self): 
        # I can connect to this function from within bin/textEditor/plugin.py (see 
        # below) but I want to connect to the function located in 
        # bin/textEditor/plugin.py instead
        text = self.editor.toPlainText()
        self.logWidget.setText(text)

# Run the app
def main():
    app = QApplication(sys.argv)
    form = MainWindow()
    form.show()
    app.exec_()
# Call main
main()

两个插件文件中的代码是:

### bin/textEditor/plugin.py
# Import PyQT modules
from PyQt4.QtCore import *
from PyQt4.QtGui import *

def create(self):
    # Add a dockable widget
    self.logDockWidget = QDockWidget("Log", self)
    self.logDockWidget.setObjectName("LogDockWidget")
    self.logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea|
                                       Qt.RightDockWidgetArea)

    self.logWidget = QTextEdit()
    self.logDockWidget.setWidget(self.logWidget)
    self.addDockWidget(Qt.LeftDockWidgetArea, self.logDockWidget)

还有

### bin/logWindow/plugin.py
Import PyQT modules
from PyQt4.QtCore import *
from PyQt4.QtGui import *

def create(self):

    # Create a text editing box
    self.editor = QTextEdit()

    # Add to main window
    self.setCentralWidget(self.editor)

    # connect text change to update log window. This is presumably what I need to 
    # change so that it connects to the function below instead of the on in main.py
    self.connect(self.editor, SIGNAL("textChanged()"), self.updateUi)

def updateUi(self):
    text = self.editor.toPlainText()
    self.logWidget.setText(text)

1 个回答

2

首先,你为什么还在用一个很旧的PyQt文档版本呢?新的版本在这里:这里

你做的一些事情有点不太寻常。一般来说,在Python中,导入语句通常放在文件的最上面(这样可以更容易看到依赖关系),不过我猜你这么做是为了将来支持更通用的插件导入系统。

看起来你面临的基本问题是,你试图把一个信号源连接到另一个对象中的一个槽,但没有把那个对象存储在特定的位置。要做到这一点,你可能需要在主程序中建立连接,或者创建一个中立的“updateUi”槽,这个槽会发出自己特有的信号,所有插件都在等待这个信号,或者干脆在主程序中保留对那些子对象的引用,并注意初始化的顺序。

撰写回答