【问题标题】:Check row by row in QTableWidget to affect QCombobox在 QTableWidget 中逐行检查以影响 QCombobox
【发布时间】:2017-02-27 05:04:08
【问题描述】:

我有一个 QTableWidget,2 列,其中第一列包含项目的名称,而第二列填充有 qcomboboxes(使用 cellwidgets 创建),其中包含颜色选项列表(例如“”、RED、BLUE、绿色)

比如下表中带*的项目有一个变量叫color_set,我尝试实现如下:

  • 它将查找场景中项目的名称
  • 然后它会通过一个函数来检查项目是否 shirt_01 包含一个名为 color_set 的变量
  • 如果变量存在,比如它是 RED,它将在组合框中查找选项列表并将 RED 显示为值
  • 如果变量不存在,则会显示一个空白字段
  • 此函数/值在启动 ui 之前使用信息填充表格,它不是按钮单击函数等。

    Name of items   | Color Options
      shirt_01*     |     RED
      shirt_02      | 
      pants*        |    GREEN
    

但是,我没有像上面那样让我的 ui 输出,而是得到以下结果:

    Name of items   | Color Options
      shirt_01*     |     RED
      shirt_02      |     RED
      pants*        |    GREEN

由于某些原因,shirt_02 似乎“纠结”并显示与shirt_01 相同的结果。而且我认为这可能是由于我的逻辑是如何编写的,但我无法弄清楚,或者因为我一直将输出结果绑定到self.color_combobox,因为我的代码最初检查第一列,然后在第二列中找到匹配的文本柱子。 但是我在行中不断收到错误 - item_name 没有属性 .text()

import maya.cmds as cmds
from PyQt4 import QtGui, QtCore
import json

def get_all_mesh():
    all_mesh = cmds.listRelatives(cmds.ls(type = 'mesh'), parent=True)
    return all_mesh

def read_json(node_name):
    # checks if the node_name exists in the json file
    with open('/Desktop/car_colors.json') as data_file:
        data = json.load(data_file)

        items = set()
        for index, name in enumerate(data):
            # if the name is in the json, it will states the color
            if node_name in name:
                for item in (data[name]):
                    #print "{0} - {1}".format(name, item)
                    items.add(item)
    return items

def attrToPy(objAttr):
    stringAttrData = str(cmds.getAttr(objAttr))
    loadedData = cPickle.loads(stringAttrData)

    return loadedData


