【问题标题】:Function pointer across classes and threads跨类和线程的函数指针
【发布时间】:2016-09-23 17:13:43
【问题描述】:

这是我的 QT 代码

from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import QTime
from PyQt4.QtGui import QApplication
from keithley.PS2231A import PS2231A

class A(QtGui.QMainWindow, gui.Ui_MainWindow):
    def __init__(self, parent=None):
        super(A, self).__init__(parent)
        self.setupUi(self)
        ps = PS2231A(port='COM8')
        self.refresh.clicked.connect(self.get_data)

     def get_data(self):
        data = ps.read_current()
        self.current_measurement.setText(str(data))

def main():
    app = QtGui.QApplication([])
    form = A()
    form.show()
    app.exec()

if __name__ == '__main__':
    main()

现在这是我的 PS2231A 库

class PS2231A:
    def __init__(self, port: str):
        self._port = port
        self._dev = serial.Serial()
        self._dev.port = self._port
        self._dev.timeout = 5
        self._dev.baudrate = 9600
        self.connect()
        self._dev.open()

    def read_current(self):
        self._dev.write('MEAS:CURR?')
        current = self._dev.readline()
        return float(current)

这是我想要实现的目标: 电源提供过电流等紧急信息。它基本上最终将该消息写入串行端口,而没有任何命令请求数据。收到该消息后,我希望 GUI 更改。

范围: 在这里,我正在为 PS2231A 编写库,用户将围绕它编写 GUI。我想要一个库端解决方案来将消息传播到 GUI,这是我的设想:

步骤 1:当 PS2231A 的对象被创建时,启动一个线程,该线程将读取串行端口(轮询它)以获取消息。读取紧急消息后,它会调用库中的函数。 第 2 步:线程调用的函数应该执行用户想要的任何函数,即如果用户想要将 GUI 背景变为红色,用户将代码写入名为 turn_background_red 的函数中,将函数名称传递给库函数。然后,每当调用紧急消息时,库函数都会执行代码。

我认为下面的代码会很好地解释这一点(我希望发生这种情况,所以有些代码不起作用):

QT代码

from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import QTime
from PyQt4.QtGui import QApplication
from keithley.PS2231A import PS2231A

class A(QtGui.QMainWindow, gui.Ui_MainWindow):
    def __init__(self, parent=None):
        super(A, self).__init__(parent)
        self.setupUi(self)
        ps = PS2231A(port='COM8')
        ps.set_over_current_callback(self.warn_user)
        self.refresh.clicked.connect(self.get_data)

     def warn_user(self):
        # manipulate some GUI element
        # implemented by user

     def get_data(self):
        data = ps.read_current()
        self.current_measurement.setText(str(data))

def main():
    app = QtGui.QApplication([])
    form = A()
    form.show()
    app.exec()

if __name__ == '__main__':
    main()

类代码实现

class PS2231A:
    def __init__(self, port: str):
        self._port = port
        self._dev = serial.Serial()
        self._dev.port = self._port
        self._dev.timeout = 5
        self._dev.baudrate = 9600
        self.connect()
        self._dev.open()

    def read_current(self):
        self._dev.write('MEAS:CURR?')
        current = self._dev.readline()
        return float(current)

    def set_over_current_callback(self, function_name):
        # write some code to run the function name passed to this function
        # This is the code I am not sure how to go ahead with

        # This function will be executed if an emergency message is received
        # on serial port

我在考虑这个问题时面临的一些关键挑战是要执行的函数在不同的类中。

【问题讨论】:

  • 如果您意识到您的问题在初稿中并不清楚,您实际上不必发布该问题。继续编辑,直到您认为它清楚并可以阅读为止。
  • 请显示代码。这含糊不清,您基本上是在要求我们为您编写项目。
  • 但是,此时您的帖子中实际上并没有创建、可操作的问题。抱歉,Stack Overflow 不太适合模糊架构头脑风暴问题。
  • 这看起来怎么样?我已经编辑了它,我认为这很好理解。

标签: python qt python-3.x


【解决方案1】:

您确实应该更多地修改您的问题(请参阅Minimal, Complete and Verifiable),但这里有一个解决方案,至少适用于 Python 2.7 和 3.5:

import types

class PS2231A:

    # Rest of your class

    def set_over_current_callback(self, function_name):
        func = getattr(self, function_name, None)
        if isinstance(func, types.MethodType):
            func()
        return

这会检查PS2231A 类的实例是否有一个名为function_name 的属性,如果它的类型是方法,它就会被调用。

如果我弄错了,请告诉我,这是在手机上输入的。

【讨论】:

  • 我认为如果 function_name 来自 PS2231A 类,这将有效,但我不知道如果传递给 set_over_current_callback 的 function_name 来自另一个类,此解决方案是否有效。你怎么看?
  • 另外,由于我是 Stack Overflow 的新手,你能帮我修改这个问题吗,所以这也可以成为对其他人有用的资源。我会阅读您回答中的链接并更新问题,希望您事后提供反馈。
  • 好的,如果您能澄清需要调用的函数的确切位置会有所帮助吗? 即如果用户想要将 GUI 背景变为红色,则用户将代码写入名为 turn_background_red 的函数中。这是否意味着用户编写函数?他们在哪里写?如果有很多函数需要通过套接字使用不同的参数调用,我认为你最好编写一个带有可以编码和解码的消息的真实协议。或者如果您的意思是用户在 client 端编写函数,那么它是一个不同的主题。
猜你喜欢
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 2011-12-13
  • 1970-01-01
  • 2011-04-26
  • 2013-10-10
  • 2015-04-03
  • 2010-12-06
相关资源
最近更新 更多