Diferencia entre revisiones de «Obijuan:Notas sobre programación en python en Freecad»

De WikiRobotics
Saltar a: navegación, buscar
(Hito 2: Cambiar los parámetros del cilindro desde una GUI en FREECAD)
(Información de interés)
 
(No se muestran 30 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)
+
# Hello world: programar un cilindro simple, con los parámetros h (grosor) y diámetro (d)
* Script que permita cambiar los parámetros desde una GUI en freecad
+
# scripts con GUI
* Programar la rueda del miniskybot, pero con esos mismos parametros variables
+
# script con gui empotrada en Freecad
* Incluir 2 coronas: pequeña y grande y permitir que se puedan seleccionar una u otra para la rueda
+
# Script con una GUI diseñada con QTcreator
* ¿Como crear un boton que al pulsarlo se abra el menú y permita meter una rueda definiendo sus parametros?
+
# Script con la gui empotrada en la pestaña task
* ¿Cómo programar  un workbench de printbots? que incluya botones con piezas: ruedas, portapilas, chásis...
+
# 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 0: Leer ==
 
* [http://www.freecadweb.org/wiki/index.php?title=Python_scripting_tutorial python scripting tutorial]
 
* [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=Power_users_hub Power Users hub]
 +
* [http://www.freecadweb.org/wiki/index.php?title=Macros_recipes Ejemplos de macros]
  
 
== Hito 1: programa "hola mundo" ==
 
== Hito 1: programa "hola mundo" ==
Línea 54: Línea 59:
 
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
 
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: Cambiar los parámetros del cilindro desde una GUI en FREECAD ==
+
== Hito 2: Scripts con GUI en FREECAD ==
 +
 
 +
Ejemplo hola mundo para sacar una ventana emergente
  
 
  from PyQt4 import QtGui
 
  from PyQt4 import QtGui
  QtGui.QMessageBox.information(None,"Apollo program","Houston, we have a problem")
+
  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 ==
 
== Log ==
 
* 28/Agosto/2014: Comenzada esta página
 
* 28/Agosto/2014: Comenzada esta página

Revisión actual del 03:42 20 ene 2015

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

  1. Hello world: programar un cilindro simple, con los parámetros h (grosor) y diámetro (d)
  2. scripts con GUI
  3. script con gui empotrada en Freecad
  4. Script con una GUI diseñada con QTcreator
  5. Script con la gui empotrada en la pestaña task
  6. Script con gui en pestaña task. Que se dibuje el cuerpo de la rueda y se puedan establecer los parametros h y d
  7. Programar la rueda del miniskybot, pero con esos mismos parametros variables
  8. Incluir 2 coronas: pequeña y grande y permitir que se puedan seleccionar una u otra para la rueda
  9. ¿Como crear un boton que al pulsarlo se abra el menú y permita meter una rueda definiendo sus parametros?
  10. ¿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

Log

  • 28/Agosto/2014: Comenzada esta página