Obijuan:Notas sobre programación en python en Freecad
Contenido
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
- 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()
Log
- 28/Agosto/2014: Comenzada esta página