Difference between revisions of "IC Python API:Progress Bar"
Chuck (RL) (Talk | contribs) (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...") |
Chuck (RL) (Talk | contribs) m |
||
(12 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{TOC}} | {{TOC}} | ||
− | {{Parent|IC_Python_API | + | {{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]] | ||
− | + | == 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 19: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:
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
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
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.