2017-01-11 27 views
0

我遇到了一个非常大的类,我现在正在尝试清理并拆分成子类。然而,我最大的问题atm是设置正确的初始化方法,以使函数在各个子类中可调用。 这个想法是有一个Ui_MainWindow类,它正在处理gui进程。另一个处理AT命令的TextMessage类和处理所有错误消息的第三个MessageBoxes类。我将如何为setupUi函数中的所有属性创建正确的init方法?这是我最大的问题。 非常感谢您提前。 大班会在这里:将一个大类分成几个子类,__init__问题

ALPHA = string.ascii_letters 

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
     MainWindow.setObjectName("MainWindow") 
     MainWindow.resize(503, 486) 
     self.centralWidget = QtWidgets.QWidget(MainWindow) 
     self.centralWidget.setObjectName("centralWidget") 
     self.widget = QtWidgets.QWidget(self.centralWidget) 
     self.widget.setGeometry(QtCore.QRect(10, 20, 477, 391)) 
     self.widget.setObjectName("widget") 
     self.gridLayout_2 = QtWidgets.QGridLayout(self.widget) 
     self.gridLayout_2.setContentsMargins(11, 11, 11, 11) 
     self.gridLayout_2.setSpacing(6) 
     self.gridLayout_2.setObjectName("gridLayout_2") 
     self.lineEdit_2 = QtWidgets.QLineEdit(self.widget) 
     self.lineEdit_2.setObjectName("lineEdit_2") 
     self.lineEdit_2.setDisabled(True) 
     self.gridLayout_2.addWidget(self.lineEdit_2, 0, 1, 1, 1) 
     self.gridLayout = QtWidgets.QGridLayout() 
     self.gridLayout.setContentsMargins(11, 11, 11, 11) 
     self.gridLayout.setSpacing(6) 
     self.gridLayout.setObjectName("gridLayout") 
     self.radioButton = QtWidgets.QRadioButton(self.widget) 
     self.radioButton.setChecked(True) 
     self.radioButton.setObjectName("radioButton") 
     self.gridLayout.addWidget(self.radioButton, 0, 0, 1, 1) 
     self.lineEdit = QtWidgets.QLineEdit(self.widget) 
     self.lineEdit.setObjectName("lineEdit") 
     self.gridLayout.addWidget(self.lineEdit, 0, 1, 1, 1) 
     self.radioButton_2 = QtWidgets.QRadioButton(self.widget) 
     self.radioButton_2.setObjectName("radioButton_2") 
     self.gridLayout.addWidget(self.radioButton_2, 1, 0, 1, 1) 
     self.lineEdit2 = QtWidgets.QLineEdit(self.widget) 
     self.lineEdit2.setObjectName("lineEdit2") 
     self.gridLayout.addWidget(self.lineEdit2, 1, 1, 1, 1) 
     self.pushButton = QtWidgets.QPushButton(self.widget) 
     self.pushButton.setObjectName("pushButton") 
     self.pushButton.clicked.connect(self.get_path) #connect add xls button with function get_path 
     self.gridLayout.addWidget(self.pushButton, 1, 2, 1, 1) 
     self.plainTextEdit = QtWidgets.QPlainTextEdit(self.widget) 
     self.plainTextEdit.setObjectName("plainTextEdit") 
     self.gridLayout.addWidget(self.plainTextEdit, 2, 1, 2, 1) 
     self.label = QtWidgets.QLabel(self.widget) 
     self.label.setObjectName("label") 
     self.gridLayout.addWidget(self.label, 2, 0, 1, 1) 
     self.label2 = QtWidgets.QLabel(self.centralWidget) 
     self.label2.setObjectName("label2") 
     self.gridLayout.addWidget(self.label2, 2, 2, 1, 1) 
     self.pushButton_2 = QtWidgets.QPushButton(self.widget) 
     self.pushButton_2.setObjectName("pushButton_2") 
     self.gridLayout.addWidget(self.pushButton_2, 3, 2, 1, 1) 
     self.pushButton_2.clicked.connect(self.send_sms) #send sms function 
     self.gridLayout_2.addLayout(self.gridLayout, 1, 0, 1, 2) 
     self.line = QtWidgets.QFrame(self.widget) 
     self.line.setFrameShape(QtWidgets.QFrame.HLine) 
     self.line.setFrameShadow(QtWidgets.QFrame.Sunken) 
     self.line.setObjectName("line") 
     self.gridLayout_2.addWidget(self.line, 2, 0, 1, 2) 
     self.pushButton_3 = QtWidgets.QPushButton(self.widget) 
     self.pushButton_3.setObjectName("pushButton_3") 
     self.gridLayout_2.addWidget(self.pushButton_3, 0, 0, 1, 1) 
     self.pushButton_3.clicked.connect(self.connect_phone) #connect add xls button with function get_path 
     self.plainTextEdit_2 = QtWidgets.QPlainTextEdit(self.widget) 
     self.plainTextEdit_2.setObjectName("plainTextEdit_2") 
     self.plainTextEdit_2.setDisabled(True) 
     self.gridLayout_2.addWidget(self.plainTextEdit_2, 4, 1, 2, 1) 
     self.progressBar = QtWidgets.QProgressBar(self.widget) 
     self.progressBar.setProperty("value", 0) 
     self.progressBar.setObjectName("progressBar") 
     self.gridLayout_2.addWidget(self.progressBar, 4, 0, 1, 1) 
     self.checkBox = QtWidgets.QCheckBox(self.widget) 
     self.checkBox.setObjectName("checkBox") 
     self.gridLayout_2.addWidget(self.checkBox, 5, 0, 1, 1) 
     MainWindow.setCentralWidget(self.centralWidget) 
     self.menuBar = QtWidgets.QMenuBar(MainWindow) 
     self.menuBar.setGeometry(QtCore.QRect(0, 0, 503, 27)) 
     self.menuBar.setObjectName("menuBar") 
     MainWindow.setMenuBar(self.menuBar) 
     self.mainToolBar = QtWidgets.QToolBar(MainWindow) 
     self.mainToolBar.setObjectName("mainToolBar") 
     MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar) 
     self.statusBar = QtWidgets.QStatusBar(MainWindow) 
     self.statusBar.setObjectName("statusBar") 
     MainWindow.setStatusBar(self.statusBar) 

     self.retranslateUi(MainWindow) 
     self.radioButton.toggled['bool'].connect(self.lineEdit.setEnabled) 
     self.radioButton.toggled['bool'].connect(self.lineEdit2.setDisabled) 
     self.radioButton_2.toggled['bool'].connect(self.lineEdit.setDisabled) 
     self.radioButton_2.toggled['bool'].connect(self.lineEdit2.setEnabled) 
     self.radioButton.toggled['bool'].connect(self.pushButton.setDisabled) 
     self.radioButton_2.toggled['bool'].connect(self.pushButton.setEnabled) 
     QtCore.QMetaObject.connectSlotsByName(MainWindow) 
     self.plainTextEdit.textChanged.connect(self.bam) 

    def bam(self): 
     _translate = QtCore.QCoreApplication.translate 
    text = self.plainTextEdit.toPlainText() 
     self.label2.setText(_translate("MainWindow", str(len(text))+"/160")) 
    if len(text) > 160: 
      root = tk.Tk() 
     root.withdraw() 
     self.plainTextEdit.setPlainText(text[:160]) 
     cursor = self.plainTextEdit.textCursor() 
     cursor.setPosition(self.plainTextEdit.document().characterCount() - 1) 
     self.plainTextEdit.setTextCursor(cursor) 
     tkMessageBox.showwarning("No Way!", "Keep it low, 160chrs max") 
     root.destroy() 
     root.mainloop() 
     return 

    def retranslateUi(self, MainWindow): 
     _translate = QtCore.QCoreApplication.translate 
     MainWindow.setWindowTitle(_translate("MainWindow", "Kotti&Co Mobilizer")) 
     self.radioButton.setText(_translate("MainWindow", "Single SMS")) 
     self.radioButton_2.setText(_translate("MainWindow", "SMS to Contacts")) 
     self.pushButton.setText(_translate("MainWindow", "Add .xls")) 
     self.label.setText(_translate("MainWindow", "Message Text")) 
     self.pushButton_2.setText(_translate("MainWindow", "Send it!")) 
     self.pushButton_3.setText(_translate("MainWindow", "Connect Phone")) 
     self.checkBox.setText(_translate("MainWindow", "Status Report")) 

    def get_path(self, MainWindow): 
     _translate = QtCore.QCoreApplication.translate 
     root = tk.Tk() 
    root.withdraw() 
    file_path = filedialog.askopenfilename(title = "Kotti Kontaktliste",filetypes = (("excel files","*.xls"),("excel files", "*.xlsx"),("csv files","*.csv"),("all files","*.*"))) 
    if not file_path: 
     return None 
    else: 
     self.lineEdit2.insert(file_path) 

    def __init__(self, recipient="+491749449785", message="TextMessage.content not set."): 
     self.recipient = recipient 
     self.content = message 

    def setRecipient(self, number): 
     self.recipient = number 

    def setContent(self, message): 
     self.content = message 

    def disconnectPhone(self): 
     self.ser.close() 

    def connect_phone(self): 
    try: 
     self.ser = serial.Serial('/dev/ttyACM0', 
        460800, 
        timeout=5, 
        xonxoff = False, 
        rtscts = False, 
        bytesize = serial.EIGHTBITS, 
        parity = serial.PARITY_NONE, 
        stopbits = serial.STOPBITS_ONE) 
      #s = input('Enter AT command --> ') 
      #print ('AT command = ' + s) 
      self.ser.write(bytes('AT+CGMI' + '\r\n')) 
      self.ser.timeout = 1 
      self.ser.write('AT+CGMM' + '\r\n') 
      self.ser.timeout = 1 
      response = self.ser.read(999) 
      print(response) 
      self.lineEdit_2.setText(response) 

    except serial.SerialException: 
     self.lineEdit_2.setText("could not connect to phone") 
     return None 

    def check_phone(self): 
     self.ser = serial.Serial('/dev/ttyACM0', 
        460800, 
        timeout=5, 
        xonxoff = False, 
        rtscts = False, 
        bytesize = serial.EIGHTBITS, 
        parity = serial.PARITY_NONE, 
        stopbits = serial.STOPBITS_ONE) 

    def sendMessage(self): 
     self.ser.write('ATZ\r') 
     time.sleep(1) 
     self.ser.write('AT+CMGF=1\r') 
     time.sleep(1) 
     self.ser.write('''AT+CMGS="''' + self.recipient + '''"\r''') 
     time.sleep(1) 
     self.ser.write(self.content + "\r") 
     time.sleep(1) 
     self.ser.write(chr(26)) 
     time.sleep(2) 

    def sms_report(self): 
     self.ser.write('AT+CMEE=2\r') 
     self.ser.timeout = 3 
     time.sleep(1) 
     self.response2 = self.ser.read(999) 
     print(self.response2) 
    self.plainTextEdit_2.setPlainText(self.lineEdit.text()+'\nmessage sent successfully'+self.response2()) 

    def send_sms(self): 
     check = self.radioButton.isChecked() 
     if check == True: #single sms use 
      if not self.lineEdit.text(): 
       root = tk.Tk() 
       root.withdraw() 
       tkMessageBox.showwarning("Phone Number Missing!", "Please enter a valid phone number") 
       root.destroy() 
       root.mainloop() 
       return 
      if not self.plainTextEdit.toPlainText(): 
       root = tk.Tk() 
       root.withdraw() 
       tkMessageBox.showwarning("Message Missing!", "Please enter a text message") 
       root.destroy() 
       root.mainloop() 
       return 
      else: 
       try: 
        sms = Ui_MainWindow(str(self.lineEdit.text()), str(self.plainTextEdit.toPlainText().encode('ISO-8859-1'))) 
        sms.check_phone() 
        sms.sendMessage() 
        repo = self.checkBox.isChecked() 
        if repo == True: 
         sms.sms_report() 

        else: 
         self.plainTextEdit_2.setPlainText(self.lineEdit.text()+'\nmessage sent successfully') 
        sms.disconnectPhone() 
       except serial.SerialException: 
        root = tk.Tk() 
        root.withdraw() 
        tkMessageBox.showwarning("NO GSM Connected!", "Plug in your mobile device") 
        root.destroy() 
        root.mainloop() 
    else: #sms to contact sheet 
     if not self.lineEdit2.text(): 
      root = tk.Tk() 
      root.withdraw() 
      tkMessageBox.showwarning("No contact sheet!", "Please add path to contact file") 
      root.destroy() 
      root.mainloop() 
      return 
     if not self.plainTextEdit.toPlainText(): 
      tkm.missing_message() 
     else: 
      try: 
       with open(str(self.lineEdit2.text().encode('utf-8'))) as f: 
       if str(self.lineEdit2.text().encode('utf-8')).endswith("csv"): #check whether the file is a .csv file or anything else 
         reader2 = csv.reader(f) 
        reader2.next() 
        linecount = len(zip(*reader2)[0]) 
        f.seek(0) 
        reader = csv.reader(f) 
        reader.next() 
        #linecount = len(open(self.lineEdit2.text()).readlines()) 
        counter = 0 
        count_all = 0 
         for i, (row) in enumerate(reader): 
         #print (row[0]) 
         if not row[0] or row[0].startswith(tuple(ALPHA)): #avoid empty lines 
          counter += 1 
           continue 
         print (row[0]) 
         sms = Ui_MainWindow("+491793288636", str(self.plainTextEdit.toPlainText().encode('utf-8'))) 
         sms.check_phone() 
         sms.sendMessage() 
         count_all +=1 
         sms.disconnectPhone() 
         self.progressBar.setValue((count_all)*(100/(linecount-counter))) 
         if count_all == linecount-counter: 
          self.plainTextEdit_2.setPlainText('list completed') 
          self.progressBar.setValue(100) 
         else: 
          self.plainTextEdit_2.setPlainText(str(count_all)+'/'+str(linecount-counter)+'\n'+str(row[0])+'\nmessage sent successfully') 
       else: #get the shit done for xls or xlsx files, converting them into data.csv 
        x = xlrd.open_workbook(self.lineEdit2.text()) #hope that works in windoofs 
        worksheet = x.sheet_by_index(0) 
        csvfile = open('data.csv', 'wb') 
         writecsv = csv.writer(csvfile, quoting=csv.QUOTE_ALL) 

         for rownum in xrange(worksheet.nrows): 
          writecsv.writerow(worksheet.row_values(rownum)) 
        csvfile.close() 
        time.sleep(2) 
        with open('data.csv', 'rb') as f: 
          reader2 = csv.reader(f) 
         reader2.next() 
         linecount = len(zip(*reader2)[0]) 
         f.seek(0) 
         reader = csv.reader(f) 
         reader.next() 
         print(linecount) 
         counter = 0 
         count_all = 0 
          for i, (row) in enumerate(reader): 
          #print (row[0]) 
          if not row[0] or row[0].startswith(tuple(ALPHA)): #avoid empty lines 
           counter += 1 
            continue 
          print (row[0]) 
          sms = TextMessage("+491793288636", str(self.plainTextEdit.toPlainText().encode('utf-8'))) 
          sms.check_phone() 
          sms.sendMessage() 
          count_all +=1 
          sms.disconnectPhone() 
          self.progressBar.setValue((count_all)*(100/(linecount-counter))) 
          if count_all == linecount-counter: 
           self.plainTextEdit_2.setPlainText('list completed') 
           self.progressBar.setValue(100) 
          else: 
           self.plainTextEdit_2.setPlainText(str(count_all)+'/'+str(linecount-counter)+'\n'+str(row[0])+'\nmessage sent successfully') 
      except serial.SerialException: 
       root = tk.Tk() 
       root.withdraw() 
       tkMessageBox.showwarning("NO GSM Connected!", "Plug in your mobile device") 
       root.destroy() 
       root.mainloop() 

