accessing variables without using list. dynamicall

2019-09-18 13:16发布

问题:

All of the answers I have found say just to use a dictionary or a list. I am making an application and the GUI is being design in QT creator. There is an array of checkboxes(21) and in Qt Creator are all labeled cb0....cb20. I have a 21 element list that represents if the checkbox should be checked or not. Is there a way to loop through variable names? Pseudo code:

for i in range(21):
    if cbList[i]:
        cb'i'.setChecked=True
    else:
        cb'i'.setChecked=False

How can I have cb'i' translate the i into the variable name?

Added for clarity: I don't want to create a dictionary and then set the dictionary value true or false. The variables already exist. They are checkboxes in the GUI. All the checkboxes are name cb0 ... cb20. They have the function setChecked that i wish to call for each instance of the checkbox. For example cb0.setChecked(False) will disable the checkbox. I have a list that corresponds to each checkbox. I am trying to avoid writing cb1.setChecked(True) for all 21 checkboxes.

回答1:

If the checkboxes were created in Qt Designer, they will end up as attributes of the top-level window, or of a ui namespace.

Given this, the correct solution is to use getattr:

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        ...
        for i in range(21):
            checkbox = getattr(self.ui, 'cb%s' % i)
            if cbList[i]:
                checkbox.setChecked(True)
            else:
                checkbox.setChecked(False)


回答2:

That's a terrible idea. And to find out why, read this article.

Instead use the list or dictionary option.

cb = defaultdict(dict)
for i in range(21):
    if cbList[i]:
        cb[i]['setChecked'] = True
    else:
        cb[i]['setChecked'] = False

Using a dictionary lets you call the variable using a “associative memory” or “associative array” instead of having to know the index of the object in the array. To achieve what you wanted to, give the dictionary keys as so:

cb["cb%s"%(i)]

That way you can refer to specific variable 4 as: cb['cb4'] if you need to.

Edit: I just realized you meant you were trying to call QT checkboxes. In that case, I suggest rather than having a list of checkboxes, you can have a dictionary where the key of the dictionary is the name of the checkbox ID, and the value is the QT object itself.

cb = {}
for i in range(21):
    cb['cb%s'%i] = getattr(self.ui, 'cb%s'%i)

Now when you want to set a particular checkbox as true or false, you could simply call:

cb['cb3'].setChecked(True)

Why this is a better coding practice: You would be iterating through getattr for each checkbox just once (when you set up the dictionary initially). Additionally, if you make a single change, you can directly obtain the object you want to manipulate.



回答3:

You should use QT's builtin data strucures instead, where you are given an indexable and iterable data structure just like the above examples with lists and dictionaries.

Here is an example with QListWidget

import sys
from PyQt4.QtGui import *

app = QApplication(sys.argv)

listWidget = QListWidget()

for i in range(10):
    item = QListWidgetItem("Item %i" % i)
    listWidget.addItem(item)

listWidget.show()
sys.exit(app.exec_())

While variable name concatenation is possible in some languages, it mostly depends on having an extra terminal (like $ in PHP) to denote variables. The syntax parser is made not to understand variable name concatenation on purpose. This is actually to help you avoid handcrafting spaghetti.