2016-10-13 41 views
1

我有一个程序,在主线程中有一个在PyQt中的GUI。它与光电探测器进行通信,并在另一个线程中获取功率读数,该线程向主线程发送信号以更新gui的功率值。 现在我想用电机自动对准光纤,从光电探测器获取反馈。孩子调用父母的方法,而无需在Python中调用父母的__init__

所以我创建了一个控制电机的类,但我必须以某种方式将光电探测器读数传递给该类。首先,我试图访问家长的权力变量,但它没有奏效。 然后我在我的gui中创建了一个方法来返回变量的值并尝试从电机类中访问它。我有一个问题,说我不能先使用父母的方法,而不使用它的__init__。有没有办法绕过它?我不能再次调用gui __init__,我只是想在子类中使用它的一个方法。

如果有其他方法可以做到这一点,我也会很高兴。

聚苯乙烯:我想我不能给孩子类的照片探测器对象,因为它是在另一个线程,对不对?

- 编辑 - GUI代码是:

class MyApp(QtGui.QMainWindow, Ui_MainWindow): 
    self.PDvalue = 0 #initial PD value 
    self.PDState = 0 #control the PD state (on-off) 
    self.PDport = self.dialog.pm100d.itemText(self.dialog.pm100d.currentIndex()) #gets pot info 

    def __init__(self): 
    ... #a lot of other stuff 
    self.nano = AlgoNanoMax.NanoMax('COM12') #creates the motor object 
    self.nano_maxX.clicked.connect(self.NanoMaximizeX) #connect its fun to a buttom 
    self.actionConnect_PM100D.triggered.connect(self.ActionConnect_PM100D) #PD buttom 

    def NanoMaximizeX(self): 
     self.nano.maximize_nano_x() #uses motor object function 

    def ActionConnect_PM100D(self): 
     if self.PDState == 0: #check if PD is on 
      self.PD = PDThread(self.PDState, self.PDport) #creates thread 
      self.PD.valueupdate.connect(self.PDHandler) #signal connect 
      self.PD.dialogSignal.connect(self.PDdialog) #create error dialog 
      self.threads = [] 
      self.threads.append(self.PD) 
      self.PD.start() #start thread 
     else: 
      self.PDState = 0 
      self.PD.state = 0 #stop thread 
      self.startpd.setText('Start PD') #change buttom name 


    def PDHandler(self, value): 
     self.PDvalue = value #slot to get pow from thread 

    def ReturnPow(self): 
     return self.PDvalue #return pow (I tried to use this to pass to the motor class) 

    def PDdialog(self): 
     self.dialog.set_instrument('PM100D') #I have a dialog that says error and asks you to type the right port 
     if self.dialog.exec_() == QtGui.QDialog.Accepted: #if Ok buttom try again 
      ret = self.dialog.pm100d.itemText(self.dialog.pm100d.currentIndex()) #new port 
      self.PD.port = str(ret) 
      self.PD.flagWhile = False #change PD stop loop condition to try again 
     else: #pressed cancel, so it gives up 
      self.PD.photodetector.__del__() #delete objects 
      self.PD.terminate() #stop thread 
      self.PD.quit() 

现在PD类,它是在另一个线程,但在同一个文件中的GUI:

class PDThread(QtCore.QThread): 

valueupdate = QtCore.pyqtSignal(float) #creating signals 
dialogSignal = QtCore.pyqtSignal() #signal in case of error 
state = 1 #used to stop thread 

def __init__(self, state, port): 
    QtCore.QThread.__init__(self) 
    self.photodetector = PM100D() #creates the PD object 
    self.port = port 

def run(self): 
    while True: 
     self.flagWhile = True #used to leave while 
     try: 
      self.photodetector.connect(self.port) #try to connect 
     except: 
      self.dialogSignal.emit() #emit error signal 
      while self.flagWhile == True: 
       time.sleep(0.5) #wait here until user press something in the dialog, which is in another thread 
     else: 
      break #leave loop when connected 

    window.PDState = 1 #change state of main gui buttom (change functionality to turn off if pressed again) 
    window.startpd.setText('Stop PD') #change buttom label 
    while self.state == 1: 
     time.sleep(0.016) 
     value = self.photodetector.get_pow() #get PD pow 
     self.valueupdate.emit(value) #emit it 

的AlgoNanoMax文件:

import gui 
from NanoMax import Nano 

class NanoMax(gui.MyApp): #inheriting parent 

def __init__(self, mcontroller_port): 
    self.mcontroller = Nano(mcontroller_port) #mcontroller is the communication to the motor 

def maximize_nano_x(self, step=0.001, spiral_number=3): 
    ''' Alignment procedure with the nano motor X''' 
    print 'Optimizing X' 
    power = super(NanoMax, self).ReturnPow() #here I try to read from the photodetector 
    xpos = self.mcontroller.initial_position_x 
    position = [] 
    position = [[power, xpos]] 
    xsign = 1 
    self.mcontroller.move_relative(self.mcontroller.xaxis, (-1) * spiral_number * step) 
    print 'X nano move: '+ str((-1) * spiral_number * step * 1000) + ' micrometers' 
    time.sleep(4) 
    power = super(NanoMax, self).ReturnPow() 
    xpos += (-1) * spiral_number * step 
    position.append([power, xpos]) 
    for _ in xrange(2*spiral_number): 
     self.mcontroller.move_relative(self.mcontroller.xaxis, xsign * step) 
     print 'X nano move: '+ str(xsign * step * 1000) + ' micrometers' 
     time.sleep(5) 
     power = super(NanoMax, self).ReturnPow() 
     xpos += xsign * step 
     position.append([power, xpos]) 
    pospower = [position[i][0] for i in xrange(len(position))] 
    optimalpoint = pospower.index(max(pospower)) 
    x_shift = (-1) * (xpos - position[optimalpoint][1]) 
    print 'Maximum power: ' + str(max(pospower)) + ' dBm' 
    print 'Current power: ' + str(super(NanoMax, self).ReturnPow()) + ' dBm' 
    self.mcontroller.move_relative(self.mcontroller.xaxis, x_shift) 
