KrzyM Napisano 24 Czerwiec 2015 Napisano 24 Czerwiec 2015 Hej, Dopiero zaczynam uczyć się pythona i utknąłem w punkcie. Mam plik toolsUI.py który przeszukuje folder Modules i dla każdego tworzy przycisk - problem jest że chciałbym żeby każdy przycisk wywoływał odpowiednie okno. Udało mi się już zaimportować każdy moduł do skryptu. np. ToolboxUI.py, jeśli w przycisku wywołam UI = mod.ToolboxUI() to bez problemu otworzy mi się Toolbox. Jednak nie mogę znaleźć sposobu jak automatycznie wywoływać wszystkie skrypty np. coś w stylu plugin = "ToolboxUI()" UI = mod.plugin Mam nadzieje że ktoś jest w stanie mi pomóc ;) Pozdro, Krzysiek Poniżej kod: kTools.py import maya.cmds as cmds import os import System.utils as utils reload(utils) import sys from functools import partial class Ktools_UI: def __init__(self): #uiElements dict self.UIElements = {} if cmds.window("Ktools_UI_Window", exists = True): cmds.deleteUI("Ktools_UI_Window") windowWidth = 200 #Main Window self.UIElements["window"] = cmds.window( "Ktools_UI_Window", menuBar=False, title="KTools", mnb=False, mxb=False ) self.UIElements["columnLayout"] = cmds.columnLayout (adjustableColumn = True, columnAlign="center") self.createPluginsButtons() cmds.showWindow(self.UIElements["window"]) cmds.window(self.UIElements["window"], edit=True, w = windowWidth, sizeable=True) def createPluginsButtons(self): windowHeight = 0 #Plugin folder path systemPath = "System" pluginPath = os.environ["RIGGING_TOOL_ROOT"] + "/modules/" plugins = os.listdir(pluginPath) plugin_list = [] #find modules for plugin in plugins: if ((plugin != "__init__.py") and (plugin != systemPath)): plugin_list.append(plugin) #create buttons for plugin_name in plugin_list: plugin_UI = plugin_name + "UI" #check for UI file for module in utils.findAllModules("Modules/"+ plugin_name): if (module == plugin_UI): #print "UI file found: " + module self.UIElements[(plugin_name + "_button")] = cmds.button( label = plugin_name, h = 64, parent = self.UIElements["columnLayout"], bgc=utils.randomBGC(), c = partial(self.runPlugin, plugin_name) ) windowHeight = windowHeight + 64 cmds.window(self.UIElements["window"], edit=True, h = windowHeight, sizeable=True) def runPlugin(self, plugin, *args): plugin_UI = plugin + "UI" mod = __import__(plugin+"."+plugin_UI, {},{},[plugin]) #btw. class_name is the same as plugin_UI #just testing class_name = mod.CLASS_NAME plugin_UI = plugin + "UI" mod = __import__(plugin+"."+plugin_UI, {},{},[plugin]) reload(mod) class_name = mod.CLASS_NAME #this works UI = mod.ToolboxUI() #e.g. pluginUI == ToolboxUI() #how to run #UI = mod.pluginUI() toolboxUI.py import maya.cmds as cmds import os import maya.mel as mel import toolbox_utils as tU reload(tU) from functools import partial import System.utils as utils reload(utils) CLASS_NAME="ToolboxUI" class ToolboxUI: def __init__(self): self.UIElements = {} windowHeight = 450 windowWidth = 212 if cmds.window("Toolbox", exists = True): cmds.deleteUI("Toolbox") self.UIElements["window"] = cmds.window("Toolbox", mnb=False, mxb=False) self.UIElements["scrollLayout"] = cmds.scrollLayout(hst=0) self.UIElements["mainLayout"] = cmds.columnLayout(adj = True, parent=self.UIElements["scrollLayout"]) cmds.showWindow(self.UIElements["window"]) cmds.window(self.UIElements["window"], edit = True, w=windowWidth, h=windowHeight, sizeable=False) windowHeight3 = self.populateIcons()
Reanimator Napisano 24 Czerwiec 2015 Napisano 24 Czerwiec 2015 Chetnie bym Ci pomogl, ale totalnie nie rozumiem Twojego pytania i problemu ;/ "problem jest że chciałbym żeby każdy przycisk wywoływał odpowiednie okno. " Dlaczego to jest problem?
KrzyM Napisano 24 Czerwiec 2015 Autor Napisano 24 Czerwiec 2015 Mam problem żeby to zrobić. Załóżmy że mamy moduły: Toolbox, PoseSaver, AutoRig - każdy z nich znajduje się w folderze o tej samej nazwie np. Modules/Toolbox w każdym z tych folderów niezależnie jaki to będzie skrypt, przyjąłem że będzie plik główny nazwaModułu_UI.py i klasą o nazwie modułu teraz skrypt KTools.py tworzy poprostu przycisk dla każdego z tych modułów i wywołuje funkcje runPlugin udało mi się "dynamicznie" zaimportować pluginy w pętli #np dla import Toolbox/Toolbox as mod; reload(mod) mod = __import__(plugin+"."+plugin_UI, {},{},[plugin]) reload(mod) - i tutaj zaczyna się problem. żeby np. odpalić Toolbox.py muszę napisać mod.Toolbox() i analogicznie do innych pluginów. nazwę pluginu mam w zmiennej, ale szukam sposobu jak sprawić żeby zadziałało mod.Plugin_UI() Coś jak shelf - przycisk uruchamiający dany skrypt. Ale przy założeniu że mamy N skryptów. Próbowałem coś z exec, partial ale bez skutku. Sory że tak bez składnie to piszę, ale wynika to raczej z mojej niewiedzy o Pythonie - zacząłem się bawić kilka dni temu i jeszcze nie ogarniam wielu elementów.
Reanimator Napisano 24 Czerwiec 2015 Napisano 24 Czerwiec 2015 Hm, mozesz przeleciec cale mod np. tak: for i in dir(mod): print i ten przypadek oczywiscie wypisze nazwy, ale moze wystarczy zrobic z tego eval: for i in dir(mod): eval("mod.{0}()".format(i))
praetorian Napisano 24 Czerwiec 2015 Napisano 24 Czerwiec 2015 Nie wiem czy rozumiem co chcesz zrobic (bo to co robisz jest dziwne), ale chodzi o cos takiego? mod = __import__("os") getenv_function = getattr(mod, "getenv") getenv_function("MAYA_PLUG_IN_PATH", "NotSet")
KrzyM Napisano 24 Czerwiec 2015 Autor Napisano 24 Czerwiec 2015 Reanimator, dzięki - działa super. Muszę przestudiować funkcje wbudowane w Pythona ;) Podrzucisz mi jakieś hasło pod którym znajdę jakieś wytłumaczenie dla tych nawiasów: mod.{0}() Szczerze to nie do końca rozumiem. Praetorian - Reanimator rozwiązał problem. Nie bardzo rozumiem twój kod, ale domyślam się że chodzi o ścieżkę? Ja stworzyłem sobie zmienną w env i przez shelfa główny skrypt wywołuje tak: import os try: riggingToolRoot = os.environ["RIGGING_TOOL_ROOT"] except: print "RIGGING_TOOL_ROOT environment variable not correctly configured" else: import sys print "Running: " + riggingToolRoot path = riggingToolRoot + "/Modules" if not path in sys.path: sys.path.append(path) import System.ktoolsUI as kUI reload(kUI) UI = kUI.Ktools_UI() może to jakoś uzupełni moje poprzednio 2 wklejony kody.
Reanimator Napisano 24 Czerwiec 2015 Napisano 24 Czerwiec 2015 poszukaj string.format :) uzywasz numerow w klamrach, a pozniej podmieniasz je wartosciami zmienna = "cos innego" polaczone = "Lorem {0}, albo {1}".format("Ipsum", zmienna) print polaczone da: "Lorem Ipsum, albo cos innego" W Twoim przypadku zebralem nazwy funkcji z modolow (stringi) i pozniej uzylem ich zeby wywolac kazda z nich za pomoca eval w loopie.
praetorian Napisano 25 Czerwiec 2015 Napisano 25 Czerwiec 2015 Praetorian - Reanimator rozwiązał problem. Nie bardzo rozumiem twój kod, ale domyślam się że chodzi o ścieżkę? Nie o ścieżkę. To samo inaczej (może jaśniej): ty napisałeś: plugin = "ToolboxUI()" UI = mod.plugin ja piszę: plugin = "ToolboxUI()" UI = getattr(mod, plugin)
Kroopson Napisano 25 Czerwiec 2015 Napisano 25 Czerwiec 2015 a nie lepiej jeszcze tak? plugins.py class PluginBase(object): def generate_ui(self): # ui creation pass class RiggingTool(PluginBase): def generate_ui(self): # override this here __init__.py import plugins from plugins import PluginBase def plugin_factory(plugin_name): result = getattr(plugins, plugin_name) if issubclass(result, PluginBase): return result plugin = plugin_factory("RiggingTool") PS. Polecam Ci jednak robić takie rzeczy w PySide a nie w standardowym majkowym UI
KrzyM Napisano 28 Czerwiec 2015 Autor Napisano 28 Czerwiec 2015 Dziękuje wam ;) PySide mam na liście ;) Moje rozwiązanie z góry było skazane na porażkę bo to pierwszy skrypt i tylko forma nauki. Znacie jakieś dobre źródła wiedzy? Obecnie przeglądam tylko manual i czytam "Maya Python for games and film"
Reanimator Napisano 28 Czerwiec 2015 Napisano 28 Czerwiec 2015 Ja uczylem sie z "Python 3 - kompletne wprowadzenie do programowania" z Heliona. Bardzo dokladne i szczegolowe sie wydaje.
KrzyM Napisano 28 Czerwiec 2015 Autor Napisano 28 Czerwiec 2015 PS. Polecam Ci jednak robić takie rzeczy w PySide a nie w standardowym majkowym UI Ogólnie robić całe UI w PySide? Nie używać Maykowego? A co z PyQT? Jeszcze nie bardzo widzę różnicę między PySide a PyQt.
Kroopson Napisano 29 Czerwiec 2015 Napisano 29 Czerwiec 2015 Znacie jakieś dobre źródła wiedzy? Obecnie przeglądam tylko manual i czytam "Maya Python for games and film" "Python od podstaw" - fajna książka i jeszcze o pythonie 2.x (Python 3 nie jest na razie nigdzie implementowany oprócz Blendera chyba). Ogólnie robić całe UI w PySide? Nie używać Maykowego? Tak. PySide to open source PyQt. Ma kilka ograniczeń ale jest wpychane wszędzie ponieważ nie trzeba za niego płacić. Oba wrappery tak naprawdę robią to samo - wywołują kod z bibliotek Qt.
Reanimator Napisano 30 Czerwiec 2015 Napisano 30 Czerwiec 2015 Python 3 nie jest zaimplementowany, ale osobiście nie miałem żadnych problemów (w majce i motionbuilderze) ucząc sie z tej ksiazki. Najwyraźniej różnice nie sa aż tak duże. Anyway: powodzenia!:)
KrzyM Napisano 31 Lipiec 2015 Autor Napisano 31 Lipiec 2015 Hej, odgrzebuje jeszcze ten temat - zmieniłem UI na pySide i nie mogę ogarnąć tego samego ;) W skrócie sytuacja: Mam skrypt "_shelf", który tworzy przyciski dla wszystkich skryptów które spełniają kryteria (odpowiednie nazwy itp). Kliknięcie przycisku przekazuje Nazwę pluginu do funkcji _pluginFactory i ten importuje UI. http://pastebin.com/UpEupcEj W sumie to mi obojętne jak uruchomić te skrypty, byle poprawnie. Zakładam wstępnie że tak chciałbym żeby wyglądał każdy główny plik danego plugina. http://pastebin.com/eXThzDnY I teraz jeśli uruchamiam ten skrypt z majkowego shelfa to robię to tak: http://pastebin.com/4hH5RYnX Dlatego próbuje coś wykąbinować na podstawie wpisu kroopsona, i stworzyłem plik pluginFactory do którego ręcznie będę dodawał classy dla każdego plugina? (No chyba że nie potrzebuje, bo zakładam że uruchamiać je będę tylko poprzez _shelf) http://pastebin.com/u7gjvjJA Próbowałem poprzez getattr, exec ale dostaję wtedy jedynie wynik w stylu: natomiast jeśli uruchomię skrypt tak jak przez majkowy shelf to otrzymuję bardzo podobny wynik Nie znalazłem jeszcze na to rozwiązania, niby wywołuję tą funkcję z powodzeniem ale nie udaje mi się wywołać UI. Napotykam się np na: [code]TypeError: descriptor 'show' of 'PySide.QtGui.QWidget' object needs an argument
CgBartosz Napisano 6 Sierpień 2015 Napisano 6 Sierpień 2015 O ile dobrze rozumiem twoj problem to potrzebujesz dwoch funkcji. 1) zaimportuj moduly do slownika. 2) ze slownika stworz panel z guzikami Polomorfizm zastosuj na poziomie modulu i zasadniczo to tyle. Niech kazdy modul ma funkcje rejestrujaca, przekaz do niej uchwyt/obiekt glownego okna i v'oila. Nie potrzeba tutaj jakichs cudow na kiju. To nie java, ludzie :-)
KrzyM Napisano 6 Sierpień 2015 Autor Napisano 6 Sierpień 2015 Ja już wczytałem wszystkie moduły i zrobiłem z nich przycisk. Każdy przycisk wywołuje funkcje _pluginFactory i przekazuje jej nazwe modułu. Chciałbym żeby ta funkcja wywołała mi okno pySide z moim modułem czyli modul_UI.py http://pastebin.com/UpEupcEj Na dole zakomentowane jak ręcznie zrobie import modulu, i pozniej modul.show() to dziala, ale jak juz zrobię coś jak: __import__(folder+"."+plugin, {},{},[plugin]) To a następnie eval, exec lub getattr to średnio rusza. Nadal szukam jakiś info na ten temat, jeszcze nie do końca rozumiem różnicy między tym jak udało się wywołać te moduły (strona 1), a teraz po przejściu na pySide. Może problem leży w samym uruchomianiu pySide, ale to poruszyłem w tym temacie: http://max3d.pl/forum/threads/98755-PySide-pytania I szukam info dot. rozwiązania Kroopsona.
CgBartosz Napisano 6 Sierpień 2015 Napisano 6 Sierpień 2015 Kiedy wywolujesz import z tymi klamrami, usuwasz caly kontekst dla importowanego modulu. Sprobuj tak: __import__(folder+"."+plugin). Napisz prosze co zwraca ta funkcja po imporcie. Dlaczego nie dziala automatyczny import ? Jakie sa objawy ? I ne kombinuj z getattr itp.. na zaimportowanym module wywowal funkcje polimorficzna i to powinno dzialac. Mozesz.ewemtualnie sprawdzic czy modul ma te funkcje. Pousuwaj wszystkie "__" to niepotrzebne.
KrzyM Napisano 6 Sierpień 2015 Autor Napisano 6 Sierpień 2015 Wydaje mi się że własnie import jest w miarę ok. Teoretycznie jestem wstanie wywołać skrypt z tego importu jak ręcznie podam import.nazwa() przy UI. (komentarze w kodzie) Jak wywołać tą funkcję? Czytałem o tym już i rozumiem koncept, ale w praktyce? Sory za nie ogarniecie ;) #plugin factory def _pluginFactory(self, plugin, *args): self.UIPlugins = {} folder = "__"+plugin.strip('_UI') ##Co mysle ze musze napisac dla plugin = toolBox_UI ## i to otwiera okno poprawnie # import __toolBox.toolBox_UI as tb # reload(tb) # self.UIPlugins["toolBox_UI"] = tb.toolBox_UI() # self.UIPlugins["toolBox_UI"].show() ##tb = ##import importPlugin = __import__(folder+"."+plugin) print "import metoda 1:" + str(importPlugin) importPlugin2 = __import__(folder+"."+plugin, {},{},[plugin]) print "import metoda 2:" + str(importPlugin2) ##import metoda 1: ##import metoda 2: ##teoretycznie metoda 2 zdaje rezultat result = getattr(pFactory, plugin) ##get attr result: ##To czego mi brakuje to wstawienia zmiennej plugin zamiast toolBox_UI() # self.UIPlugins[plugin] = importPlugin2.toolBox_UI() # self.UIPlugins[plugin].show() ##^ teraz tez dziala self.UIPlugins[plugin] = importPlugin.toolBox_UI() self.UIPlugins[plugin].show() ## TypeError: 'module' object is not callable # # # if __name__ == "__main__": # # # try: # # # self.UIPlugins[plugin+"_UI"].close() # # # except: # # # pass
CgBartosz Napisano 7 Sierpień 2015 Napisano 7 Sierpień 2015 http://python-reference.readthedocs.org/en/latest/docs/functions/__import__.html
KrzyM Napisano 7 Sierpień 2015 Autor Napisano 7 Sierpień 2015 Czytałem to i próbowałem różnych opcji jak importowałem to na samym początku, możesz mi wytłumaczyć w czym tkwi różnica i czemu lepiej importować __init__.py i jak wtedy dobrać się do tego pliku? Mam w init.py dodać funkcję która to uruchomi? konkrednie dla zmiennej plugin = "toolBox_UI" wygląda to tak i uruchamia się: import __toolBox.toolBox_UI as tb reload(tb) self.UIPlugins["toolBox_UI"] = tb.toolBox_UI() self.UIPlugins["toolBox_UI"].show() I import daje mi wynik: Dlatego ja importowałem to tak: importPlugin2 = __import__(folder+"."+plugin, {},{},[plugin]) i dawało to taki sam wynik: Dlatego też próbuję wywołać okno przez: Tylko nie wiem jak to wywołać żeby podać za XXXXXX np. plugin15_UI() self.UIPlugins[plugin] = importPlugin2.XXXXXX self.UIPlugins[plugin].show() Natomiast jak importuje w sposób który podałeś importPlugin = __import__(folder+"."+plugin) dostaje wynik:
CgBartosz Napisano 7 Sierpień 2015 Napisano 7 Sierpień 2015 W imporcie bez klamr pomijasz [plugin] i dlatego funkcja zwraca module ale nie "plugin". Czyli wszystko juz dziala jak nalezy ?
KrzyM Napisano 7 Sierpień 2015 Autor Napisano 7 Sierpień 2015 Tak, dzięki - miałem jakieś zaćmienie z tym znowu ;) Użyłem import jak radziłeś, eval i poszło ;) Jak możesz, zajrzyj proszę do drugiego mojego tematu, tam też mam kilka pytań ;)
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się