What is the best way to gather a list of values from ui and use it?

79 views
Skip to first unread message

yann19

unread,
Mar 15, 2017, 8:57:18 PM3/15/17
to Python Programming for Autodesk Maya
I got a couple of QPushButton(s) in which their text are changeable as user clicks on it. And also,
a couple of QLineEdits that specify the minimum and maximum values for scaling.

So when user clicks on the 'Create' button, it will takes in these texts as part of the information,
and creates the nodes while applying the information onto the new nodes.

Eg. 

# The default button/ text to be shown will be Sphere
self.geo_btn = QtGui.QPushButton('Sphere')
self.cmd_btn = QtGui.QPushButton('Duplicate')
self.scale_x = QtGui.QCheckBox('Scale')
# If self.scale_x is checked, min_x and max_x will be used
# Else, it will be ignored
self.min_x = QtGui.QLineEdit('1.0')
self.max_x = QtGui.QLineEdit('1.0')

def which_geo(self):
 
# Default text is Sphere
 
# Switch to Cube if button is hit, and vice verse
   
if self.geo_btn.text() == 'Sphere':
       
self.geo_btn.setText('Cube')
   
else:
       
self.geo_btn.setText('Sphere')

def which_cmd(self):
  if self.cmd_btn.text() == 'Duplicate':
    self.cmd_btn.setText('Instance')
    else:
    self.cmd_btn.setText('Duplicate')

def create_node(self):
 
# How do I write my function here?



Suppose if the push buttons are 'Cube' and 'Duplicate', and I checked scale_x withthe min value being 1.0
while max value is 2.0, how should I write in `create_node()`?
Should I store such variables as a dictionary or some sort so that it will be easier for me to call and use
the values?

I am not sure what is the best way for me to call such values.. 
FYI, I have quite some widgets in my ui in which I need them for my new node creations

Justin Israel

unread,
Mar 16, 2017, 12:23:50 AM3/16/17
to python_in...@googlegroups.com
On Thu, Mar 16, 2017 at 1:57 PM yann19 <yang...@gmail.com> wrote:

Suppose if the push buttons are 'Cube' and 'Duplicate', and I checked scale_x withthe min value being 1.0
while max value is 2.0, how should I write in `create_node()`?
Should I store such variables as a dictionary or some sort so that it will be easier for me to call and use
the values?

I am not sure what is the best way for me to call such values.. 
FYI, I have quite some widgets in my ui in which I need them for my new node creations


First, I would recommend repeating string literals as little as possible. It is prone to error if you make a typo somewhere or change the naming. 

TYPE_CUBE = "Cube"
ACTION_DUP = "Duplicate"

def which_geo(self):
    if self.geo_btn.text() == TYPE_CUBE:
        ...

def which _cmd(self):
    if self.cmd_btn.text() == ACTION_DUP:
        ...

In order to handle these types and actions more dynamically, as you request, you could accomplish as simply as with a dictionary, or you could organize things into classes. 

TYPE_SPHERE = "Sphere"
TYPE_CUBE = "Cube"
ACTION_DUP = "Duplicate"
ACTION_INST = "Instance"

def sphere_duplicate(*args, **kwargs):
    #...

action_map = {
    TYPE_SPHERE: {
        ACTION_DUP: sphere_duplicate,
        ACTION_INST: sphere_instance,
    },
    TYPE_CUBE: {
        ACTION_DUP: cube_duplicate,
        ACTION_INST: cube_instance,
    },
}

This creates a mapping of object types to actions and functions.
If you wanted to be more organized than this, you could do it with classes.

class ObjectActioner(object):
    NAME=""

    def callByName(self, name, *args, **kwargs):
        name = name.lower()
        fn = getattr(self, name)
        return fn(*args, **kwargs)

    def duplicate(self, *args, **kwargs):
        raise NotImplementedError()

    def instance(self, *args, **kwargs):
        raise NotImplementedError()

class Sphere(ObjectActioner):
    NAME = "Sphere"

    def duplicate(self, *args, **kwargs):
        #...

    def instance(self, *args, **kwargs):
        #...

class Cube(ObjectActioner):
    NAME = "Cube"
    #...

object_map = {
    Sphere.NAME: Sphere,
    Cube.NAME: Cube,
}

Once you have some kind of mapping, then it is just a matter of looking up the correct object or function and passing it the arguments in your create_node() function. This would be instead of having to do complicated "if then" logic in create_node()

Justin

 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/cf106490-d8d7-41c2-82fd-a8312e36cbb8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

yann19

unread,
Mar 16, 2017, 12:57:04 PM3/16/17
to Python Programming for Autodesk Maya
Hi Justin, thanks for getting back.

