IC Python API:List View

From Reallusion Wiki!
Jump to: navigation, search

Main article: RL Python Samples.

Ic python api list view 01.png

The Qt list widget is a useful UI element for listing items that belong to the same grouping, i.e. they share a set of common attributes. Imagine if you were going to do some grocery shopping. You would likely pick out items you were in short supply of at home, like food stuffs, kitchen / bathroom appliances, etc. The common theme for all of these items are that they are household goods that are bought in the same location such as a super market. These items are not hierarchical in nature, but they may be related, i.e. cereals are related to milk, but not to mops and microwaves.

If you are listing items that are part of a relational structure that have a clear parent and child hierarchy, then you are better off using a Qt tree widget.

Necessary Modules

Besides the fundamental Reallusion Python module, we'll also need Pyside2 to build the user interface.

import RLPy
from PySide2 import QtWidgets
from PySide2.shiboken2 import wrapInstance
from PySide2.QtCore import Qt

Creating the Window

Ic python api list view 02.png

Let's create a an interface where, items can be named, added, editing, and removed from a list.

# Create a dialog window
window = RLPy.RUi.CreateRDialog()
window.SetWindowTitle("Qt List View")

# Create Pyside layout for RDialog
dialog = wrapInstance(int(window.GetWindow()), QtWidgets.QDialog)
main_widget = QtWidgets.QWidget()
dialog.setFixedSize(300, 300)
dialog.setStyleSheet("::item{color:grey} ::item:selected{color:white; background-color:grey; font-weight: bold;}")

# Create a list widget
list_widget = QtWidgets.QListWidget()
list_widget.setAlternatingRowColors(True)
list_widget.setStyleSheet("background-color:#222222; alternate-background-color:#1a1a1a;")
dialog.layout().addWidget(list_widget)

# Create a line edit field
line_edit = QtWidgets.QLineEdit()
line_edit.setAlignment(Qt.AlignCenter)
line_edit.setPlaceholderText("Unknown Item")
dialog.layout().addWidget(line_edit)

# Create an add button
add_button = QtWidgets.QPushButton("Add")
add_button.setFixedHeight(24)
dialog.layout().addWidget(add_button)

# Create an edit button
edit_button = QtWidgets.QPushButton("Edit")
edit_button.setFixedHeight(24)
dialog.layout().addWidget(edit_button)

# Create a remove button
remove_button = QtWidgets.QPushButton("Remove")
remove_button.setFixedHeight(24)
dialog.layout().addWidget(remove_button)

window.Show()

Adding and Removing Items

We'll need some function to add, remove, and edit items from the list widget, and attach them to the proper buttons:

Adding List Items

def add_list_item():
    name = line_edit.text() or "Unknown Item"
    name = check_duplicate_names(name)
    listItem = QtWidgets.QListWidgetItem(name, list_widget)
    listItem.setFlags(listItem.flags() | Qt.ItemIsEditable)
    line_edit.clear()


add_button.clicked.connect(add_list_item)

Notice that we check for duplicate name entries before we add the item to the list: check_duplicate_names(name). This is done in the following manner:

def check_duplicate_names(name, num=0):
    _name = name
    if(num > 0):
        _name += str(num)

    for i in range(list_widget.count()):
        if list_widget.item(i).text() == _name:
            return check_duplicate_names(name, num+1)

    return _name

Notice that this is a recursive function which calls itself when a duplicate name is found, until a unique name is formed. Recursive functions like this must be handled carefully, therefore, novice programmers are advised to implement an error exception when dealing with recurring loops.

A recursive function is a function that calls itself during its execution. This enables the function to repeat itself several times, outputting the result and the end of each iteration.

Removing List Items

def remove_list_item():
    items = list_widget.selectedItems()
    for item in items:
        list_widget.takeItem(list_widget.row(item))


remove_button.clicked.connect(remove_list_item)

Editing List Items

We can edit the names of the list items with the following function:

def edit_list_item():
    items = list_widget.selectedItems()
    if len(items) > 0:
        list_widget.editItem(items[0])


edit_button.clicked.connect(edit_list_item)

Everything Put Together

Ic python api list view 03.gif

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
from PySide2.QtCore import Qt

# Create a dialog window
window = RLPy.RUi.CreateRDialog()
window.SetWindowTitle("Qt List View")

# Create Pyside layout for RDialog
dialog = wrapInstance(int(window.GetWindow()), QtWidgets.QDialog)
main_widget = QtWidgets.QWidget()
dialog.setFixedSize(300, 300)
dialog.setStyleSheet("::item{color:grey} ::item:selected{color:white; background-color:grey; font-weight: bold;}")

# Create a list widget
list_widget = QtWidgets.QListWidget()
list_widget.setAlternatingRowColors(True)
list_widget.setStyleSheet("background-color:#222222; alternate-background-color:#1a1a1a;")
dialog.layout().addWidget(list_widget)

# Create a line edit field
line_edit = QtWidgets.QLineEdit()
line_edit.setAlignment(Qt.AlignCenter)
line_edit.setPlaceholderText("Unknown Item")
dialog.layout().addWidget(line_edit)

# Create an add button
add_button = QtWidgets.QPushButton("Add")
add_button.setFixedHeight(24)
dialog.layout().addWidget(add_button)

# Create an edit button
edit_button = QtWidgets.QPushButton("Edit")
edit_button.setFixedHeight(24)
dialog.layout().addWidget(edit_button)

# Create a remove button
remove_button = QtWidgets.QPushButton("Remove")
remove_button.setFixedHeight(24)
dialog.layout().addWidget(remove_button)

window.Show()


def add_list_item():
    name = line_edit.text() or "Unknown Item"
    name = check_duplicate_names(name)
    listItem = QtWidgets.QListWidgetItem(name, list_widget)
    listItem.setFlags(listItem.flags() | Qt.ItemIsEditable)
    line_edit.clear()


add_button.clicked.connect(add_list_item)


def remove_list_item():
    items = list_widget.selectedItems()
    for item in items:
        list_widget.takeItem(list_widget.row(item))


remove_button.clicked.connect(remove_list_item)


def edit_list_item():
    items = list_widget.selectedItems()
    if len(items) > 0:
        list_widget.editItem(items[0])


edit_button.clicked.connect(edit_list_item)


def check_duplicate_names(name, num=0):
    _name = name
    if(num > 0):
        _name += str(num)

    for i in range(list_widget.count()):
        if list_widget.item(i).text() == _name:
            return check_duplicate_names(name, num+1)

    return _name

APIs Used

You can research the following references for the APIs deployed in this code.