在QTableWidget中逐行检查影响QCombobox
Check row by row in QTableWidget to affect QCombobox
我有一个 QTableWidget,2 列,其中第一列包含项目名称,而第二列填充了 qcomboboxes(使用 cellwidgets 创建),其中包含颜色选项列表(例如“”,RED,蓝色、绿色)
例如下面table中,带*的项有一个变量叫color_set
,我想实现如下:
- 它将查找场景中的项目名称
- 然后它会通过一个函数来检查并查看该项目是否
shirt_01
包含一个名为 color_set
的变量
- 如果变量存在,比如它是 RED,它将在组合框中查找选项列表并显示 RED 作为值
- 如果变量不存在,它将显示一个空白字段
此 function/values 在 ui 启动之前用信息填充 table,它不是按钮单击功能等
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
似乎得到 'tangled' 并显示与 shirt_01
相同的结果。而且我认为这可能是由于我的逻辑是如何编写的但我无法弄清楚或者因为我一直将输出结果绑定到 self.color_combobox
因为我的代码最初检查第一列然后在中找到匹配的文本第二列。
但是我一直在该行出错 - item_name has no attribute .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 检查场景中的项目列表,计算它应该去哪个名称和组合框(根据哪个 rows/columns)?否则我还有什么其他方法可以接近?
编辑:这是我做的附件 quick - Link
如果你 运行 UI,你会注意到 pCube1 的颜色是 "red" 而 pCube2 是 "blue",但是两个组合框都会变成蓝色
如果您查看您发布的代码,它不会显示将组合框放在每个单元格中的行循环,但我假设有一个,否则它根本无法工作。
您应该做的是以下两件事之一:
- 如果你有一个单独的循环来创建你的组合框,那么如果项目没有颜色,那么在那个循环中不要创建组合框;然后在第二个循环中检查单元格是否有组合框,只有在有组合框时才进行配置。
- 第二个选项是将第一个循环移动到行循环中,即您循环遍历每一行,确定项目是否有颜色,只有在有颜色的情况下,您才创建组合框并对其进行配置;如果没有颜色,就让那个卖空。
如果颜色变量不存在,您的代码需要将颜色组合显式设置为空白项:
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)
(注意:要使其正常工作,您显然必须确保组合框中的第一个条目是空白项)。
好的,所以问题出在 color_value_to_combobox
。您无需为所有对象设置组合框,而是需要指定函数需要处理的对象和组合框。主要缺陷是您每次都使用 self.color_combobox
进行设置,因此每个对象都会继续设置相同的组合框!它需要更通用。
无论如何,我只需要更改 populate_data
和 color_value_to_combobox
的结尾即可。现在 cube1
显示 red
,cube2
显示 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()
我有一个 QTableWidget,2 列,其中第一列包含项目名称,而第二列填充了 qcomboboxes(使用 cellwidgets 创建),其中包含颜色选项列表(例如“”,RED,蓝色、绿色)
例如下面table中,带*的项有一个变量叫color_set
,我想实现如下:
- 它将查找场景中的项目名称
- 然后它会通过一个函数来检查并查看该项目是否
shirt_01
包含一个名为color_set
的变量
- 如果变量存在,比如它是 RED,它将在组合框中查找选项列表并显示 RED 作为值
- 如果变量不存在,它将显示一个空白字段
此 function/values 在 ui 启动之前用信息填充 table,它不是按钮单击功能等
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
似乎得到 'tangled' 并显示与 shirt_01
相同的结果。而且我认为这可能是由于我的逻辑是如何编写的但我无法弄清楚或者因为我一直将输出结果绑定到 self.color_combobox
因为我的代码最初检查第一列然后在中找到匹配的文本第二列。
但是我一直在该行出错 - item_name has no attribute .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 检查场景中的项目列表,计算它应该去哪个名称和组合框(根据哪个 rows/columns)?否则我还有什么其他方法可以接近?
编辑:这是我做的附件 quick - Link 如果你 运行 UI,你会注意到 pCube1 的颜色是 "red" 而 pCube2 是 "blue",但是两个组合框都会变成蓝色
如果您查看您发布的代码,它不会显示将组合框放在每个单元格中的行循环,但我假设有一个,否则它根本无法工作。
您应该做的是以下两件事之一: - 如果你有一个单独的循环来创建你的组合框,那么如果项目没有颜色,那么在那个循环中不要创建组合框;然后在第二个循环中检查单元格是否有组合框,只有在有组合框时才进行配置。 - 第二个选项是将第一个循环移动到行循环中,即您循环遍历每一行,确定项目是否有颜色,只有在有颜色的情况下,您才创建组合框并对其进行配置;如果没有颜色,就让那个卖空。
如果颜色变量不存在,您的代码需要将颜色组合显式设置为空白项:
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)
(注意:要使其正常工作,您显然必须确保组合框中的第一个条目是空白项)。
好的,所以问题出在 color_value_to_combobox
。您无需为所有对象设置组合框,而是需要指定函数需要处理的对象和组合框。主要缺陷是您每次都使用 self.color_combobox
进行设置,因此每个对象都会继续设置相同的组合框!它需要更通用。
无论如何,我只需要更改 populate_data
和 color_value_to_combobox
的结尾即可。现在 cube1
显示 red
,cube2
显示 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()