+1

_I试图访问父的力量variable_ ...父?这个电机类是从GUI类继承的?这看起来不正确或者甚至是有用的。一个电机类的实例可以从另一个线程中的光检测器对象获取数据,但可能需要锁定才能使线程安全。假设你的光电探测器有一个使用'threading.Lock'读取数据的getter方法。 – tdelaney

+0

你能分享你的代码吗?理想情况下不是全部,但至少是他们之间交流的阶级和路线? – brandizzi

回答

1

__init__NanoMaxMyApp应该调用super().__init__()以确保为所有级别完成初始化(如果这是Python 2,则不能使用无参数super,因此它将分别为super(NanoMax, self).__init__()super(MyApp, self).__init__())。这假设PyQT正确写入新风格的类,并正确使用super本身;你在其他地方使用super,所以推测至少前者是真的。在所有课程中适当地使用super将确保所有级别都为__init__ -ed一次,而手动列出超级类别将不会在某些继承模式下工作,或可能多次调用某些__init__或根本不调用某些__init__

如果有一种可能性,即多层次可能采取的论点,你也应该接受*args/**kwargs,并将其转发给super().__init__调用,这样的参数被转发在那里,然后需要去。

结合了两下,你的代码应该是这样的:

class MyApp(QtGui.QMainWindow, Ui_MainWindow): 
    def __init__(self, *args, **kwargs): 
     super(MyApp, self).__init__(*args, **kwargs) 
     ... rest of __init__ ... 

class PDThread(QtCore.QThread): 
    def __init__(self, state, port, *args, **kwargs): 
     super(PDThread, self).__init__(*args, **kwargs) 
     ... 

class NanoMax(gui.MyApp): #inheriting parent 

    def __init__(self, mcontroller_port, *args, **kwargs): 
     super(NanoMax, self).__init__(*args, **kwargs) 
     self.mcontroller = Nano(mcontroller_port) #mcontroller is the communication to the motor 

注意:如果你已经超载,超级类可能在其__init__和你的重载调用取决于国家的在自己的__init__设置方法,您需要先设置该状态,而不是在拨打super().__init__(...)之后。合作的多重遗传可能是一种痛苦。还要注意,除了最低级别的类别之外,对于除最低级别类别之外的任何其他类型使用位置参数都可能会变得很丑,所以按关键字传递所有参数可能是有意义的,并且只接受并转发**kwargs而不是*args,因此人们不会传递位置参数在继承层次略有变化的情况下会以此方式破坏。

+0

对不起,我没有复制到我的帖子中的代码,但我正在初始化MyApp类。现在我改变了所有'__init__',例如'super(MyApp,self).__ init __()'。但是,我得到了一个无限循环'__inits'__'。 MyApp启动NanoMax,它会再次启动MyApp构造函数,如此来回运行 – Eduardo

+0

@Eduardo:要么滥用'super'(将错误的类型作为第一个参数传递),否则您的代码会因设计而中断。你确定'NanoMax'的'__init__'使用'super(NanoMax,self)'而'MyApp'使用'super(MyApp,self)'吗?即使如此,在重读时,当'NanoMax'_is_是'MyApp'时,'MyApp'可能会创建'NanoMax'的实例。看起来你正在将继承与组合相结合,打破了两者;如果'NanoMax'是'MyApp','MyApp'不需要'NanoMax';如果'MyApp'需要'NanoMax','NanoMax'不应该是'MyApp'。否则,它全部是圆形的。 – ShadowRanger

+0

@ShadoRanger:是的,他们都使用超级。而且,我同意你刚才所说的,这很有道理。在我的情况下,发生的事情是:我只想让NanoMax读取我的MyApp对象的变量,它并不是真的需要成为MyApp的孩子。还有另一种方法可以做到吗? – Eduardo

0
class MyApp(QtGui.QMainWindow, Ui_MainWindow): 
    self.PDvalue = 0 #initial PD value 
    self.PDState = 0 #control the PD state (on-off) 

在上面的代码中,它是在函数之外设置一个变量。要在课堂上做到这一点,不要把self关键字放在它的前面。这样,你可以只在类定义

class MyApp(QtGui.QMainWindow, Ui_MainWindow): 
    PDvalue = 0 #initial PD value 
    PDState = 0 #control the PD state (on-off) 

,并在超线

power = super(NanoMax, self).PDvalue 

例如:

>>> class Hi: 
    H = 5 
    def __init__(self): 
    self.g = 6 

>>> class Bye(Hi): 
    def H(self): 
    print(super(Bye, self).H) 

>>> e = Bye() 
>>> e.H() 
5 
>>> 
+0

它的工作原理是这样的,但它总是读取0的权力。我认为这是因为他正在阅读父类变量而不是实例变量。还是我做错了什么?我将主代码中的所有self.PD值也更改为MyApp.PDvalue – Eduardo

相关问题