Diferencia entre revisiones de «Obijuan:Notas sobre programación en python en Freecad»
(Página creada con «== Introducción == Quiero aprender a programar piezas en Freecad, al estilo openscad, para poder hacer piezas paramétricas. Empezaremos con ruedas paramétricas para pri...») |
(→Información de interés) |
||
(No se muestran 42 ediciones intermedias del mismo usuario) | |||
Línea 5: | Línea 5: | ||
== Roadmap == | == Roadmap == | ||
− | + | # Hello world: programar un cilindro simple, con los parámetros h (grosor) y diámetro (d) | |
− | + | # scripts con GUI | |
− | * | + | # script con gui empotrada en Freecad |
+ | # Script con una GUI diseñada con QTcreator | ||
+ | # Script con la gui empotrada en la pestaña task | ||
+ | # Script con gui en pestaña task. Que se dibuje el cuerpo de la rueda y se puedan establecer los parametros h y d | ||
+ | # Programar la rueda del miniskybot, pero con esos mismos parametros variables | ||
+ | # Incluir 2 coronas: pequeña y grande y permitir que se puedan seleccionar una u otra para la rueda | ||
+ | # ¿Como crear un boton que al pulsarlo se abra el menú y permita meter una rueda definiendo sus parametros? | ||
+ | # ¿Cómo programar un workbench de printbots? que incluya botones con piezas: ruedas, portapilas, chásis... | ||
+ | |||
+ | == Hito 0: Leer == | ||
+ | * [http://www.freecadweb.org/wiki/index.php?title=Python_scripting_tutorial python scripting tutorial] | ||
+ | * [http://www.freecadweb.org/wiki/index.php?title=Power_users_hub Power Users hub] | ||
+ | * [http://www.freecadweb.org/wiki/index.php?title=Macros_recipes Ejemplos de macros] | ||
+ | |||
+ | == Hito 1: programa "hola mundo" == | ||
+ | |||
+ | Visualizar un cilindro genérico (el mismo que cuando se le da al botón de cilindro en el workbench part) | ||
+ | |||
+ | import FreeCAD | ||
+ | import Part | ||
+ | |||
+ | doc = App.ActiveDocument | ||
+ | cyl = doc.addObject("Part::Cylinder","Cylinder") | ||
+ | cyl.Label = "Cylinder" | ||
+ | doc.recompute() | ||
+ | |||
+ | Otro ejemplo, con la función cilindro definida, donde se le pasan los parámetros de altura y diámetro | ||
+ | |||
+ | import FreeCAD | ||
+ | import Part | ||
+ | |||
+ | def cylinder(h = 8, d = 56): | ||
+ | doc = App.ActiveDocument | ||
+ | cyl = doc.addObject("Part::Cylinder","Cylinder") | ||
+ | cyl.Label = "Cylinder" | ||
+ | cyl.Height = h | ||
+ | cyl.Radius = d / 2.0 <br> | ||
+ | cylinder() | ||
+ | cylinder(h = 20, d =10) | ||
+ | App.ActiveDocument.recompute() | ||
+ | |||
+ | He encontrado '''una forma más sencilla''' de hacer el cilindro: | ||
+ | |||
+ | import FreeCAD | ||
+ | import Part | ||
+ | |||
+ | #-- radius = 56, height = 8 | ||
+ | cyl = Part.makeCylinder(56, 8) | ||
+ | Part.show(cyl) | ||
+ | |||
+ | sin embargo el objeto que se crea es un "shape". Las propiedades de altura y radio se pierden. Nos servirá por tanto para construir otros objetos, pero no para hacer algo paramétrico que cambie dinámicamente | ||
+ | |||
+ | == Hito 2: Scripts con GUI en FREECAD == | ||
+ | |||
+ | Ejemplo hola mundo para sacar una ventana emergente | ||
+ | |||
+ | from PyQt4 import QtGui | ||
+ | QtGui.QMessageBox.information(None,"Titulo","Hola Mundo!") | ||
+ | |||
+ | Ventana desde la que especifiar el lado para hacer un cubo | ||
+ | |||
+ | from PyQt4 import QtGui, QtCore | ||
+ | import Part, FreeCAD | ||
+ | from FreeCAD import Base, Vector | ||
+ | |||
+ | class BoxExample(QtGui.QWidget): | ||
+ | def __init__(self): | ||
+ | super(BoxExample, self).__init__() | ||
+ | self.initUI() | ||
+ | |||
+ | def initUI(self): | ||
+ | self.setGeometry(100, 100, 260, 100) | ||
+ | self.setWindowTitle('Mi cubo') | ||
+ | self.lengthLabel = QtGui.QLabel("Lado: ",self) | ||
+ | self.lengthLabel.move(20, 20) | ||
+ | self.length = QtGui.QLineEdit(self) | ||
+ | self.length.move(100, 15) | ||
+ | |||
+ | self.okButton = QtGui.QPushButton("Crear cubo",self) | ||
+ | self.okButton.move(20, 60) | ||
+ | self.show() | ||
+ | |||
+ | QtCore.QObject.connect (self.okButton, QtCore.SIGNAL("pressed()"),self.box) | ||
+ | |||
+ | def box(self): | ||
+ | l = float(self.length.text()) | ||
+ | box = Part.makeBox(l, l, l) | ||
+ | Part.show(box) | ||
+ | |||
+ | |||
+ | d = BoxExample() | ||
+ | |||
+ | == Hito 3: Script con gui empotrada en Freecad == | ||
+ | |||
+ | Widget "hola mundo" empotrado en la gui de Freecad, en la parte de la derecha: | ||
+ | |||
+ | import sys | ||
+ | from PyQt4 import QtGui, QtCore | ||
+ | app = QtGui.qApp | ||
+ | mw = app.activeWindow() | ||
+ | |||
+ | myWidget = QtGui.QDockWidget() | ||
+ | mw.addDockWidget(QtCore.Qt.RightDockWidgetArea,myWidget) | ||
+ | |||
+ | myWidget.setObjectName("my Nice New Widget") | ||
+ | myWidget.resize(QtCore.QSize(300,100)) # sets size of the widget | ||
+ | label = QtGui.QLabel("Hello World", myWidget) # creates a label | ||
+ | label.setGeometry(QtCore.QRect(50,50,200,24)) # sets its size | ||
+ | label.setObjectName("myLabel") # sets its name, so it can be found by name | ||
+ | |||
+ | == Hito 4: Script con GUI diseñada con QTdesigner == | ||
+ | |||
+ | Hay que instalar el paquete: | ||
+ | * qt4-designer | ||
+ | |||
+ | El qt designer se ejecuta así: | ||
+ | |||
+ | $ designer-qt4 | ||
+ | |||
+ | Con el qt designer se gener un fichero con extensión ui que es el que contiene la interfaz. | ||
+ | Esta interfaz se puede pasar a código python mediante el comando: | ||
+ | |||
+ | $ pyuic4 testgui.ui -o python.py | ||
+ | |||
+ | que se instala con: | ||
+ | |||
+ | sudo apt-get install pyqt4-dev-tools | ||
+ | |||
+ | Aquí está integrado en un lateral (aunque por temas de tamaño sale un poco feo, pero funciona) | ||
+ | |||
+ | import sys | ||
+ | from PyQt4 import QtGui, QtCore | ||
+ | |||
+ | app = QtGui.qApp | ||
+ | mw = app.activeWindow() | ||
+ | |||
+ | try: | ||
+ | _fromUtf8 = QtCore.QString.fromUtf8 | ||
+ | except AttributeError: | ||
+ | def _fromUtf8(s): | ||
+ | return s | ||
+ | |||
+ | try: | ||
+ | _encoding = QtGui.QApplication.UnicodeUTF8 | ||
+ | def _translate(context, text, disambig): | ||
+ | return QtGui.QApplication.translate(context, text, disambig, _encoding) | ||
+ | except AttributeError: | ||
+ | def _translate(context, text, disambig): | ||
+ | return QtGui.QApplication.translate(context, text, disambig) | ||
+ | |||
+ | class Ui_Dialog(object): | ||
+ | def setupUi(self, Dialog): | ||
+ | Dialog.setObjectName(_fromUtf8("Dialog")) | ||
+ | Dialog.resize(400, 300) | ||
+ | self.buttonBox = QtGui.QDialogButtonBox(Dialog) | ||
+ | self.buttonBox.setGeometry(QtCore.QRect(30, 240, 341, 32)) | ||
+ | self.buttonBox.setOrientation(QtCore.Qt.Horizontal) | ||
+ | self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) | ||
+ | self.buttonBox.setObjectName(_fromUtf8("buttonBox")) | ||
+ | |||
+ | self.retranslateUi(Dialog) | ||
+ | QtCore.QMetaObject.connectSlotsByName(Dialog) | ||
+ | |||
+ | def retranslateUi(self, Dialog): | ||
+ | Dialog.setWindowTitle(_translate("Dialog", "Dialog", None)) | ||
+ | |||
+ | myNewFreeCADWidget = QtGui.QDockWidget() | ||
+ | myNewFreeCADWidget.ui = Ui_Dialog() # load the Ui script | ||
+ | myNewFreeCADWidget.ui.setupUi(myNewFreeCADWidget) # setup the ui | ||
+ | mw.addDockWidget(QtCore.Qt.RightDockWidgetArea,myNewFreeCADWidget) # add the widget to the main window | ||
+ | |||
+ | '''Pregunta''': ¿Se puede cargar directamente el fichero ui? --> Buscar!!!! | ||
+ | |||
+ | == Hito 5: Script con la gui empotrada en la pestaña task == | ||
+ | |||
+ | Este ejemplo esta tomado el banco de trabajo Ship. La GUI está en el fichero TaskPanel.ui. Se carga dinamicamente | ||
+ | |||
+ | import FreeCAD as App | ||
+ | import FreeCADGui as Gui | ||
+ | from PySide import QtGui, QtCore | ||
+ | |||
+ | class TaskPanel: | ||
+ | def __init__(self): | ||
+ | """Constructor.""" | ||
+ | self.ui = "/home/obijuan/.FreeCAD/TaskPanel.ui" | ||
+ | return | ||
+ | |||
+ | def reject(self): | ||
+ | """Cancel the job""" | ||
+ | return True | ||
+ | |||
+ | def clicked(self, index): | ||
+ | pass | ||
+ | |||
+ | def open(self): | ||
+ | pass | ||
+ | |||
+ | def needsFullSpace(self): | ||
+ | return True | ||
+ | |||
+ | def isAllowedAlterSelection(self): | ||
+ | return False | ||
+ | |||
+ | def isAllowedAlterView(self): | ||
+ | return True | ||
+ | |||
+ | def isAllowedAlterDocument(self): | ||
+ | return False | ||
+ | |||
+ | def helpRequested(self): | ||
+ | pass | ||
+ | |||
+ | def setupUi(self): | ||
+ | """Setup the task panel user interface.""" | ||
+ | mw = self.getMainWindow() | ||
+ | form = mw.findChild(QtGui.QWidget, "TaskPanel") | ||
+ | self.form = form | ||
+ | |||
+ | def getMainWindow(self): | ||
+ | return QtGui.qApp.activeWindow() | ||
+ | |||
+ | def widget(self, class_id, name): | ||
+ | """Return the selected widget. | ||
+ | |||
+ | Keyword arguments: | ||
+ | class_id -- Class identifier | ||
+ | name -- Name of the widget | ||
+ | """ | ||
+ | mw = self.getMainWindow() | ||
+ | form = mw.findChild(QtGui.QWidget, "TaskPanel") | ||
+ | return form.findChild(class_id, name) | ||
+ | |||
+ | def retranslateUi(self): | ||
+ | """Set the user interface locale strings.""" | ||
+ | pass | ||
+ | |||
+ | panel = TaskPanel() | ||
+ | Gui.Control.showDialog(panel) | ||
+ | panel.setupUi() | ||
+ | |||
+ | == Hito 6: Establecer los parametros h y d del cuerpo de la rueda del miniskybot == | ||
+ | |||
+ | == Información de interés == | ||
+ | * [http://freecadbuch.de/doku.php?id=blog:ein_eigenes_fenster_in_der_freecad_oberflaeche http://freecadbuch.de/doku.php?id=blog:ein_eigenes_fenster_in_der_freecad_oberflaeche]: En este enlace hay información interesante. Analizar! | ||
+ | |||
+ | == Log == | ||
+ | * 28/Agosto/2014: Comenzada esta página |
Revisión actual del 03:42 20 ene 2015
Contenido
- 1 Introducción
- 2 Roadmap
- 3 Hito 0: Leer
- 4 Hito 1: programa "hola mundo"
- 5 Hito 2: Scripts con GUI en FREECAD
- 6 Hito 3: Script con gui empotrada en Freecad
- 7 Hito 4: Script con GUI diseñada con QTdesigner
- 8 Hito 5: Script con la gui empotrada en la pestaña task
- 9 Hito 6: Establecer los parametros h y d del cuerpo de la rueda del miniskybot
- 10 Información de interés
- 11 Log
Introducción
Quiero aprender a programar piezas en Freecad, al estilo openscad, para poder hacer piezas paramétricas.
Empezaremos con ruedas paramétricas para printbots
Roadmap
- Hello world: programar un cilindro simple, con los parámetros h (grosor) y diámetro (d)
- scripts con GUI
- script con gui empotrada en Freecad
- Script con una GUI diseñada con QTcreator
- Script con la gui empotrada en la pestaña task
- Script con gui en pestaña task. Que se dibuje el cuerpo de la rueda y se puedan establecer los parametros h y d
- Programar la rueda del miniskybot, pero con esos mismos parametros variables
- Incluir 2 coronas: pequeña y grande y permitir que se puedan seleccionar una u otra para la rueda
- ¿Como crear un boton que al pulsarlo se abra el menú y permita meter una rueda definiendo sus parametros?
- ¿Cómo programar un workbench de printbots? que incluya botones con piezas: ruedas, portapilas, chásis...
Hito 0: Leer
Hito 1: programa "hola mundo"
Visualizar un cilindro genérico (el mismo que cuando se le da al botón de cilindro en el workbench part)
import FreeCAD import Part doc = App.ActiveDocument cyl = doc.addObject("Part::Cylinder","Cylinder") cyl.Label = "Cylinder" doc.recompute()
Otro ejemplo, con la función cilindro definida, donde se le pasan los parámetros de altura y diámetro
import FreeCAD import Part def cylinder(h = 8, d = 56): doc = App.ActiveDocument cyl = doc.addObject("Part::Cylinder","Cylinder") cyl.Label = "Cylinder" cyl.Height = h cyl.Radius = d / 2.0
cylinder() cylinder(h = 20, d =10) App.ActiveDocument.recompute()
He encontrado una forma más sencilla de hacer el cilindro:
import FreeCAD import Part #-- radius = 56, height = 8 cyl = Part.makeCylinder(56, 8) Part.show(cyl)
sin embargo el objeto que se crea es un "shape". Las propiedades de altura y radio se pierden. Nos servirá por tanto para construir otros objetos, pero no para hacer algo paramétrico que cambie dinámicamente
Hito 2: Scripts con GUI en FREECAD
Ejemplo hola mundo para sacar una ventana emergente
from PyQt4 import QtGui QtGui.QMessageBox.information(None,"Titulo","Hola Mundo!")
Ventana desde la que especifiar el lado para hacer un cubo
from PyQt4 import QtGui, QtCore import Part, FreeCAD from FreeCAD import Base, Vector class BoxExample(QtGui.QWidget): def __init__(self): super(BoxExample, self).__init__() self.initUI() def initUI(self): self.setGeometry(100, 100, 260, 100) self.setWindowTitle('Mi cubo') self.lengthLabel = QtGui.QLabel("Lado: ",self) self.lengthLabel.move(20, 20) self.length = QtGui.QLineEdit(self) self.length.move(100, 15) self.okButton = QtGui.QPushButton("Crear cubo",self) self.okButton.move(20, 60) self.show() QtCore.QObject.connect (self.okButton, QtCore.SIGNAL("pressed()"),self.box) def box(self): l = float(self.length.text()) box = Part.makeBox(l, l, l) Part.show(box) d = BoxExample()
Hito 3: Script con gui empotrada en Freecad
Widget "hola mundo" empotrado en la gui de Freecad, en la parte de la derecha:
import sys from PyQt4 import QtGui, QtCore app = QtGui.qApp mw = app.activeWindow() myWidget = QtGui.QDockWidget() mw.addDockWidget(QtCore.Qt.RightDockWidgetArea,myWidget) myWidget.setObjectName("my Nice New Widget") myWidget.resize(QtCore.QSize(300,100)) # sets size of the widget label = QtGui.QLabel("Hello World", myWidget) # creates a label label.setGeometry(QtCore.QRect(50,50,200,24)) # sets its size label.setObjectName("myLabel") # sets its name, so it can be found by name
Hito 4: Script con GUI diseñada con QTdesigner
Hay que instalar el paquete:
- qt4-designer
El qt designer se ejecuta así:
$ designer-qt4
Con el qt designer se gener un fichero con extensión ui que es el que contiene la interfaz. Esta interfaz se puede pasar a código python mediante el comando:
$ pyuic4 testgui.ui -o python.py
que se instala con:
sudo apt-get install pyqt4-dev-tools
Aquí está integrado en un lateral (aunque por temas de tamaño sale un poco feo, pero funciona)
import sys from PyQt4 import QtGui, QtCore app = QtGui.qApp mw = app.activeWindow() try: _fromUtf8 = QtCore.QString.fromUtf8 except AttributeError: def _fromUtf8(s): return s try: _encoding = QtGui.QApplication.UnicodeUTF8 def _translate(context, text, disambig): return QtGui.QApplication.translate(context, text, disambig, _encoding) except AttributeError: def _translate(context, text, disambig): return QtGui.QApplication.translate(context, text, disambig) class Ui_Dialog(object): def setupUi(self, Dialog): Dialog.setObjectName(_fromUtf8("Dialog")) Dialog.resize(400, 300) self.buttonBox = QtGui.QDialogButtonBox(Dialog) self.buttonBox.setGeometry(QtCore.QRect(30, 240, 341, 32)) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) self.buttonBox.setObjectName(_fromUtf8("buttonBox")) self.retranslateUi(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog) def retranslateUi(self, Dialog): Dialog.setWindowTitle(_translate("Dialog", "Dialog", None)) myNewFreeCADWidget = QtGui.QDockWidget() myNewFreeCADWidget.ui = Ui_Dialog() # load the Ui script myNewFreeCADWidget.ui.setupUi(myNewFreeCADWidget) # setup the ui mw.addDockWidget(QtCore.Qt.RightDockWidgetArea,myNewFreeCADWidget) # add the widget to the main window
Pregunta: ¿Se puede cargar directamente el fichero ui? --> Buscar!!!!
Hito 5: Script con la gui empotrada en la pestaña task
Este ejemplo esta tomado el banco de trabajo Ship. La GUI está en el fichero TaskPanel.ui. Se carga dinamicamente
import FreeCAD as App import FreeCADGui as Gui from PySide import QtGui, QtCore class TaskPanel: def __init__(self): """Constructor.""" self.ui = "/home/obijuan/.FreeCAD/TaskPanel.ui" return def reject(self): """Cancel the job""" return True def clicked(self, index): pass def open(self): pass def needsFullSpace(self): return True def isAllowedAlterSelection(self): return False def isAllowedAlterView(self): return True def isAllowedAlterDocument(self): return False def helpRequested(self): pass def setupUi(self): """Setup the task panel user interface.""" mw = self.getMainWindow() form = mw.findChild(QtGui.QWidget, "TaskPanel") self.form = form def getMainWindow(self): return QtGui.qApp.activeWindow() def widget(self, class_id, name): """Return the selected widget. Keyword arguments: class_id -- Class identifier name -- Name of the widget """ mw = self.getMainWindow() form = mw.findChild(QtGui.QWidget, "TaskPanel") return form.findChild(class_id, name) def retranslateUi(self): """Set the user interface locale strings.""" pass panel = TaskPanel() Gui.Control.showDialog(panel) panel.setupUi()
Hito 6: Establecer los parametros h y d del cuerpo de la rueda del miniskybot
Información de interés
- http://freecadbuch.de/doku.php?id=blog:ein_eigenes_fenster_in_der_freecad_oberflaeche: En este enlace hay información interesante. Analizar!
Log
- 28/Agosto/2014: Comenzada esta página