2014-11-22 116 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)) 
相关问题