I will try out with the examples you have provided, greatly appreciated for it. And see how much can I do.

Some questions I have in mind though, if you do not mind answering... It is a bit off-topic..

Generally when I wrote my ui code, it comes in its own class with the necesasry initialization and after the `self.connect_signals()` I will be scripting in the functions/ methods for the signals,
or addiitonal functions that is required.

# UI file
class UIManager(QtGui.QDialog):
   
def __init__(self, parent=None):
       
#QtGui.QDialog.__init__(self, parent)
       
super(UIManager, self).__init__(parent)
       
self.tool_title = 'UI MANAGER'
       
self.setWindowTitle(self.tool_title)
       
self.setModal(False)
       
self.init_ui()
       
self.connect_signals()
       
self.setFixedSize(QtCore.QSize(450, 1000))


   
def button_signal_action(self):
   
...
   
...
   
   
# More and coming functions for the signals or any other functions
   
...
   
...


def main():
    dialog
= UIManager()
    dialog
.show()
   
return dialog


At times, I will create a script called utils file if there are functions that are either used in the UI file/ shared across with other scripts for 
easy maintenance

1. In such cases, should the signals functions and the ui initialization be separated into 2 different files?

2. If there are several classes within a script file in which it can make debugging un-manageable, while I think it will be better to break up these classes
into separate files, is it wise to do so? If so, what are some of the procedures to take note of?

Justin Israel

unread,
Mar 16, 2017, 4:47:27 PM3/16/17
to python_in...@googlegroups.com


On Fri, Mar 17, 2017 at 5:57 AM yann19 <yang...@gmail.com> wrote:
... 
At times, I will create a script called utils file if there are functions that are either used in the UI file/ shared across with other scripts for 
easy maintenance

1. In such cases, should the signals functions and the ui initialization be separated into 2 different files?

My opinion is that the consumer of the widget should wire up any signals it cares about on those widgets, to slots it knows about. So if your UI is composed of a bunch of internal widgets which are not part of the public interface then it should connect those up itself. Then the UI can expose its own top level signals for things that a consume of that UI class should have access to.

In another class consuming the UI, it would make use of the top level signals or signals of any of the documented public child widgets of the class.

 

2. If there are several classes within a script file in which it can make debugging un-manageable, while I think it will be better to break up these classes
into separate files, is it wise to do so? If so, what are some of the procedures to take note of?

A module should consist of logic that shares the same purpose. If all of the content in that file, which shares the same purpose, makes the file larger than you feel is manageable, then an option is to turn the single file module into a package, and split the content into modules of that package.

So if you have something like:

database.py

And the User and Project content within that module become too large. You can split it into something like this:

database/
    __init__.py
    user.py
    project.py

And you could even import those two modules into your __init__.py so that the database package behaves like it did before.

Justin
 

yann19

unread,
Mar 22, 2017, 8:28:10 PM3/22/17
to Python Programming for Autodesk Maya
Actually I am trying to rewrite this tool - spPaint3d (https://www.highend3d.com/maya/script/sppaint3d-for-maya), adding a few more features
and at the same time trying to revamp the code while improving my coding skills.

Though I manage to get the Uis and some of the widgets done, (if you have downloaded the python code), it is has quite some stuff all over the place which makes it hard for me to add in the additional features.

As for the split ups, I am still trying to get my head around it, especially so when I am still unsure if I should place both the ui creations and signals together in a file (usually that is what I did but they are of small code files) or if I should split it.
This may be a bit much to ask, but is there any documentations / sample codes that I can refer to for reference?

Justin Israel

unread,
Mar 23, 2017, 4:43:32 PM3/23/17
to python_in...@googlegroups.com
I don't have any documentation or samples to offer on the subject, but basically just read the code of any established pyqt project, possible?

It is a general programming practice to apply separation of concerns to your units of code (classes, modules, ..) and also to keep an eye on your public API of any object. So ideally what you are trying to do is have good encapsulation, where a particular class hides away as much of the implementation details as possible, while providing only the neccessary top level access as public attributes. This means trying to hide away embedded child widgets and objects if you can, and routing child signals to the top if they are important to expose. The less you expose on the surface of your APIs, the less likely they are to break consumers of that code if you were to make changes
 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

yann19

unread,
Mar 23, 2017, 6:39:18 PM3/23/17
to Python Programming for Autodesk Maya
Noted on that. Will try and see if I can find similar code projects.

I am trying to figure out how best it will be, in this case, to store the values as a dictionary and how to update/ use them as it is being called.11
Reply all
Reply to author
Forward
0 new messages