【问题标题】:calling a function with dynamic objectname pyqt5调用具有动态对象名 pyqt5 的函数
【发布时间】:2021-04-20 04:28:54
【问题描述】:

抱歉,上面的问题陈述不清楚,我不知道具体如何构架。

我的查询是我有一些按钮具有相同的功能但它们是重复的因此我想简化代码所以我想用对象名称调用函数并获取值/对该对象执行任何操作

这是一个示例代码。

self.movement('intro_files_paths',final_intro_list)

movement 是我想为特定功能调用的函数 intro_files_paths 是pyqt5 item Widget的对象名

而运动的作用是这样的

def movement(self,b,c):

    index=self.b.currentRow()

    c=self.swapPositions(c,index,index-1)

    self.b.clear()

    for i in c:
        self.b.addItem(i)

所以我得到了错误

AttributeError: 'UI' object has no attribute 'b'

我确实明白为什么我会收到错误 但不知道如何解决这个问题

更多信息: 我正在构建一个视频编辑应用程序,我正在尝试进行批量视频编辑。因此,当有人打开一个文件时,文件名存储在一个列表中,并按照他们打开它们的顺序显示在 qt 列表小部件中,所以在打开它们之后,用户可能想要更改视频的顺序,因此我给了 move_up move_down 和 delete_item

以下所有内容都属于同一类

完整代码

from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QTextEdit, QFileDialog
from PyQt5 import uic
import sys

final_intro_list= ['C:/Users/thota/OneDrive/Desktop/VET/testing area/1.mp4', 'C:/Users/thota/OneDrive/Desktop/VET/testing area/2.mp4', 'C:/Users/thota/OneDrive/Desktop/VET/testing area/30sec.mp4', 'C:/Users/thota/OneDrive/Desktop/VET/testing area/1280.mp4', 'C:/Users/thota/OneDrive/Desktop/VET/testing area/12800.mp4', 'C:/Users/thota/OneDrive/Desktop/VET/testing area/out.mp4', 'C:/Users/thota/OneDrive/Desktop/VET/testing area/output.mp4']

class UI(QMainWindow):
    def __init__(self):
        super(UI, self).__init__()
        uic.loadUi("lol.ui", self)

        self.show()

        self.move_up_4.clicked.connect(self.move_up_in_list_4)
        self.move_down_4.clicked.connect(self.move_down_in_list_4)
        self.remove_4.clicked.connect(self.remove_in_list_4)
        for i in final_intro_list:
            self.intro_files_paths.addItem(i)

    def move_up_in_list_4(self):
        global final_intro_list
        self.movement(0,'intro_files_paths',final_intro_list)

    def move_down_in_list_4(self):
        global final_intro_list
        self.movement(1,'intro_files_paths',final_intro_list)

    def remove_in_list_4(self):
        global final_intro_list
        self.movement(2,'intro_files_paths',final_intro_list)

    def movement(self,a,b,c):
        index=self.b.currentRow()
        if(a==0): #moving up in list
            c=self.swapPositions(c,index,index-1)
        elif(a==1): #moving down in list
            c=self.swapPositions(c,index,index+1)
        else: # delete that item
            del c[index]
        self.b.clear()
        for i in c:
            self.b.addItem(i)

    def swapPositions(self,list, pos1, pos2):
         list[pos1], list[pos2] = list[pos2], list[pos1]
         return list


app = QApplication(sys.argv)
window = UI()
app.exec_()

