在QTableWidget中逐行检查以影响QCombobox

时间:2016-10-18 04:26:17

标签: python pyqt maya qtablewidget qcombobox

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

例如,在下表中,用*表示的项目有一个名为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()

无论如何,我可以让我的ui检查场景中的项目列表,标记它应该去哪个名称和组合框(根据哪些行/列)?否则我还能采取其他方式吗?

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

3 个答案:

答案 0 :(得分:1)

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

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)

(注意:为了使其正常工作,您显然必须确保组合框中的第一个条目是空白项目。)

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

答案 2 :(得分:0)

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

你应该做的是两件事之一: - 如果你有一个单独的循环来创建组合框,那么在该循环中如果项目没有颜色则不创建组合框;然后在第二个循环中检查单元格是否有一个组合框,并且只有在确定它是否配置它时。 - 第二个选项是将第一个循环移动到行循环中,即您循环通过每一行确定项目是否有颜色,并且只有在它确定的情况下,您是否创建组合框并进行配置;如果没有颜色,那就把那个卖空了。