if __name__ == "__main__": 
    import sys 
    app = QtWidgets.QApplication(sys.argv) 
    MainWindow = QtWidgets.QMainWindow() 
    ui = Ui_MainWindow() 
    ui.setupUi(MainWindow) 
    MainWindow.show() 
    sys.exit(app.exec_()) 

我尝试了其他类来完成到目前为止是这样的:

lml = Ui_MainWindow() 

class MessageBoxes(): 

    def missing_phone_number(self): 
    root = tk.Tk() 
    root.withdraw() 
    tkMessageBox.showwarning("Phone Number Missing!", "Please enter a valid phone number") 
    root.destroy() 
    root.mainloop() 
    return 
    def missing_message(self): 
    root = tk.Tk() 
    root.withdraw() 
    tkMessageBox.showwarning("Message Missing!", "Please enter a text message") 
    root.destroy() 
    root.mainloop() 
    return 

class TextMessage(): 

    def __init__(self, recipient="+491749449785", message="TextMessage.content not set."): 
     self.recipient = recipient 
     self.content = message 

    def missing_phone_number(self): 
     tkm = MessageBoxes() 

但我总是得到问题的Ui_MainWindow类的属性,如:AttributeError: Ui_MainWindow instance has no attribute 'lineEdit'

+1

划分一类成子类是不常见的在面向对象编程中创建派生类的原因 - 通常是为了专门化基类 - 所以很难提供建议。 – martineau

