Difference between revisions of "IC Python API:Table View"

From Reallusion Wiki!
Jump to: navigation, search
m
m
Line 22: Line 22:
 
== Light Table Widget ==
 
== Light Table Widget ==
  
 +
[[File:Ic_python_api_lights_table_02.png|frame]]
  
 +
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.
  
 +
<syntaxhighlight lang="python">
 +
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)
 +
</syntaxhighlight>
  
 +
Notice how the resize policy is set by adjusting the '''header''' attribute.
  
=== Refresh Function ===
+
== Refresh Function ==
 +
 
 +
[[File:Ic_python_api_lights_table_03.png|frame]]
 +
 
 +
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).
 +
 
 +
<syntaxhighlight lang = "python">
 +
    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)
 +
</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 which would look like the following:
 +
 
 +
<syntaxhighlight lang="python">
 +
table_widget = LightTableWidget()
 +
table_widget.refresh()
 +
</syntaxhighlight>
 +
 
 +
== Dialog Window Boilerplate ==
 +
 
 +
[[File:Ic_python_api_lights_table_04.png|frame]]
 +
 
 +
In order for us to show the scene lights table list we must first create a window and declare an instance of our custom table class.
 +
 
 +
<syntaxhighlight lang="python">
 +
# 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)
 +
</syntaxhighlight>
 +
 
 +
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.
 +
 
 +
<syntaxhighlight lang= "python">
 +
# 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()
 +
</syntaxhighlight>

Revision as of 22:25, 15 December 2019

Main article: RL Python Samples.
Ic python api lights table 01.png
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 your assets are part of a hierarchical structure, then a QT tree widget would be more suitable

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

Ic python api lights table 02.png

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

Ic python api lights table 03.png

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. refresh method from outside of the class after its declaration which would look like the following:

table_widget = LightTableWidget()
table_widget.refresh()

Dialog Window Boilerplate

Ic python api lights table 04.png

In order for us to show the scene lights table list we must first create a window and declare an instance of our custom table class.

# 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()