class testTableView(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        self.setWindowTitle('Color Test')
        self.setModal(False)

        self.all_mesh = get_all_mesh()

        # Build the GUI
        self.init_ui()
        self.populate_data()


    def init_ui(self):
        # Table setup
        self.mesh_table = QtGui.QTableWidget()
        self.mesh_table.setRowCount(len(self.all_mesh))
        self.mesh_table.setColumnCount(3)
        self.mesh_table.setHorizontalHeaderLabels(['Mesh Found', 'Color for Mesh'])
        self.md_insert_color_btn = QtGui.QPushButton('Apply color')

        # Layout
        self.layout = QtGui.QVBoxLayout()
        self.layout.addWidget(self.mesh_table)
        self.layout.addWidget(self.md_insert_color_btn)
        self.setLayout(self.layout)

    def populate_data(self):
        geo_name = self.all_mesh

        for row_index, geo_item in enumerate(geo_name):
            new_item = QtGui.QTableWidgetItem(geo_item)
            # Add in each and every mesh found in scene and append them into rows
            self.mesh_table.setItem(row_index, 0, new_item)

            geo_exclude_num = ''.join(i for i in geo_item if not i.isdigit())
            color_list = read_json(geo_exclude_num)

            color_list.add("")
            # Insert in the color
            self.color_combobox = QtGui.QComboBox()
            #color_list = get_color()
            self.color_combobox.addItems(list(sorted(color_list)))
            self.mesh_table.setCellWidget(row_index, 1, self.color_combobox)
            self.color_value_to_combobox()

    def color_value_to_combobox(self):
        obj_nodes = get_all_mesh()
        for node in obj_nodes:
            # This attribute is stored in the Extra Attributes
            objAttr = '%s.pyPickle'%node
            storedData = attrToPy(objAttr)

            if 'color_set' in storedData:
                color_variant = storedData['color_set']
                combo_index = self.color_combobox.findText(color_variant, QtCore.Qt.MatchFixedString)
                self.color_combobox.setCurrentIndex(0 if combo_index < 0 else combo_index)


# To opent the dialog window
dialog = testTableView()
dialog.show()

无论如何我可以让我的用户界面检查场景中的项目列表,记录它应该去的名称和组合框(根据哪些行/列)?否则我还有什么其他方法可以接近?

编辑:这是我快速完成的附件 - Link 如果你运行 UI,你会注意到 pCube1 的颜色是“红色”而 pCube2 是“蓝色”,但是两个组合框都会变成蓝色

【问题讨论】:

    标签: python pyqt maya qtablewidget qcombobox


    【解决方案1】:

    好的,所以问题出在color_value_to_combobox。您需要指定函数需要处理的对象和组合框,而不是为所有对象设置组合框。主要缺陷是您每次都使用self.color_combobox 进行设置,因此每个对象都会继续设置相同的组合框!它需要更通用。

    无论如何,我只需要更改populate_datacolor_value_to_combobox 的结尾。现在cube1 显示redcube2 显示blue

    import maya.cmds as cmds
    from PyQt4 import QtGui, QtCore
    import json
    import cPickle
    
    def get_all_mesh():
        all_mesh = cmds.listRelatives(cmds.ls(type = 'mesh'), parent=True)
        return all_mesh
    
    def read_json(node_name):
        # checks if the node_name exists in the json file
        with open('/Desktop/car_colors.json') as data_file:
            data = json.load(data_file)
    
            items = set()
            for index, name in enumerate(data):
                # if the name is in the json, it will states the color
                if node_name in name:
                    for item in (data[name]):
                        #print "{0} - {1}".format(name, item)
                        items.add(item)
        return items
    
    def attrToPy(objAttr):
        stringAttrData = str(cmds.getAttr(objAttr))
        loadedData = cPickle.loads(stringAttrData)
    
        return loadedData
    
    
    class testTableView(QtGui.QDialog):
        def __init__(self, parent=None):
            QtGui.QDialog.__init__(self, parent)
            self.setWindowTitle('Color Test')
            #self.setModal(False)
    
            self.all_mesh = get_all_mesh()
    
            # Build the GUI
            self.init_ui()
            self.populate_data()
    
    
        def init_ui(self):
            # Table setup
            self.mesh_table = QtGui.QTableWidget()
            self.mesh_table.setRowCount(len(self.all_mesh))
            self.mesh_table.setColumnCount(3)
            self.mesh_table.setHorizontalHeaderLabels(['Mesh Found', 'Color for Mesh'])
            self.md_insert_color_btn = QtGui.QPushButton('Apply color')
    
            # Layout
            self.layout = QtGui.QVBoxLayout()
            self.layout.addWidget(self.mesh_table)
            self.layout.addWidget(self.md_insert_color_btn)
            self.setLayout(self.layout)
    
        def populate_data(self):
            geo_name = self.all_mesh
    
            for row_index, geo_item in enumerate(geo_name):
                new_item = QtGui.QTableWidgetItem(geo_item)
                # Add in each and every mesh found in scene and append them into rows
                self.mesh_table.setItem(row_index, 0, new_item)
    
                geo_exclude_num = ''.join(i for i in geo_item if not i.isdigit())
                color_list = read_json(geo_exclude_num)
    
                color_list.add("")
                # Insert in the color
                color_combobox = QtGui.QComboBox()
                #color_list = get_color()
                color_combobox.addItems(list(sorted(color_list)))
                self.mesh_table.setCellWidget(row_index, 1, color_combobox)
    
                self.color_value_to_combobox(geo_item, color_combobox) # Pass the object and combobox you want to set
    
        # This use to work on all mesh objects, but only edits a single combobox. This is wrong!
        def color_value_to_combobox(self, node, combobox):
            # This attribute is stored in the Extra Attributes
            objAttr = '%s.pyPickle'%node
            storedData = attrToPy(objAttr)
    
            if 'color_set' in storedData:
                color_variant = storedData['color_set']
                combo_index = combobox.findText(color_variant, QtCore.Qt.MatchFixedString)
                combobox.setCurrentIndex(0 if combo_index < 0 else combo_index) # Needs to work on the proper combobox!
    
    
    # To opent the dialog window
    dialog = testTableView()
    dialog.show()
    

    【讨论】:

    • 实际上,使用self.color_combobox 完全没有区别,因为它会不断重置。真正的缺陷是color_value_to_combobox 中的额外 for 循环。最简单的解决方法是注释掉color_value_to_combobox 的前三行,并将node 更改为geo_item。换句话说,将所有内容放在一个 for 循环中,就像我在回答中所做的那样;-)
    • 他正在遍历color_value_to_combobox 中的所有对象并将值设置为相同的组合框self.color_combobox。事实上,在他遍历populate_datacolor_value_to_combobox 中的所有对象之前,这是没有意义的。我们基本上做了同样的答案;你刚刚合并了两个函数,这很好,而我只是让函数需要参数来指定对象和组合框。我确实用他提供的文件测试了这个例子,它确实有效。
    • @GreenCell 您的代码适用于我的情况,谢谢。我意识到这与我创建的self.color_combobox 有关,因为我一直在调用相同的东西以在我的代码中使用。只是不知道如何解决它。
    • @ekhumoro 我也确实在我的一些代码中使用了你所做的一些代码,并将其与 GreenCell 所做的部分合并在一起。谢谢大家!
    • 只是想知道您能否告诉我为什么将组合框存储在列表中是一个“更好”的主意?列表方法和这个答案之间有多大区别,看到两者都给出相同的结果?另外,如果TS使用列表方法,我想他需要在color_value_to_combobox函数中添加这一行for i in self.combo_ls[-1:]
    【解决方案2】:

    如果颜色变量不存在,您的代码需要将颜色组合显式设置为空白项:

    def populate_data(self):
        geo_name = self.all_mesh
    
        for row_index, geo_item in enumerate(geo_name):
            new_item = QtGui.QTableWidgetItem(geo_item)
            # Add in each and every mesh found in scene and append them into rows
            self.mesh_table.setItem(row_index, 0, new_item)
    
            geo_exclude_num = ''.join(i for i in geo_item if not i.isdigit())
            color_list = read_json(geo_exclude_num)
    
            color_list.add("")
            # Insert in the color
            color_combobox = QtGui.QComboBox()
            #color_list = get_color()
            color_combobox.addItems(list(sorted(color_list)))
            self.mesh_table.setCellWidget(row_index, 1, color_combobox)
    
            # This attribute is stored in the Extra Attributes
            objAttr = '%s.pyPickle' % geo_item
            storedData = attrToPy(objAttr)
    
            if 'color_set' in storedData:
                color_variant = storedData['color_set']
            else:
                color_variant = ''
    
            combo_index = color_combobox.findText(color_variant, QtCore.Qt.MatchFixedString)
            color_combobox.setCurrentIndex(0 if combo_index < 0 else combo_index)
    

    (注意:为此,您显然必须确保组合框中的第一个条目是空白项)。

    【讨论】:

    • 我在item_name = str(item_col.text()) 行收到错误# AttributeError: 'NoneType' object has no attribute 'text' # ,使用currentText 也会给我同样的错误...有什么想法吗?
    • @dissidia。这些行出现在我的答案所指的代码部分之前。您是否声称我建议的更改以某种方式导致这些错误?
    • 我尝试在 for 循环中将您的代码替换为我的代码,但出现错误。但即便如此,当我省略 item_name 的行时,我仍然得到相同的输出shirt_02 是红色的
    • @dissidia。在这种情况下,您实际运行的代码与您的问题中的代码不同。我发布的代码中没有任何内容会导致该错误。请编辑您的问题并显示您实际运行的完整代码。
    • @dissidia。 PS:你确定组合框都有一个空白条目作为零项吗?
    【解决方案3】:

    如果您查看您发布的代码,它不会显示行上的循环以将组合框放在每个单元格中,但我会假设有一个,否则它根本不起作用。

    您应该做以下两件事之一: - 如果您有一个单独的循环来创建组合框,那么在该循环中,如果项目没有颜色,则不要创建组合框;然后在第二个循环中检查单元格是否有组合框,并且只有当它有组合框时才配置它。 - 第二个选项是将第一个循环移动到行循环中,即循环遍历每一行,确定项目是否有颜色,并且只有当有颜色时,才创建组合框并对其进行配置;如果没有颜色,则将其留空。

    【讨论】:

      猜你喜欢
      • 2010-11-22
      • 2017-02-04
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-30
      • 2020-06-26
      相关资源
      最近更新 更多