是否有更优雅或简单的方法来实现我的目标?

时间:2014-11-22 16:49:09

标签: python pyqt

我知道蛮力的方式来做我想要的但是我很确定有一种更优雅的方式来完成我的任务。所以我正在寻找一种比蛮力方式更好的方法的帮助。

我有一个类似于应用程序的电子表格,网格上有21行和5列。第一行中的第一列只是用户输入的权重值(w1,w2,w3,w4)。第5列对重量值求和。我的工作正常,不需要太多帮助。

第2行到第20行的复杂性。对于每一行,用户在第1列中输入值,然后在第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 ......等等。我知道还有更多行优雅的方法。

2 个答案:

答案 0 :(得分:4)

这是非常复杂的,所以我只想给你一个概述和一些指示 如何完成它。

总体概要如下:

  1. 创建一个Equation对象来记录小部件之间的功能关系。
  2. 编写一个函数,该函数接受一个Equation对象并重新计算目标值。
  3. 编写一个函数,重新评估依赖于小部件的所有方程式。
  4. 将所有editFinished回调连接到#3中的函数。
  5. 步骤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 - 目标小部件的名称
    • eq.argWidgets() - 返回公式中使用的小部件列表
    • eq.compute(vals) - 运行带有值列表的计算函数
    • eq.affected(wname) - 如果等式取决于小部件wname
    • ,则返回True

    您需要一个存储所有方程式的地方。在下面的代码中 我使用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.更新受影响的方程式。

    首先,我们开发一种方法来确定所有受影响的方程式:

       # 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方法:

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

    步骤4.连接所有回调。

    此代码未经测试,但希望意图明确。 我们只是将所有的editingFinished回调路由到我们的 名为widget的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))
    

答案 1 :(得分: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))