图形界面代码

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>811</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QListWidget" name="intro_files_paths">
    <property name="geometry">
     <rect>
      <x>100</x>
      <y>90</y>
      <width>430</width>
      <height>290</height>
     </rect>
    </property>
    <property name="dragDropMode">
     <enum>QAbstractItemView::DragDrop</enum>
    </property>
    <property name="movement">
     <enum>QListView::Free</enum>
    </property>
    <property name="spacing">
     <number>0</number>
    </property>
    <property name="gridSize">
     <size>
      <width>20</width>
      <height>20</height>
     </size>
    </property>
    <property name="viewMode">
     <enum>QListView::ListMode</enum>
    </property>
   </widget>
   <widget class="QPushButton" name="remove_4">
    <property name="geometry">
     <rect>
      <x>540</x>
      <y>270</y>
      <width>41</width>
      <height>41</height>
     </rect>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="icon">
     <iconset>
      <normaloff>Cross.png</normaloff>Cross.png</iconset>
    </property>
    <property name="iconSize">
     <size>
      <width>50</width>
      <height>50</height>
     </size>
    </property>
   </widget>
   <widget class="QPushButton" name="move_up_4">
    <property name="geometry">
     <rect>
      <x>540</x>
      <y>170</y>
      <width>41</width>
      <height>41</height>
     </rect>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="icon">
     <iconset>
      <normaloff>up.png</normaloff>up.png</iconset>
    </property>
    <property name="iconSize">
     <size>
      <width>50</width>
      <height>50</height>
     </size>
    </property>
   </widget>
   <widget class="QPushButton" name="move_down_4">
    <property name="geometry">
     <rect>
      <x>540</x>
      <y>220</y>
      <width>41</width>
      <height>41</height>
     </rect>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="icon">
     <iconset>
      <normaloff>down.png</normaloff>down.png</iconset>
    </property>
    <property name="iconSize">
     <size>
      <width>50</width>
      <height>50</height>
     </size>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

【问题讨论】:

  • b 不应具有 self 属性。它是传递给 ur 方法的参数。因此您无法以这种方式访问​​
  • 是的,我理解这个问题,但我该如何解决它以达到要求
  • 很少需要使用对象名称(或实例属性),这通常是由于实施不当导致的要求。什么函数会调用self.movement?为什么不能只传递小部件的引用呢?请提供minimal, reproducible example
  • 对不起,我已经添加了代码,请检查一次
  • movement()move_up_in_list_4() 在一个班级吗?我们通常只对python中的类方法使用参数self。如果这些是全局方法,我建议你给参数一个更具描述性的名称来描述它是什么。同样,bc 应重命名以更具描述性。

标签: python pyqt pyqt5


【解决方案1】:

movement 函数中,您有一个b 参数,但您正在尝试访问self.b。错误很明显:您的 UI 中没有 b 对象,您的实例中也没有,但即使是,它也没有多大意义,因为您想使用函数的参数。

由于这些函数已经引用了实际的对象,因此尝试将属性作为字符串访问确实没有意义,只需使用属性即可:

    def remove_in_list_4(self):
        global final_intro_list
        self.movement(2, self.intro_files_paths, final_intro_list)

    def movement(self, a, b, c):
        index = b.currentRow()

为了知识,您可以使用字符串文字来访问实例属性:

        # ...
        self.movement(2, 'intro_files_paths', final_intro_list)

    def movement(self, a, b, c):
        index = getattr(self, b).currentRow()

Qt 对象也是如此:

    def movement(self, a, b, c):
        index = self.findChild(QListWidget, b).currentRow()

但是,如前所述,仅应在特定情况下使用名称属性(例如,由于配置文件解析而动态创建的对象)。对于任何其他情况,通常不需要它,这通常是实施不当的症状。

无论如何,我强烈建议您对类和实例(它们是什么,它们如何工作)进行更多研究和研究,并认真改进您的语法和命名:将变量命名为“a,b,c”毫无意义,它没有提供任何好处,只会使您的代码更难阅读(甚至对您而言);在官方Style Guide for Python Code 上阅读有关建议做法的更多信息。
最后,总是不鼓励使用全局变量;经验法则是:只有当你真的知道为什么要使用它们时,你才应该使用它们,如果你知道为什么应该使用它们,那么你可能不会使用它们。请改用实例属性。

【讨论】:

  • 谢谢先生,当我做错了,现在我明白如何发布查询将遵循这一点,对不起,如果我一次又一次地评论浪费了你的一些时间,非常感谢先生
【解决方案2】:

不要使用self.b,而是使用selfb,因为这些是函数的参数。使用哪一个取决于您操作的对象。

【讨论】:

    【解决方案3】:

    您在函数中传递了b,而您在函数中使用了self.b

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-27
      • 2019-02-23
      • 2021-01-04
      • 1970-01-01
      • 2021-08-17
      • 2023-03-12
      • 1970-01-01
      相关资源
      最近更新 更多