2016-10-13 5 views
1

メインスレッドにPyQtのguiを持つプログラムがあります。これは光検出器と通信し、別のスレッドでパワーリーディングを取得し、メインスレッドに信号を送り、GUIのパワー値を更新します。 今、光ファイバを自動的に整列させるためにモーターを使用して、光検出器からのフィードバックを得たいと考えています。Pythonで親の__init__を呼び出さずに子の親のメソッドを呼び出す

私はモーターを制御するクラスを作成しましたが、何とかそのクラスに光検出器の読み取り値を渡す必要があります。まず、親のパワー変数にアクセスしようとしましたが、動かなかったのです。 次に、変数の値を返すためにGUI内にメソッドを作成し、モータークラスからアクセスしようとしました。最初に__init__を使わずに親の方法を使うことができないという問題がありました。それをバイパスする方法はありますか?私はGUIの__init__をもう一度呼び出すことはできません、私はちょうど子クラス内からそのメソッドの1つを使いたいと思います。

これを行う別の方法がある場合は、私も満足しています。

PS:別のスレッドにあるので、子クラスに光検出器オブジェクトを与えることはできませんね。

--Edit-- 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() 

別のスレッドではなく、GUIと同じファイル内にあるPDクラス:

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ファイル:NanoMaxとのため

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'を使ってデータを読み取るゲッターメソッドがあるとします。 – tdelaney

+0

コードを共有できますか?理想的にはすべてではありませんが、少なくともクラスと行間では通信しますか? – brandizzi

答えて

1

super().__init__()を呼び出して、すべてのレベルで初期化が行われるようにする必要があります(これはPython 2の場合はno argを使用できないため、それぞれsuper(NanoMax, self).__init__()super(MyApp, self).__init__()となります)。これは、PyQTが新しいスタイルのクラスで正しく書かれており、super自身を正しく使用していることを前提としています。あなたは他の場所でsuperを使用しているので、おそらく少なくとも前者は真です。 superをすべてのクラスで適切に使用すると、すべてのレベルが__init__ -edであることが保証されますが、スーパークラスは手動で特定の継承パターンでは動作しません。

多くのレベルは引数を取るかもしれないという可能性がある場合は、*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 

注:2を組み合わせる

、あなたのコードは次のようになりますあなたは、スーパークラスがその__init__で呼ぶかもしれないメソッドをオーバーロードしてきましたし、あなたのオーバーロードは、あなた自身の__init__に状態セットに依存している場合、 super().__init__(...)コールの後ではなく、その前の状態を設定する必要があります。協調的な多重継承は、そうした痛みをもたらす可能性があります。また、最下位レベルのクラス以外のものの定位置引数を使用すると、複数の継承をするのが醜いことがあるので、すべての引数をキーワードで渡すと意味があり、*argsではなく、**kwargsを受け入れて転送するだけです。継承階層がわずかに変化した場合に壊れるような方法で。

+0

申し訳ありません私のポストのコードにコピーしていませんが、私はMyAppクラスを初期化しています。今度は、あなたが言及したように、 'super(MyApp、self).__ init __()'のすべての '__init__'を変更しました。しかし、私は '__inits'__を無限ループします。 MyAppはNanoMaxを起動し、MyAppコンストラクタを再起動します。 – Eduardo

+0

@Eduardo:「super」(間違った型を最初の引数として渡します)か、コードが設計上破損しています。 'NanoMax'の' __init__'は 'super(NanoMax、self)'を使用していますか? 'MyApp'は' super(MyApp、self) 'を使用していますか?たとえそうであっても、読み返しても、「NanoMax」_が「MyApp」のときに「MyApp」が「NanoMax」のインスタンスを作成することは間違いである可能性があります。コンポジションを継承して、両方を壊しているように見えます。 'NanoMax'が' MyApp'の場合、 'MyApp'は' NanoMax'を必要としません。 MyAppに 'NanoMax'が必要な場合、' NanoMax'は 'MyApp'であってはなりません。それ以外の場合はすべて円形です。 – ShadowRanger

+0

@ShadoRanger:はい、彼らはすべてsuperを使用しています。さらに、私はあなたがちょうど言ったことに同意します、それは理にかなっています。私の場合、何が起こっているのですか:私は、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

関連する問題