+0

您的代码中的缩进是否与您在此处提供的缩进相同?看起来你可能已经犯了一个复制错误。如果是这样,你的缩进是错误的。您在成员被分配之前呼叫成员,所以他们不会存在。 – JackCC

+0

你现在在TextMessage类中的意思是?或者一般? – fahrradlaus

回答

0

你必须建立你的分类 - letś称他们为“混搭类”,他们共同工作的方式。

在Python中,使用内置的super很容易实现。 您必须编写__init__方法(如果它们存在于所有类中,则可能有其他方法)采用任意keywoard参数,使用它们使用的参数,并使用super调用其他类__init__。如果所有mixin都这样做(并且你没有方法或者attribut namign冲突),那么你可以用任意数量的os混合构建任意大的类。

class Base(object): 
    pass 

class M1(Base): 
    """ Methods responsible for foo-things""" 
    def __init__(self, **kwargs): 
      self.foo_param1 = kwargs.pop("foo_param1") 
      self.foo_param2 = kwargs.pop("foo_param2") 
      super(M1, self).__init__(**kwargs) 

    # define specific foo methods here: 

# repeat for other mixins: 

    class M2(Base): 
     ... 

    class M3(base): 
     ... 

# declare your main class: 

class UI_Main(M1, M2, M3, ...): 
    def __init__(self, **kwargs): 
      super(Ui_Main, self).__init__(**kwargs) 

(你真的应该使用Python3.x,在这种情况下,郁可强制使用super().__init__(**kwargs),wihtout硬编码当前的类名。)