Difference between revisions of "IC Python API:Float Slider"
Chuck (RL) (Talk | contribs) m (→Everything Put Together) |
Chuck (RL) (Talk | contribs) m |
||
(5 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}} |
[[File:Ic_python_api_float_slider_01.png|frame|left|The slider and the spin-box are interrelated. ]] | [[File:Ic_python_api_float_slider_01.png|frame|left|The slider and the spin-box are interrelated. ]] | ||
− | This article will go over the creation of the popular float slider interface widget. The float slider widget includes a slider bar and a floating point spin-box that are linked in a way that an adjustment on one will effect the other to maintain correlation. | + | This article will go over the creation of the popular float slider interface widget. The float slider widget includes a slider bar and a floating point spin-box that are linked in a way that an adjustment on one will effect the other to maintain correlation.{{Clear}} |
− | {{Clear}} | + | |
== Necessary Modules == | == Necessary Modules == | ||
Line 32: | Line 31: | ||
== Building the UI == | == Building the UI == | ||
+ | |||
+ | [[File:Ic_python_api_float_slider_03.gif|frame|Individual widgets are not much use for an interactive float slider widget.]] | ||
Next, we'll create a dock-able window and add the slider and double spin-box widget. | Next, we'll create a dock-able window and add the slider and double spin-box widget. | ||
Line 67: | Line 68: | ||
== Correlating the Widgets == | == Correlating the Widgets == | ||
+ | |||
+ | [[File:Ic_python_api_float_slider_02.gif|frame|Linked widgets improves usability significantly]] | ||
We'll have to link the slider and the double spin-box values with the following code. | We'll have to link the slider and the double spin-box values with the following code. | ||
Line 78: | Line 81: | ||
Notice that default value input happens after the widgets are linked so they are adjusted in lock-step. | Notice that default value input happens after the widgets are linked so they are adjusted in lock-step. | ||
+ | |||
+ | {{Notice|Qt does not provide a native float or double slider. Instead we hack the integer slider to behave like a double slider by giving it a high integer range and dividing by the same range value to retrieve the double value.}} | ||
== Everything Put Together == | == Everything Put Together == |
Latest revision as of 19:37, 18 October 2020
- Main article: Python of the Month.
Necessary Modules
Get started by loading the required modules for the script.
import RLPy
from PySide2 import QtWidgets
from PySide2.shiboken2 import wrapInstance
from PySide2.QtCore import *
We'll need RLPy to access iClone's Python API and Pyside2 related modules to create a functional interface.
Qt Widgets
The Qt Widgets module extends Qt GUI with C++ widget functionality. This is the building blocks for composing the user interface. To learn more about Qt user interface creation with Pyside2, see Pyside2 QtWidgets
Shiboken2
Shiboken is the Python binding generator that Qt for Python uses to create the PySide module, in other words, its the system used to expose the Qt C++ API to Python. The name Shiboken2 and Pyside2 make reference to the Qt5 compatibility, since the previous versions (without the 2) refer to Qt4. For more information, see the Shiboken documentation
QtCore
QtCore provides core non-GUI functionality with all other Qt modules relying on this module. For more information, see the QtCore documentation
Building the UI
Next, we'll create a dock-able window and add the slider and double spin-box widget.
# Create an iClone Dock Widget
dockable_window = RLPy.RUi.CreateRDockWidget()
dockable_window.SetWindowTitle("Float Slider")
# Use wrapInstance to convert the dockable window to something that Python can understand, in this case a Dock Widget
dock = wrapInstance(int(dockable_window.GetWindow()), QtWidgets.QDockWidget)
# Create the main widget for the dock window
main_widget = QtWidgets.QWidget()
dock.setWidget(main_widget)
dock.setFixedWidth(300)
# Create the layout for the widgets, in this case a horizontal box layout
parent_layout = QtWidgets.QHBoxLayout()
main_widget.setLayout(parent_layout)
# Configurable attributes
span = (0, 1) # The min and max value for the float slider range
factor = 1000 # Density of the float slider, more allows for finer control
default = 0 # Default starting value for the float slider, does not go beyond the range of the span
# Create the slider and double spin box according to the configurable attributes above
slider = QtWidgets.QSlider(orientation=Qt.Horizontal, singleStep=1, maximum=span[1] * factor, minimum=span[0] * factor)
double_spinBox = QtWidgets.QDoubleSpinBox(singleStep=0.025 * span[1], decimals=len(str(factor)) - 1, maximum=span[1], minimum=span[0])
# Attach the slider and double spinbox to the horizontal box layout
parent_layout.addWidget(slider)
parent_layout.addWidget(double_spinBox)
Correlating the Widgets
We'll have to link the slider and the double spin-box values with the following code.
# Create the commands to link the slider and double spinbox values
double_spinBox.valueChanged.connect(lambda x: slider.setValue(x * factor)) # Slider value = double spinbox value times the factor
slider.valueChanged.connect(lambda x: double_spinBox.setValue(x / factor)) # Double spinbox value = slider value divided by the factor
double_spinBox.setValue(default) # Adjust the spinbox value after the widgets are linked
Notice that default value input happens after the widgets are linked so they are adjusted in lock-step.
- ⚠ Qt does not provide a native float or double slider. Instead we hack the integer slider to behave like a double slider by giving it a high integer range and dividing by the same range value to retrieve the double value.
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
from PySide2.QtCore import *
# Create an iClone Dock Widget
dockable_window = RLPy.RUi.CreateRDockWidget()
dockable_window.SetWindowTitle("Float Slider")
# Use wrapInstance to convert the dockable window to something that Python can understand, in this case a Dock Widget
dock = wrapInstance(int(dockable_window.GetWindow()), QtWidgets.QDockWidget)
# Create the main widget for the dock window
main_widget = QtWidgets.QWidget()
dock.setWidget(main_widget)
dock.setFixedWidth(300)
# Create the layout for the widgets, in this case a horizontal box layout
parent_layout = QtWidgets.QHBoxLayout()
main_widget.setLayout(parent_layout)
# Configurable attributes
span = (0, 1) # The min and max value for the float slider range
factor = 1000 # Density of the float slider, more allows for finer control
default = 0 # Default starting value for the float slider, does not go beyond the range of the span
# Create the slider and double spin box according to the configurable attributes above
slider = QtWidgets.QSlider(orientation=Qt.Horizontal, singleStep=1, maximum=span[1] * factor, minimum=span[0] * factor)
double_spinBox = QtWidgets.QDoubleSpinBox(singleStep=0.025 * span[1], decimals=len(str(factor)) - 1, maximum=span[1], minimum=span[0])
# Attach the slider and double spinbox to the horizontal box layout
parent_layout.addWidget(slider)
parent_layout.addWidget(double_spinBox)
# Create the commands to link the slider and double spinbox values
double_spinBox.valueChanged.connect(lambda x: slider.setValue(x * factor)) # Slider value = double spinbox value times the factor
slider.valueChanged.connect(lambda x: double_spinBox.setValue(x / factor)) # Double spinbox value = slider value divided by the factor
double_spinBox.setValue(default) # Adjust the spinbox value after the widgets are linked
dockable_window.Show()
APIs Used
You can research the following references for the APIs deployed in this code.