2014-11-22 83 views
0

我知道蠻力的方式來做我想做的事,但我非常確定有一種更優雅的方式來完成我的任務。所以我在尋找比強力方式更好的方法尋求幫助。有沒有更優雅或更簡單的方法來實現我的目標?

我有一個類似電子表格的應用程序,在網格上有21行5列。第一行的第一列只是用戶輸入的權重值(w1,w2,w3,w4)。第5列將權重值相加。我有這個工作正常,不需要太多的幫助。

行2到20的複雜性。對於每行,用戶在列1:4中輸入值,然後在列5中計算行的加權平均值(使用行1中的權重)。例如,對於任何給定的行,如果用戶輸入的值進入名爲va1,va2,va3,va4的QLineEdit小部件,則va_wa = va1 * w1 + va2 * w2 + va3 * w3 + va4 * w4。

這對於單行代碼很容易做到。但我不知道如何完成另一行,而不是一遍又一遍地複製代碼並更改每行的名稱(暴力方式)。

這裏是我的代碼:

class MyForm(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(MyForm,self).__init__(parent) 
     self.ui=Ui_MainWindow() 
     self.ui.setupUi(self)   

     self.ui.mdiArea.addSubWindow(self.ui.subwindow) 
     self.ui.mdiArea.addSubWindow(self.ui.subwindow_2) 
     QtCore.QTimer.singleShot(10, lambda: self.ui.mdiArea.setActiveSubWindow(self.ui.mdiArea.subWindowList()[0])) 

     self.ui.wt1.editingFinished.connect(self.runBoth) 
     self.ui.wt2.editingFinished.connect(self.runBoth) 
     self.ui.wt3.editingFinished.connect(self.runBoth) 
     self.ui.wt4.editingFinished.connect(self.runBoth) 

     self.ui.ca1.editingFinished.connect(self.waCalc) 
     self.ui.ca2.editingFinished.connect(self.waCalc) 
     self.ui.ca3.editingFinished.connect(self.waCalc) 
     self.ui.ca4.editingFinished.connect(self.waCalc) 

    def runBoth(self): 
      self.wtResult() 
      self.waCalc() 

    def wtResult(self): 
     if len(self.ui.wt1.text())!=0: 
      a=float(self.ui.wt1.text()) 
     else: 
      a=0 
     if len(self.ui.wt2.text())!=0: 
      b=float(self.ui.wt2.text()) 
     else: 
      b=0 
     if len(self.ui.wt3.text())!=0: 
      c=float(self.ui.wt3.text()) 
     else: 
      c=0 
     if len(self.ui.wt4.text())!=0: 
      d=float(self.ui.wt4.text()) 
     else: 
      d=0      
     sum=a+b+c+d 
     self.ui.wt_total.setText(str(sum)) 

    def waCalc(self): 

     if len(self.ui.ca1.text())!=0: 
      ca1=float(self.ui.ca1.text()) 
     else: 
      ca1=0 

     if len(self.ui.ca2.text())!=0: 
      ca2=float(self.ui.ca2.text()) 
     else: 
      ca2=0 

     if len(self.ui.ca3.text())!=0: 
      ca3=float(self.ui.ca3.text()) 
     else: 
      ca3=0 

     if len(self.ui.ca4.text())!=0: 
      ca4=float(self.ui.ca4.text()) 
     else: 
      ca4=0 

     if len(self.ui.wt1.text())!=0: 
      wt1=float(self.ui.wt1.text()) 
     else: 
      wt1=0 
     if len(self.ui.wt2.text())!=0: 
      wt2=float(self.ui.wt2.text()) 
     else: 
      wt2=0 
     if len(self.ui.wt3.text())!=0: 
      wt3=float(self.ui.wt3.text()) 
     else: 
      wt3=0 
     if len(self.ui.wt4.text())!=0: 
      wt4=float(self.ui.wt4.text()) 
     else: 
      wt4=0 

     wa=(wt1*ca1)+(wt2*ca2)+(wt3*ca3)+(wt4*ca4) 
     self.ui.ca_wa.setText(str(wa))   


if __name__ == "__main__": 
    app = QtGui.QApplication(sys.argv) 
    myapp=MyForm() 
    myapp.show() 
    app.exec_() 

所以我所示,其中該行已CA1,CA2,CA3,CA4,ca_wa的例子。我會爲接下來的19行做什麼(除了複製wa_Calc代碼19次並將變量改爲nx1:4,nx_wa ab1:4,ab_wa,ba1:4,ba_wa ...等等。我知道還有更多優雅的方法

回答

3

使用列表:

class MyForm(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(MyForm,self).__init__(parent) 
     self.ui=Ui_MainWindow() 
     self.ui.setupUi(self)   

     self.ui.mdiArea.addSubWindow(self.ui.subwindow) 
     self.ui.mdiArea.addSubWindow(self.ui.subwindow_2) 
     QtCore.QTimer.singleShot(10, lambda: self.ui.mdiArea.setActiveSubWindow(self.ui.mdiArea.subWindowList()[0])) 

     self.ui_weights = [getattr(self.ui,'wt%d'%i) for i in range(1,5)] 
     self.ui_cas = [ 
      [getattr(self.ui,'ca%d_%d'%(row,i)) for i in range(1,5)] 
      for row in range(1,21) 
     ] 
     self.ui_cawas = [getattr(self.ui,'ca_wa_%d'%row) for row in range(1,21)] 
     for wt in self.ui_weights: 
      wt.editingFinished.connect(self.runBoth) 
     for row in self.ui_cas: 
      for cell in row: 
       cell.editingFinished.connect(self.waCalc) 

    def runBoth(self): 
     self.wtResult() 
     self.waCalc() 

    def wtResult(self): 
     result = sum(float(wt.text() or 0) for wt in self.ui_weights) 
     self.ui.wt_total.setText(str(result)) 

    def waCalc(self): 
     for row, wa in zip(self.ui_cas,self.ui_cawas): 
      result = sum(
       float(ca.text() or 0) * float(wt.text() or 0) 
       for ca,wt in zip(row, self.ui_weights) 
      ) 
      wa.setText(str(result))   
+0

雖然這不是QTable。它是100個單獨的QLineEdit項目,看起來有點像一張表格(20行,每行有5個QLineEdits)。這種方法仍然有效嗎? – user3720101 2014-11-22 17:13:43

+0

用'getattr'將單獨的QLineEdits放入列表中,您只需要給它們正確的名稱。 – Daniel 2014-11-22 17:18:26

+0

我得到一個回溯錯誤: 回溯(最近通話最後一個): 文件 「」,1號線,在 ... 文件 「C:/Users/callphreeqcInput1.pyw」 18行,在__init__ (1,20) AttributeError:'Ui_MainWindow'對象沒有屬性'ca1_1' 當你說我必須給QLineEdits一個正確的名字時,我不清楚這意味着什麼。所有的QLineEdits都有一個對象名稱;例如ca1,ca2,ca3,ca4,ca_wa,nx1,nx2,nx3,nx4,nx_wa。這是使用QtDesigner設置的。 我是否需要返回到QtDesigner並保留所有100個QLineEdits? 對不起,簡單的問題;只是學習。 – user3720101 2014-11-22 17:56:08

4

這是相當複雜,因此我只是給你一個概述,並就如何完成它的一些指針

一般概述。這個:

  1. 創建一個Equation對象以記錄小部件之間的函數關係。
  2. 編寫一個採用等式對象並重新計算目標值的函數。
  3. 編寫一個函數,重新評估所有依賴於窗口小部件的方程。
  4. 將所有編輯完成的回調連接到#3中的函數。

第1步。公式類。

創建一個新的Equation對象可能是這樣的:

eq1 = Equation("wt_total", computeSum, ["wt1", "wt2", "wt3", "wt4"]) 
eq2 = Equation("ca_wa", computeDot, ["wt1", "wt2", "wt3", "wt4", "ca1", "ca2", "ca3", "ca4"]) 

computeSumcomputeDor可能看起來像:

def computeSum(arr): 
    return sum(arr) 

def computDot(arr): 
    xs = arr[0:3] 
    ys = arr[4:7] 
    return sum ([ x*y for (x,y) in zip(xs,ys) ]) 

您需要的Equation類下列插槽/方法:

  • eq.target - name的目標小部件
  • eq。argWidgets() - 返回公式中使用的小部件列表
  • eq.compute(vals) - 運行帶有值列表的計算函數
  • eq.affected(wname) - 如果方程取決於小部件wname

您將需要一個地方來存儲所有的方程。在 以下的代碼中,我使用self.equations,其中selfMyForm對象。

第2步 - 更新單個方程。

的方法來更新一個方程會是什麼樣子:

# update a single equation 
    def update(self, eq): 
    args = [] 
    for wname in eq.argWidgets(): 
     val = ...lookup and convert value stored in wname... 
     args.append(val) 
    result = eq.compute(args) 
    # store result in target widget eq.target 

步驟3.更新受影響的方程。

首先我們開發了一個方法來確定所有受影響的方程:

def handleEditingFinished(self, wname): 
    eqs = self.affected(wname) 
    for e in eqs: 
     self.update(e) 

第4步鉤出來的:

# return the equations affected by a change in widget wname 
    def affected(self, wname): 
    return [ e | if e.affected(wname) for e in self.equations ] 

的handleEditingFinished方法將窗口小部件名稱叫回調。

此代碼未經測試,但希望其意圖清晰。 我們只是將所有編輯完成的回調路由到我們的 handleEditingFinished方法中,其中第一個參數爲 。

from functools import partial 

    def callback(self, wname): 
    self.handleEditingFinished(wname) 

    for e in self.equations: 
    for wname in e.argWidgets(): 
     w = ... get the widget named wname... 
     w.editingFinished(partial(callback, self, wname)) 
相關問題