Difference between revisions of "IC Python API:Table View"
Chuck (RL) (Talk | contribs) m (→Refresh Function) |
Chuck (RL) (Talk | contribs) m |
||
(5 intermediate revisions by the same user not shown) | |||
Line 2: | Line 2: | ||
{{Parent|IC_Python_API:RL_Python_Samples|RL Python Samples}} | {{Parent|IC_Python_API:RL_Python_Samples|RL Python Samples}} | ||
− | [[File:Ic_python_api_lights_table_01.png |left]] The | + | [[File:Ic_python_api_lights_table_01.png |left]] The Qt table widget is a useful UI widget suitable for listing distinct non-hierarchical entities that share common set of attributes. Imagine if you were to list the different brands of luxury hand-bags. You would need a column to list the names of each bag such as "Jackie", "Leather Serpenti Forever", "Monogram Canvas", etc. You would likely also have a column to list the brand name that the bags belong to such as "Gucci", "Bulgari", "Coach", "Louis Vuitton", etc. You might even add other columns for pricing, color, type, etc. Likewise, many digital assets can be categorized in this fashion as well. |
− | If | + | If the assets listed are part of a hierarchical structure, then a QT tree widget would be more suitable way to represent this type of data: see [http://wiki.reallusion.com/IC_Python_API:Bone_Hierarchies Bone Hierarchies]. |
This article will go over the creation of a table widget for listing all the standard lights in the scene; their name, active state, multiplier, and color attributes. To top it off, we will add a refresh button to the window to update the light list to the current state of the scene. | This article will go over the creation of a table widget for listing all the standard lights in the scene; their name, active state, multiplier, and color attributes. To top it off, we will add a refresh button to the window to update the light list to the current state of the scene. | ||
Line 81: | Line 81: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Notice that we call refresh command in the initialization phase. Unlike normal python declaration order, methods and call to methods inside classes don't have to follow a specific order due to the use of '''self'''. '''refresh''' method from outside of the class after its declaration | + | Notice that we call refresh command in the initialization phase. Unlike normal python declaration order, methods and call to methods inside classes don't have to follow a specific order due to the use of '''self'''. The class-specific '''refresh''' method can also be called from outside of the class after its declaration; Which would look like the following: |
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
Line 87: | Line 87: | ||
table_widget.refresh() | table_widget.refresh() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | Whether you choose to make the call from inside or outside the class initialization; you should only initialize the refresh method once. | ||
== Dialog Window Boilerplate == | == Dialog Window Boilerplate == |
Latest revision as of 19:15, 2 March 2020
- Main article: RL Python Samples.
If the assets listed are part of a hierarchical structure, then a QT tree widget would be more suitable way to represent this type of data: see Bone Hierarchies.
This article will go over the creation of a table widget for listing all the standard lights in the scene; their name, active state, multiplier, and color attributes. To top it off, we will add a refresh button to the window to update the light list to the current state of the scene.
Necessary Modules
Besides the fundamental Reallusion Python module, we'll also need Pyside2 to build the user interface. But we don't need the entire Pyside2 module for this simple example, so I'll just import QtWidgets for building the user interface and wrapInstance to bind the iClone dialog window to the Pyside2 interface.
import RLPy
from PySide2 import QtWidgets
from PySide2.shiboken2 import wrapInstance
Light Table Widget
In order to create a table widget we must first create the widget as a class that inherits from the QtWidgets.QtableWidget class. This will give us a shell of a table widget to work with, i.e. to populate.
class LightTableWidget(QtWidgets.QTableWidget):
def __init__(self):
super().__init__()
labels = ["Name", "Active", "Multiplier", "Color (RGB)"]
self.setColumnCount(len(labels))
self.setHorizontalHeaderLabels(labels)
# Adjust row resize policy
header = self.horizontalHeader()
header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QtWidgets.QHeaderView.Stretch)
Notice how the resize policy is set by adjusting the header attribute.
Refresh Function
In order to populate the scene lights table, we have to add a refresh method to search the scene for all of the lights and add them one by one to the table widget. This method belongs in the same class we used to inherit from the QtWidgets.QTableWidget because of this we can rely on the handy self keyword to refer to the instance of the class (after its creation).
self.refresh()
def refresh(self):
# Clear the table widget
self.setRowCount(0)
# Grab all props in the scene
all_lights = RLPy.RScene.FindObjects(RLPy.EObjectType_Light)
# Add an entry into the combo-box for every prop found
for i in range(len(all_lights)):
row_count = self.rowCount()
self.setRowCount(row_count + 1)
# Create a object name item
item_object = QtWidgets.QTableWidgetItem()
item_object.setText(all_lights[i].GetName())
self.setItem(row_count, 0, item_object)
# Create a active toggle item
active_object = QtWidgets.QTableWidgetItem()
active_object.setText(str(all_lights[i].GetActive()))
self.setItem(row_count, 1, active_object)
# Create multiplier item
multiplier_object = QtWidgets.QTableWidgetItem()
multiplier_object.setText(str(round(all_lights[i].GetMultiplier(), 4)))
self.setItem(row_count, 2, multiplier_object)
# Create a color item
color_object = QtWidgets.QTableWidgetItem()
color = all_lights[i].GetColor()
color_value = "{} - {} - {}".format(color.Red(), color.Green(), color.Blue())
color_object.setText(color_value)
self.setItem(row_count, 3, color_object)
Notice that we call refresh command in the initialization phase. Unlike normal python declaration order, methods and call to methods inside classes don't have to follow a specific order due to the use of self. The class-specific refresh method can also be called from outside of the class after its declaration; Which would look like the following:
table_widget = LightTableWidget()
table_widget.refresh()
Whether you choose to make the call from inside or outside the class initialization; you should only initialize the refresh method once.
Dialog Window Boilerplate
In order for us to show the scene lights table list we must first create a window, declare an instance of our custom table class, and attach the said table to the window layout.
# Create a dialog window
dialog = RLPy.RUi.CreateRDialog()
dialog.SetWindowTitle("Scene Lights")
# Create Pyside layout for RDialog
qt_dialog = wrapInstance(int(dialog.GetWindow()), QtWidgets.QDialog)
main_widget = QtWidgets.QWidget()
qt_dialog.setFixedWidth(350)
# Create a Light Table widget
table_widget = LightTableWidget()
qt_dialog.layout().addWidget(table_widget)
We can also add a handy refresh button that simply calls the method declared in the custom table class. Finally, we will need to show the window.
# Add a refresh button
refresh_button = QtWidgets.QPushButton()
refresh_button.setFixedHeight(24)
refresh_button.setText("Refresh List")
refresh_button.clicked.connect(lambda: table_widget.refresh())
qt_dialog.layout().addWidget(refresh_button)
dialog.Show()
Notice the use of lambda which is a handy way to declare an anonymous function.
Everything Put Together
You can copy and paste the following code into a PY file and load it into iClone via Script > Load Python.
import RLPy
from PySide2 import QtWidgets
from PySide2.shiboken2 import wrapInstance
class LightTableWidget(QtWidgets.QTableWidget):
def __init__(self):
super().__init__()
labels = ["Name", "Active", "Multiplier", "Color (RGB)"]
self.setColumnCount(len(labels))
self.setHorizontalHeaderLabels(labels)
# Adjust row resize policy
header = self.horizontalHeader()
header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QtWidgets.QHeaderView.Stretch)
self.refresh()
def refresh(self):
# Clear the table widget
self.setRowCount(0)
# Grab all props in the scene
all_lights = RLPy.RScene.FindObjects(RLPy.EObjectType_Light)
# Add an entry into the combo-box for every prop found
for i in range(len(all_lights)):
row_count = self.rowCount()
self.setRowCount(row_count + 1)
# Create a object name item
item_object = QtWidgets.QTableWidgetItem()
item_object.setText(all_lights[i].GetName())
self.setItem(row_count, 0, item_object)
# Create a active toggle item
active_object = QtWidgets.QTableWidgetItem()
active_object.setText(str(all_lights[i].GetActive()))
self.setItem(row_count, 1, active_object)
# Create multiplier item
multiplier_object = QtWidgets.QTableWidgetItem()
multiplier_object.setText(str(round(all_lights[i].GetMultiplier(), 4)))
self.setItem(row_count, 2, multiplier_object)
# Create a color item
color_object = QtWidgets.QTableWidgetItem()
color = all_lights[i].GetColor()
color_value = "{} - {} - {}".format(color.Red(), color.Green(), color.Blue())
color_object.setText(color_value)
self.setItem(row_count, 3, color_object)
# Create a dialog window
dialog = RLPy.RUi.CreateRDialog()
dialog.SetWindowTitle("Scene Lights")
# Create Pyside layout for RDialog
qt_dialog = wrapInstance(int(dialog.GetWindow()), QtWidgets.QDialog)
main_widget = QtWidgets.QWidget()
qt_dialog.setFixedWidth(350)
# Create a Light Table widget
table_widget = LightTableWidget()
qt_dialog.layout().addWidget(table_widget)
# Add a refresh button
refresh_button = QtWidgets.QPushButton()
refresh_button.setFixedHeight(24)
refresh_button.setText("Refresh List")
refresh_button.clicked.connect(lambda: table_widget.refresh())
qt_dialog.layout().addWidget(refresh_button)
dialog.Show()
APIs Used
You can research the following references for the APIs deployed in this code.