Difference between revisions of "IC Python API:Progress Bar"

From Reallusion Wiki!
Jump to: navigation, search
(Created page with "{{TOC}} {{Parent|IC_Python_API:RL_Python_Samples|RL Python Samples}} File:Ic_python_api_prime_number_01.png This lesson will go over the creation of a progress bar as on...")
 
m
 
(12 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
{{TOC}}
 
{{TOC}}
{{Parent|IC_Python_API:RL_Python_Samples|RL Python Samples}}
+
{{Parent|IC_Python_API#Python_of_the_Month|Python of the Month}}
 +
 
 +
This article will go over the creation of a progress bar as one of the fundamental building blocks of a functional user interface.  This is useful for operations that require a good amount of time to complete.  You should include a progress bar in your user interface for scripts that take longer than a couple of seconds to complete.  For this example, we'll be creating a prime number finder that looks like the following:
  
 
[[File:Ic_python_api_prime_number_01.png]]
 
[[File:Ic_python_api_prime_number_01.png]]
  
This lesson will go over the creation of a progress bar as one of the fundamental building blocks of a functional user interface.
+
== Required Modules ==
 +
 
 +
Besides the fundamental Reallusion Python module, you'll also need '''Pyside2''' to build the user interface.
 +
 
 +
<syntaxhighlight lang="Python">
 +
import RLPy
 +
from PySide2 import QtWidgets
 +
from PySide2.shiboken2 import wrapInstance
 +
</syntaxhighlight>
 +
 
 +
== Prime Number Checker ==
 +
 
 +
For our CPU intensive operation, we'll be checking for prime numbers from 1 to 10,000.  A prime number is natural number greater than 1 that cannot be formed by multiplying two smaller natural numbers. The opposite of this is a composite number. For example, 5 is prime because the only ways of writing it as a product, 1 × 5 or 5 × 1, involve 5 itself. However, 6 is composite because it is the product of two numbers (2 × 3) that are both smaller than 6.
 +
 
 +
<syntaxhighlight lang="Python">
 +
def check_prime_number(num):
 +
    if num > 1:    # Prime numbers are greater than 1
 +
        for i in range(2, num):    # Check for factors
 +
            if (num % i) == 0:
 +
                return False
 +
        else:
 +
            return True
 +
    else:    # If input number is less than or equal to 1, it is not prime
 +
        return False
 +
</syntaxhighlight>
 +
 
 +
== Building the UI ==
 +
 
 +
[[File: Ic_python_api_prime_number_02.png|frame]]
 +
 
 +
<syntaxhighlight lang="Python">
 +
window = RLPy.RUi.CreateRDockWidget()
 +
window.SetWindowTitle("All Prime Numbers (0-10K)")
 +
 
 +
dock = wrapInstance(int(window.GetWindow()), QtWidgets.QDockWidget)
 +
dock.setFixedSize(350, 350)
 +
dock.setStyleSheet(
 +
    """ QProgressBar{ font: bold; color: black; border: 1px solid black; background-color: grey;}
 +
        QProgressBar::chunk { width: 1px; background-color: #13c1ec}""")
 +
 
 +
widget = QtWidgets.QWidget()
 +
dock.setWidget(widget)
 +
 
 +
layout = QtWidgets.QVBoxLayout()
 +
widget.setLayout(layout)
 +
 
 +
progress_bar = QtWidgets.QProgressBar()
 +
 
 +
text_edit = QtWidgets.QTextEdit(readOnly=True)
 +
 
 +
button = QtWidgets.QPushButton("Calculate")
 +
button.clicked.connect(run)
 +
 
 +
for widget in [progress_bar, text_edit, button]:
 +
    layout.addWidget(widget)
 +
 
 +
window.Show()
 +
</syntaxhighlight>
 +
 
 +
Notice the '''Calculate''' button runs a function to start the entire prime number search process which is covered below.
 +
 
 +
== Running the Script ==
 +
 
 +
[[File:Ic_python_api_prime_numbers_03.gif|frame]]
 +
 
 +
Keep in mind that progress bars may not always run smoothly. Particularly when the operations are very taxing on the system, one may experience fits and starts from time to time.
 +
 
 +
<syntaxhighlight lang="Python">
 +
def run():
 +
 
 +
    progress_bar.setRange(1, 10000)
 +
    button.setHidden(True)
 +
    found = 0
 +
 
 +
    for i in range(1, 10001):
 +
        if check_prime_number(i):
 +
            text_edit.insertPlainText("{:,}".format(i) + "\t")
 +
            found += 1
 +
        progress_bar.setValue(i)
 +
        progress_bar.setFormat(f"Calculating: {round(i/100)}%")
 +
        bottom = text_edit.verticalScrollBar().maximum()
 +
        text_edit.verticalScrollBar().setValue(bottom)
 +
 
 +
    progress_bar.setFormat(f"{ '{:,}'.format(found) } prime numbers found.")
 +
</syntaxhighlight>
 +
 
 +
== Everything Put Together ==
 +
 
 +
You can copy and paste the following code into a PY file and load it into iClone via '''Script > Load Python'''.
 +
 
 +
<syntaxhighlight lang="Python">
 +
import RLPy
 +
from PySide2 import QtWidgets
 +
from PySide2.shiboken2 import wrapInstance
 +
 
 +
 
 +
def check_prime_number(num):
 +
    if num > 1:    # Prime numbers are greater than 1
 +
        for i in range(2, num):    # Check for factors
 +
            if (num % i) == 0:
 +
                return False
 +
        else:
 +
            return True
 +
    else:    # If input number is less than or equal to 1, it is not prime
 +
        return False
 +
 
 +
 
 +
def run():
 +
 
 +
    progress_bar.setRange(1, 10000)
 +
    button.setHidden(True)
 +
    found = 0
 +
 
 +
    for i in range(1, 10001):
 +
        if check_prime_number(i):
 +
            text_edit.insertPlainText("{:,}".format(i) + "\t")
 +
            found += 1
 +
        progress_bar.setValue(i)
 +
        progress_bar.setFormat(f"Calculating: {round(i/100)}%")
 +
        bottom = text_edit.verticalScrollBar().maximum()
 +
        text_edit.verticalScrollBar().setValue(bottom)
 +
 
 +
    progress_bar.setFormat(f"{ '{:,}'.format(found) } prime numbers found.")
 +
 
 +
 
 +
window = RLPy.RUi.CreateRDockWidget()
 +
window.SetWindowTitle("All Prime Numbers (0-10K)")
 +
 
 +
dock = wrapInstance(int(window.GetWindow()), QtWidgets.QDockWidget)
 +
dock.setFixedSize(350, 350)
 +
dock.setStyleSheet(
 +
    """ QProgressBar{ font: bold; color: black; border: 1px solid black; background-color: grey;}
 +
        QProgressBar::chunk { width: 1px; background-color: #13c1ec}""")
 +
 
 +
widget = QtWidgets.QWidget()
 +
dock.setWidget(widget)
 +
 
 +
layout = QtWidgets.QVBoxLayout()
 +
widget.setLayout(layout)
 +
 
 +
progress_bar = QtWidgets.QProgressBar()
 +
 
 +
text_edit = QtWidgets.QTextEdit(readOnly=True)
 +
 
 +
button = QtWidgets.QPushButton("Calculate")
 +
button.clicked.connect(run)
 +
 
 +
for widget in [progress_bar, text_edit, button]:
 +
    layout.addWidget(widget)
 +
 
 +
window.Show()
 +
</syntaxhighlight>
 +
 
 +
=== APIs Used ===
 +
You can research the following references for the APIs deployed in this code.
 +
<div style="column-count:4; -moz-column-count:4; -webkit-column-count:4">
 +
* [[ IC_Python_API:RLPy_RUi#CreateRDockWidget | RLPy.RUi.CreateRDockWidget() ]]
 +
</div>

Latest revision as of 20:39, 18 October 2020

Main article: Python of the Month.

This article will go over the creation of a progress bar as one of the fundamental building blocks of a functional user interface. This is useful for operations that require a good amount of time to complete. You should include a progress bar in your user interface for scripts that take longer than a couple of seconds to complete. For this example, we'll be creating a prime number finder that looks like the following:

Ic python api prime number 01.png

Required Modules

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

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

Prime Number Checker

For our CPU intensive operation, we'll be checking for prime numbers from 1 to 10,000. A prime number is natural number greater than 1 that cannot be formed by multiplying two smaller natural numbers. The opposite of this is a composite number. For example, 5 is prime because the only ways of writing it as a product, 1 × 5 or 5 × 1, involve 5 itself. However, 6 is composite because it is the product of two numbers (2 × 3) that are both smaller than 6.

def check_prime_number(num):
    if num > 1:    # Prime numbers are greater than 1
        for i in range(2, num):     # Check for factors
            if (num % i) == 0:
                return False
        else:
            return True
    else:     # If input number is less than or equal to 1, it is not prime
        return False

Building the UI

Ic python api prime number 02.png
window = RLPy.RUi.CreateRDockWidget()
window.SetWindowTitle("All Prime Numbers (0-10K)")

dock = wrapInstance(int(window.GetWindow()), QtWidgets.QDockWidget)
dock.setFixedSize(350, 350)
dock.setStyleSheet(
    """ QProgressBar{ font: bold; color: black; border: 1px solid black; background-color: grey;} 
        QProgressBar::chunk { width: 1px; background-color: #13c1ec}""")

widget = QtWidgets.QWidget()
dock.setWidget(widget)

layout = QtWidgets.QVBoxLayout()
widget.setLayout(layout)

progress_bar = QtWidgets.QProgressBar()

text_edit = QtWidgets.QTextEdit(readOnly=True)

button = QtWidgets.QPushButton("Calculate")
button.clicked.connect(run)

for widget in [progress_bar, text_edit, button]:
    layout.addWidget(widget)

window.Show()

Notice the Calculate button runs a function to start the entire prime number search process which is covered below.

Running the Script

Ic python api prime numbers 03.gif

Keep in mind that progress bars may not always run smoothly. Particularly when the operations are very taxing on the system, one may experience fits and starts from time to time.

def run():

    progress_bar.setRange(1, 10000)
    button.setHidden(True)
    found = 0

    for i in range(1, 10001):
        if check_prime_number(i):
            text_edit.insertPlainText("{:,}".format(i) + "\t")
            found += 1
        progress_bar.setValue(i)
        progress_bar.setFormat(f"Calculating: {round(i/100)}%")
        bottom = text_edit.verticalScrollBar().maximum()
        text_edit.verticalScrollBar().setValue(bottom)

    progress_bar.setFormat(f"{ '{:,}'.format(found) } prime numbers found.")

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


def check_prime_number(num):
    if num > 1:    # Prime numbers are greater than 1
        for i in range(2, num):     # Check for factors
            if (num % i) == 0:
                return False
        else:
            return True
    else:     # If input number is less than or equal to 1, it is not prime
        return False


def run():

    progress_bar.setRange(1, 10000)
    button.setHidden(True)
    found = 0

    for i in range(1, 10001):
        if check_prime_number(i):
            text_edit.insertPlainText("{:,}".format(i) + "\t")
            found += 1
        progress_bar.setValue(i)
        progress_bar.setFormat(f"Calculating: {round(i/100)}%")
        bottom = text_edit.verticalScrollBar().maximum()
        text_edit.verticalScrollBar().setValue(bottom)

    progress_bar.setFormat(f"{ '{:,}'.format(found) } prime numbers found.")


window = RLPy.RUi.CreateRDockWidget()
window.SetWindowTitle("All Prime Numbers (0-10K)")

dock = wrapInstance(int(window.GetWindow()), QtWidgets.QDockWidget)
dock.setFixedSize(350, 350)
dock.setStyleSheet(
    """ QProgressBar{ font: bold; color: black; border: 1px solid black; background-color: grey;} 
        QProgressBar::chunk { width: 1px; background-color: #13c1ec}""")

widget = QtWidgets.QWidget()
dock.setWidget(widget)

layout = QtWidgets.QVBoxLayout()
widget.setLayout(layout)

progress_bar = QtWidgets.QProgressBar()

text_edit = QtWidgets.QTextEdit(readOnly=True)

button = QtWidgets.QPushButton("Calculate")
button.clicked.connect(run)

for widget in [progress_bar, text_edit, button]:
    layout.addWidget(widget)

window.Show()

APIs Used

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