Dialog creation/sv: Difference between revisions

From FreeCAD Documentation
(Created page with "Category:Python Code/sv")
(Updating to match new version of source page)
 
(12 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<languages/>
<languages/>

{{docnav
{{Docnav
|[[Line drawing function|Line drawing function]]
|[[Interface_creation|Interface creation]]
|[[Licence|Licence]]
|[[License|License]]
}}
}}


{{TOCright}}

== Introduction ==

<div class="mw-translate-fuzzy">
På denna sida kommer vi att visa hur man bygger en simpel Qt Dialog med [http://qt-project.org/doc/qt-4.8/designer-manual.html Qt Designer], Qt's officiella verktyg för att designa gränssnitt, och sedan konvertera den till pythonkod, och sedan använda den inuti FreeCAD. Jag antar i exemplet att du redan vet hur du ska redigera och köra python skript, och att du kan göra enkla saker i ett terminalfönster som att navigera, etc. Du måste förstås också ha pyqt installerat.
På denna sida kommer vi att visa hur man bygger en simpel Qt Dialog med [http://qt-project.org/doc/qt-4.8/designer-manual.html Qt Designer], Qt's officiella verktyg för att designa gränssnitt, och sedan konvertera den till pythonkod, och sedan använda den inuti FreeCAD. Jag antar i exemplet att du redan vet hur du ska redigera och köra python skript, och att du kan göra enkla saker i ett terminalfönster som att navigera, etc. Du måste förstås också ha pyqt installerat.
</div>


In this example, the entire interface is defined in [[Python|Python]]. Although this is possible for small interfaces, for larger interfaces the recommendation is to load the created {{FileName|.ui}} files directly into the program.

[[File:FreeCAD_creating_interfaces.svg|600px]]
{{Caption|Two general methods to create interfaces, by including the interface in the Python file, or by using {{incode|.ui}} files.}}

<span id="Designing_the_dialog"></span>
<div class="mw-translate-fuzzy">
== Designa dialogen ==
== Designa dialogen ==


Att i CAD applikationer designa ett bra användargränssnitt är mycket viktigt. Nästan allt som användaren kommer att göra kommer att vara genom någon typ av gränssnitt: läsa dialogrutor, klicka på knappar, välja mellan ikoner, etc. Så det är mycket viktigt att noga tänka igenom vad du vill göra, hur du vill att användaren ska bete sig, och hur arbetsflödet i din aktion kommer att se ut.
Att i CAD applikationer designa ett bra användargränssnitt är mycket viktigt. Nästan allt som användaren kommer att göra kommer att vara genom någon typ av gränssnitt: läsa dialogrutor, klicka på knappar, välja mellan ikoner, etc. Så det är mycket viktigt att noga tänka igenom vad du vill göra, hur du vill att användaren ska bete sig, och hur arbetsflödet i din aktion kommer att se ut.
</div>

In CAD applications, designing a good UI (User Interface) is very important. About everything the user will do will be through some piece of interface: reading dialog boxes, pressing buttons, choosing between icons, etc. So it is very important to think carefully to what you want to do, how you want the user to behave, and how will be the workflow of your action.


Det finns några koncept man bör känna till när man designar ett gränssnitt:
Det finns några koncept man bör känna till när man designar ett gränssnitt:
Line 41: Line 58:
[[Image:Qtpropeditor.jpg]]
[[Image:Qtpropeditor.jpg]]


<span id="Converting_our_dialog_to_python"></span>
== Konvertera vår dialog till python ==
== Konvertera vår dialog till python ==
Låt oss nu spara vår widget någonstans. Den kommar att sparas som en .ui fil, som vi smidigt kan omvandla till python skript med pyuic. på windows, så är pyuic programmet hoppackat med pyqt (ska verifieras), på linux behöver du troligen installera den separat från din pakethanterare (på debian-baserade system, så är det en del av pyqt4-dev-tools paketet). För att göra konverteringen, så behöver du öppna ett terminalfönster (eller ett kommandoprompt fönster på windows), navigera till där du sparade din .ui file, och skriva:
Låt oss nu spara vår widget någonstans. Den kommar att sparas som en .ui fil, som vi smidigt kan omvandla till python skript med pyuic. på windows, så är pyuic programmet hoppackat med pyqt (ska verifieras), på linux behöver du troligen installera den separat från din pakethanterare (på debian-baserade system, så är det en del av pyqt4-dev-tools paketet). För att göra konverteringen, så behöver du öppna ett terminalfönster (eller ett kommandoprompt fönster på windows), navigera till där du sparade din .ui file, och skriva:
Line 54: Line 72:
{{Code|code=
{{Code|code=
compQt4 myUiFile
compQt4 myUiFile
}}

In macOS, you can retrieve the appropriate version (the same that is used internally in FreeCAD 0.19) of QT and Pyside with these commands (pip required)
{{Code|code=
python3 -m pip install pyqt5
python3 -m pip install pySide2
}}
This will install uic in the folder "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/uic", and Designer in "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/Designer.app".
For convenience you can create a link of uic in /usr/local/bin to be able to call it simply with uic -g python ... instead of typing the whole path of the program, and a link to Designer to retrieve it in the mac's Applications folder with
{{Code|code=
sudo ln -s /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/uic /usr/local/bin
ln -s /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/Designer.app /Applications
}}
}}


Line 245: Line 275:


}}
}}
==Creation of a dialog with buttons==


===Method 1===
==More examples ==
An example of a dialog box complete with its connections.
{{Code|code=
# -*- coding: utf-8 -*-
# Create by flachyjoe


* [[Dialog_creation_with_various_widgets|Dialog creation with various widgets]] with {{incode|QPushButton}}, {{incode|QLineEdit}}, {{incode|QCheckBox}}, {{incode|QRadioButton}}, and others.
from PySide import QtCore, QtGui
* [[Dialog_creation_reading_and_writing_files|Dialog creation reading and writing files]] with {{incode|QFileDialog}}.
* [[Dialog_creation_setting_colors|Dialog creation setting colors]] with {{incode|QColorDialog}}.
* [[Dialog_creation_image_and_animated_GIF|Dialog creation image and animated GIF]] with {{incode|QLabel}} and {{incode|QMovie}}.
* [[PySide_usage_snippets|PySide usage snippets]].
* [[Qt_Example|Qt Example]]


== Relevant links ==
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s


* [[Manual:Creating interface tools]]
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_MainWindow(object):

def __init__(self, MainWindow):
self.window = MainWindow

MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(400, 300)
self.centralWidget = QtGui.QWidget(MainWindow)
self.centralWidget.setObjectName(_fromUtf8("centralWidget"))

self.pushButton = QtGui.QPushButton(self.centralWidget)
self.pushButton.setGeometry(QtCore.QRect(30, 170, 93, 28))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.pushButton.clicked.connect(self.on_pushButton_clicked) #connection pushButton

self.lineEdit = QtGui.QLineEdit(self.centralWidget)
self.lineEdit.setGeometry(QtCore.QRect(30, 40, 211, 22))
self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
self.lineEdit.returnPressed.connect(self.on_lineEdit_clicked) #connection lineEdit

self.checkBox = QtGui.QCheckBox(self.centralWidget)
self.checkBox.setGeometry(QtCore.QRect(30, 90, 81, 20))
self.checkBox.setChecked(True)
self.checkBox.setObjectName(_fromUtf8("checkBoxON"))
self.checkBox.clicked.connect(self.on_checkBox_clicked) #connection checkBox

self.radioButton = QtGui.QRadioButton(self.centralWidget)
self.radioButton.setGeometry(QtCore.QRect(30, 130, 95, 20))
self.radioButton.setObjectName(_fromUtf8("radioButton"))
self.radioButton.clicked.connect(self.on_radioButton_clicked) #connection radioButton

MainWindow.setCentralWidget(self.centralWidget)

self.menuBar = QtGui.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 400, 26))
self.menuBar.setObjectName(_fromUtf8("menuBar"))
MainWindow.setMenuBar(self.menuBar)

self.mainToolBar = QtGui.QToolBar(MainWindow)
self.mainToolBar.setObjectName(_fromUtf8("mainToolBar"))
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)

self.statusBar = QtGui.QStatusBar(MainWindow)
self.statusBar.setObjectName(_fromUtf8("statusBar"))
MainWindow.setStatusBar(self.statusBar)

self.retranslateUi(MainWindow)

def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.pushButton.setText(_translate("MainWindow", "OK", None))
self.lineEdit.setText(_translate("MainWindow", "tyty", None))
self.checkBox.setText(_translate("MainWindow", "CheckBox", None))
self.radioButton.setText(_translate("MainWindow", "RadioButton", None))

def on_checkBox_clicked(self):
if self.checkBox.checkState()==0:
App.Console.PrintMessage(str(self.checkBox.checkState())+" CheckBox KO\r\n")
else:
App.Console.PrintMessage(str(self.checkBox.checkState())+" CheckBox OK\r\n")
# App.Console.PrintMessage(str(self.lineEdit.setText("tititi"))+" LineEdit\r\n") #write text to the lineEdit window !
# str(self.lineEdit.setText("tititi")) #écrit le texte dans la fenêtre lineEdit
App.Console.PrintMessage(str(self.lineEdit.displayText())+" LineEdit\r\n")

def on_radioButton_clicked(self):
if self.radioButton.isChecked():
App.Console.PrintMessage(str(self.radioButton.isChecked())+" Radio OK\r\n")
else:
App.Console.PrintMessage(str(self.radioButton.isChecked())+" Radio KO\r\n")

def on_lineEdit_clicked(self):
# if self.lineEdit.textChanged():
App.Console.PrintMessage(str(self.lineEdit.displayText())+" LineEdit Display\r\n")

def on_pushButton_clicked(self):
App.Console.PrintMessage("Terminé\r\n")
self.window.hide()

MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow(MainWindow)
MainWindow.show()
}}
Here the same window but with an icon on each button.

Download associated icons (click right "Copy the image below ...)"

[[File:Icone01.png]] [[File:Icone02.png]] [[File:Icone03.png]]

{{Code|code=
# -*- coding: utf-8 -*-

from PySide import QtCore, QtGui

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_MainWindow(object):

def __init__(self, MainWindow):
self.window = MainWindow
path = FreeCAD.ConfigGet("UserAppData")
# path = FreeCAD.ConfigGet("AppHomePath")

MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(400, 300)
self.centralWidget = QtGui.QWidget(MainWindow)
self.centralWidget.setObjectName(_fromUtf8("centralWidget"))

self.pushButton = QtGui.QPushButton(self.centralWidget)
self.pushButton.setGeometry(QtCore.QRect(30, 170, 93, 28))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.pushButton.clicked.connect(self.on_pushButton_clicked) #connection pushButton

self.lineEdit = QtGui.QLineEdit(self.centralWidget)
self.lineEdit.setGeometry(QtCore.QRect(30, 40, 211, 22))
self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
self.lineEdit.returnPressed.connect(self.on_lineEdit_clicked) #connection lineEdit

self.checkBox = QtGui.QCheckBox(self.centralWidget)
self.checkBox.setGeometry(QtCore.QRect(30, 90, 100, 20))
self.checkBox.setChecked(True)
self.checkBox.setObjectName(_fromUtf8("checkBoxON"))
self.checkBox.clicked.connect(self.on_checkBox_clicked) #connection checkBox

self.radioButton = QtGui.QRadioButton(self.centralWidget)
self.radioButton.setGeometry(QtCore.QRect(30, 130, 95, 20))
self.radioButton.setObjectName(_fromUtf8("radioButton"))
self.radioButton.clicked.connect(self.on_radioButton_clicked) #connection radioButton

MainWindow.setCentralWidget(self.centralWidget)

self.menuBar = QtGui.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 400, 26))
self.menuBar.setObjectName(_fromUtf8("menuBar"))
MainWindow.setMenuBar(self.menuBar)

self.mainToolBar = QtGui.QToolBar(MainWindow)
self.mainToolBar.setObjectName(_fromUtf8("mainToolBar"))
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)

self.statusBar = QtGui.QStatusBar(MainWindow)
self.statusBar.setObjectName(_fromUtf8("statusBar"))
MainWindow.setStatusBar(self.statusBar)

self.retranslateUi(MainWindow)

# Affiche un icone sur le bouton PushButton
# self.image_01 = "C:\Program Files\FreeCAD0.13\Icone01.png" # adapt the icon name
self.image_01 = path+"Icone01.png" # adapt the name of the icon
icon01 = QtGui.QIcon()
icon01.addPixmap(QtGui.QPixmap(self.image_01),QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.pushButton.setIcon(icon01)
self.pushButton.setLayoutDirection(QtCore.Qt.RightToLeft) # This command reverses the direction of the button

# Affiche un icone sur le bouton RadioButton
# self.image_02 = "C:\Program Files\FreeCAD0.13\Icone02.png" # adapt the name of the icon
self.image_02 = path+"Icone02.png" # adapter le nom de l'icone
icon02 = QtGui.QIcon()
icon02.addPixmap(QtGui.QPixmap(self.image_02),QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.radioButton.setIcon(icon02)
# self.radioButton.setLayoutDirection(QtCore.Qt.RightToLeft) # This command reverses the direction of the button

# Affiche un icone sur le bouton CheckBox
# self.image_03 = "C:\Program Files\FreeCAD0.13\Icone03.png" # the name of the icon
self.image_03 = path+"Icone03.png" # adapter le nom de l'icone
icon03 = QtGui.QIcon()
icon03.addPixmap(QtGui.QPixmap(self.image_03),QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.checkBox.setIcon(icon03)
# self.checkBox.setLayoutDirection(QtCore.Qt.RightToLeft) # This command reverses the direction of the button


def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "FreeCAD", None))
self.pushButton.setText(_translate("MainWindow", "OK", None))
self.lineEdit.setText(_translate("MainWindow", "tyty", None))
self.checkBox.setText(_translate("MainWindow", "CheckBox", None))
self.radioButton.setText(_translate("MainWindow", "RadioButton", None))

def on_checkBox_clicked(self):
if self.checkBox.checkState()==0:
App.Console.PrintMessage(str(self.checkBox.checkState())+" CheckBox KO\r\n")
else:
App.Console.PrintMessage(str(self.checkBox.checkState())+" CheckBox OK\r\n")
# App.Console.PrintMessage(str(self.lineEdit.setText("tititi"))+" LineEdit\r\n") # write text to the lineEdit window !
# str(self.lineEdit.setText("tititi")) #écrit le texte dans la fenêtre lineEdit
App.Console.PrintMessage(str(self.lineEdit.displayText())+" LineEdit\r\n")

def on_radioButton_clicked(self):
if self.radioButton.isChecked():
App.Console.PrintMessage(str(self.radioButton.isChecked())+" Radio OK\r\n")
else:
App.Console.PrintMessage(str(self.radioButton.isChecked())+" Radio KO\r\n")

def on_lineEdit_clicked(self):
# if self.lineEdit.textChanged():
App.Console.PrintMessage(str(self.lineEdit.displayText())+" LineEdit Display\r\n")

def on_pushButton_clicked(self):
App.Console.PrintMessage("Terminé\r\n")
self.window.hide()

MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow(MainWindow)
MainWindow.show()
}}
Here the code to display the icon on the '''pushButton''', change the name for another button, ('''radioButton, checkBox''') and the path to the icon.
{{Code|code=
# Affiche un icône sur le bouton PushButton
# self.image_01 = "C:\Program Files\FreeCAD0.13\icone01.png" # the name of the icon
self.image_01 = path+"icone01.png" # the name of the icon
icon01 = QtGui.QIcon()
icon01.addPixmap(QtGui.QPixmap(self.image_01),QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.pushButton.setIcon(icon01)
self.pushButton.setLayoutDirection(QtCore.Qt.RightToLeft) # This command reverses the direction of the button
}}
The command
'''UserAppData''' gives the user path
'''AppHomePath''' gives the installation path of FreeCAD
{{Code|code=
# path = FreeCAD.ConfigGet("UserAppData")
path = FreeCAD.ConfigGet("AppHomePath")
}}
This command reverses the horizontal button, right to left.
{{Code|code=
self.pushButton.setLayoutDirection(QtCore.Qt.RightToLeft) # This command reverses the direction of the button
}}

===Method 2===
Another method to display a window, here by creating a file '''QtForm.py''' which contains the header program (module called with '''import QtForm'''), and a second module that contains the code window all these accessories, and your code (the calling module).

This method requires two separate files, but allows to shorten your program using the file ' ' QtForm.py ' ' import. Then distribute the two files together, they are inseparable.

The file '''QtForm.py'''
{{Code|code=

# -*- coding: utf-8 -*-
# Create by flachyjoe
from PySide import QtCore, QtGui

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 Form(object):
def __init__(self, title, width, height):
self.window = QtGui.QMainWindow()
self.title=title
self.window.setObjectName(_fromUtf8(title))
self.window.setWindowTitle(_translate(self.title, self.title, None))
self.window.resize(width, height)

def show(self):
self.createUI()
self.retranslateUI()
self.window.show()
def setText(self, control, text):
control.setText(_translate(self.title, text, None))
}}
The calling file that contains the window and your code.

The file my_file.py

The connections are to do, a good exercise.
{{Code|code=

# -*- coding: utf-8 -*-
# Create by flachyjoe
from PySide import QtCore, QtGui
import QtForm

class myForm(QtForm.Form):
def createUI(self):
self.centralWidget = QtGui.QWidget(self.window)
self.window.setCentralWidget(self.centralWidget)
self.pushButton = QtGui.QPushButton(self.centralWidget)
self.pushButton.setGeometry(QtCore.QRect(30, 170, 93, 28))
self.pushButton.clicked.connect(self.on_pushButton_clicked)
self.lineEdit = QtGui.QLineEdit(self.centralWidget)
self.lineEdit.setGeometry(QtCore.QRect(30, 40, 211, 22))
self.checkBox = QtGui.QCheckBox(self.centralWidget)
self.checkBox.setGeometry(QtCore.QRect(30, 90, 81, 20))
self.checkBox.setChecked(True)
self.radioButton = QtGui.QRadioButton(self.centralWidget)
self.radioButton.setGeometry(QtCore.QRect(30, 130, 95, 20))
def retranslateUI(self):
self.setText(self.pushButton, "Fermer")
self.setText(self.lineEdit, "essais de texte")
self.setText(self.checkBox, "CheckBox")
self.setText(self.radioButton, "RadioButton")
def on_pushButton_clicked(self):
self.window.hide()

myWindow=myForm("Fenetre de test",400,300)
myWindow.show()
}}

'''Other example'''
<center>
<gallery widths="400" heights="200">
Image:Qt_Example_00.png|Qt example 1
Image:Qt_Example_01.png|Qt example details
</gallery>
</center>
{{clear}}

Are treated :

# icon for window
# horizontalSlider
# progressBar horizontal
# verticalSlider
# progressBar vertical
# lineEdit
# lineEdit
# doubleSpinBox
# doubleSpinBox
# doubleSpinBox
# button
# button
# radioButton with icons
# checkBox with icon checked and unchecked
# textEdit
# graphicsView with 2 graphes
The code page and the icons [[Qt_Example|Qt_Example]]

==Icon personalised in ComboView==

Here an example to create an object with properties and icon personalised in ComboView

Download the example icon to the same directory as the macro [[File:FreeCADIco.png|icon Example for the macro|24px]]

Use of an icon for three different use cases: icon_in_file_disk (format .png), icon_XPM_in_macro (format .XPM) and icon_resource_FreeCAD

[[File:Qt_Example_02.png|icon personalised]]
{{clear}}

{{Code|code=
import PySide
import FreeCAD, FreeCADGui, Part
from pivy import coin
from PySide import QtGui ,QtCore
from PySide.QtGui import *
from PySide.QtCore import *
import Draft

global path
param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path in FreeCAD preferences
path = param.GetString("MacroPath","") + "/" # macro path
path = path.replace("\\","/") # convert the "\" to "/"


class IconViewProviderToFile: # Class ViewProvider create Property view of object
def __init__( self, obj, icon):
self.icone = icon
def getIcon(self): # GetIcon
return self.icone
def attach(self, obj): # Property view of object
self.modes = []
self.modes.append("Flat Lines")
self.modes.append("Shaded")
self.modes.append("Wireframe")
self.modes.append("Points")
obj.addDisplayMode( coin.SoGroup(),"Flat Lines" ) # Display Mode
obj.addDisplayMode( coin.SoGroup(),"Shaded" )
obj.addDisplayMode( coin.SoGroup(),"Wireframe" )
obj.addDisplayMode( coin.SoGroup(),"Points" )
return self.modes

def getDisplayModes(self,obj):
return self.modes

#####################################################
########## Example with icon to file # begin ########
#####################################################

object1 = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "Icon_In_File_Disk") # create your object
object1.addProperty("App::PropertyString","Identity", "ExampleTitle0", "Identity of object").Identity = "FCSpring" # Identity of object
object1.addProperty("App::PropertyFloat" ,"Pitch", "ExampleTitle0", "Pitch betwen 2 heads").Pitch = 2.0 # other Property Data
object1.addProperty("App::PropertyBool" ,"View", "ExampleTitle1", "Hello world").View = True # ...
object1.addProperty("App::PropertyColor" ,"LineColor","ExampleTitle2", "Color to choice").LineColor = (0.13,0.15,0.37) # ...
#...other Property Data
#...other Property Data
#
object1.ViewObject.Proxy = IconViewProviderToFile( object1, path + "FreeCADIco.png") # icon download to file
App.ActiveDocument.recompute()
#
#__Detail__:
# FreeCAD.ActiveDocument.addObject( = create now object personalized
# "App::FeaturePython", = object as FeaturePython
# "Icon_In_File_Disk") = internal name of your object
#
#
# "App::PropertyString", = type of Property , availlable : PropertyString, PropertyFloat, PropertyBool, PropertyColor
# "Identity", = name of the feature
# "ExampleTitle0", = title of the "section"
# "Identity of object") = tooltip displayed on mouse
# .Identity = variable (same of name of the feature)
# object1.ViewObject.Proxy = create the view object and gives the icon
#
########## example with icon to file end



#####################################################
########## Example with icon in macro # begin #######
#####################################################

def setIconInMacro(self): # def contener the icon in format .xpm
# File format XPM created by Gimp "https://www.gimp.org/"
# Choice palette Tango
# Create your masterwork ...
# For export the image in XPM format
# Menu File > Export as > .xpm
# (For convert image true color in Tango color palette :
# Menu Image > Mode > Indexed ... > Use custom palette > Tango Icon Theme > Convert)
return """
/* XPM */
static char * XPM[] = {
"22 24 5 1",
" c None",
". c #CE5C00",
"+ c #EDD400",
"@ c #F57900",
"# c #8F5902",
" ",
" ",
" .... ",
" ..@@@@.. ",
" . ...@...... ",
" .+++++++++... ",
" . ....++... ",
" .@..@@@@@@.+++++.. ",
" .@@@@@..# ++++ .. ",
" . ++++ .@.. ",
" .++++++++ .@@@.+. ",
" . ..@@@@@. ++. ",
" ..@@@@@@@@@. +++ . ",
" ....@...# +++++ @.. ",
" . ++++++++ .@. . ",
" .++++++++ .@@@@ . ",
" . #....@@@@. ++. ",
" .@@@@@@@@@.. +++ . ",
" ........ +++++... ",
" ... ..+++++ ..@.. ",
" ...... .@@@ +. ",
" ......++. ",
" ... ",
" "};
"""

object2 = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "Icon_XPM_In_Macro") #
object2.addProperty("App::PropertyString","Identity","ExampleTitle","Identity of object").Identity = "FCSpring"
#...other Property Data
#...other Property Data
#
object2.ViewObject.Proxy = IconViewProviderToFile( object2, setIconInMacro("")) # icon in macro (.XPM)
App.ActiveDocument.recompute()
########## example with icon in macro end



####################################################################
########## Example with icon to FreeCAD ressource # begin ##########
####################################################################

object3 = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "Icon_Ressource_FreeCAD") #
object3.addProperty("App::PropertyString","Identity","ExampleTitle","Identity of object").Identity = "FCSpring"
#...other Property Data
#...other Property Data
#
object3.ViewObject.Proxy = IconViewProviderToFile( object3, ":/icons/Draft_Draft.svg") # icon to FreeCAD ressource
App.ActiveDocument.recompute()
########## example with icon to FreeCAD ressource end

}}

Complete example creating a cube and its icon

{{Code|code=
#https://forum.freecadweb.org/viewtopic.php?t=10255#p83319
import FreeCAD, Part, math
from FreeCAD import Base
from PySide import QtGui

global path
param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")# macro path in FreeCAD preferences
path = param.GetString("MacroPath","") + "/" # macro path
path = path.replace("\\","/") # convert the "\" to "/"

def setIconInMacro(self):
return """
/* XPM */
static char * xpm[] = {
"22 22 12 1",
" c None",
". c #A40000",
"+ c #2E3436",
"@ c #CE5C00",
"# c #F57900",
"$ c #FCAF3E",
"% c #5C3566",
"& c #204A87",
"* c #555753",
"= c #3465A4",
"- c #4E9A06",
"; c #729FCF",
" ",
" ",
" ",
" .. .. ",
" +@#+++.$$ ",
" +.#+%..$$ ",
" &*$ &*#* ",
" & =&= = ",
" ++& +.== %= ",
" ++$@ ..$ %= & ",
" ..-&%.#$$ &## +=$ ",
" .# ..$ ..#%%.#$$ ",
" ; =+=## %-$# ",
" &= ;& %= ",
" ;+ &=; %= ",
" ++$- +*$- ",
" .#&&+.@$$ ",
" ..$# ..$# ",
" .. .. ",
" ",
" ",
" "};
"""

class PartFeature:
def __init__(self, obj):
obj.Proxy = self

class Box(PartFeature):
def __init__(self, obj):
PartFeature.__init__(self, obj)
obj.addProperty("App::PropertyLength", "Length", "Box", "Length of the box").Length = 1.0
obj.addProperty("App::PropertyLength", "Width", "Box", "Width of the box" ).Width = 1.0
obj.addProperty("App::PropertyLength", "Height", "Box", "Height of the box").Height = 1.0

def onChanged(self, fp, prop):
try:
if prop == "Length" or prop == "Width" or prop == "Height":
fp.Shape = Part.makeBox(fp.Length,fp.Width,fp.Height)
except:
pass

def execute(self, fp):
fp.Shape = Part.makeBox(fp.Length,fp.Width,fp.Height)

class ViewProviderBox:
def __init__(self, obj, icon):
obj.Proxy = self
self.icone = icon
def getIcon(self):
return self.icone

def attach(self, obj):
return

def setupContextMenu(self, obj, menu):
action = menu.addAction("Set default height")
action.triggered.connect(lambda f=self.setDefaultHeight, arg=obj:f(arg))

action = menu.addAction("Hello World")
action.triggered.connect(self.showHelloWorld)

def setDefaultHeight(self, view):
view.Object.Height = 15.0

def showHelloWorld(self):
QtGui.QMessageBox.information(None, "Hi there", "Hello World")

def makeBox():
FreeCAD.newDocument()
a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Box")
Box(a)
# ViewProviderBox(a.ViewObject, path + "FreeCADIco.png") # icon download to file
# ViewProviderBox(a.ViewObject, ":/icons/Draft_Draft.svg") # icon to FreeCAD ressource
ViewProviderBox(a.ViewObject, setIconInMacro("")) # icon in macro (.XPM)
App.ActiveDocument.recompute()

makeBox()


}}

==Use QFileDialog for writing to a file==
Complete code:
{{Code|code=
# -*- coding: utf-8 -*-
import PySide
from PySide import QtGui ,QtCore
from PySide.QtGui import *
from PySide.QtCore import *
path = FreeCAD.ConfigGet("UserAppData")

try:
SaveName = QFileDialog.getSaveFileName(None,QString.fromLocal8Bit("Save a file txt"),path, "*.txt") # PyQt4
# "here the text displayed on windows" "here the filter (extension)"
except Exception:
SaveName, Filter = PySide.QtGui.QFileDialog.getSaveFileName(None, "Save a file txt", path, "*.txt") # PySide
# "here the text displayed on windows" "here the filter (extension)"
if SaveName == "": # if the name file are not selected then Abord process
App.Console.PrintMessage("Process aborted"+"\n")
else: # if the name file are selected or created then
App.Console.PrintMessage("Registration of "+SaveName+"\n") # text displayed to Report view (Menu > View > Report view checked)
try: # detect error ...
file = open(SaveName, 'w') # open the file selected to write (w)
try: # if error detected to write ...
# here your code
print("here your code")
file.write(str(1)+"\n") # write the number convert in text with (str())
file.write("FreeCAD the best") # write the the text with (" ")
except Exception: # if error detected to write
App.Console.PrintError("Error write file "+"\n") # detect error ... display the text in red (PrintError)
finally: # if error detected to write ... or not the file is closed
file.close() # if error detected to write ... or not the file is closed
except Exception:
App.Console.PrintError("Error Open file "+SaveName+"\n") # detect error ... display the text in red (PrintError)

}}

==Use QFileDialog to read a file==
Complete code:
{{Code|code=
# -*- coding: utf-8 -*-
import PySide
from PySide import QtGui ,QtCore
from PySide.QtGui import *
from PySide.QtCore import *
path = FreeCAD.ConfigGet("UserAppData")

OpenName = ""
try:
OpenName = QFileDialog.getOpenFileName(None,QString.fromLocal8Bit("Read a file txt"),path, "*.txt") # PyQt4
# "here the text displayed on windows" "here the filter (extension)"
except Exception:
OpenName, Filter = PySide.QtGui.QFileDialog.getOpenFileName(None, "Read a file txt", path, "*.txt") #PySide
# "here the text displayed on windows" "here the filter (extension)"
if OpenName == "": # if the name file are not selected then Abord process
App.Console.PrintMessage("Process aborted"+"\n")
else:
App.Console.PrintMessage("Read "+OpenName+"\n") # text displayed to Report view (Menu > View > Report view checked)
try: # detect error to read file
file = open(OpenName, "r") # open the file selected to read (r) # (rb is binary)
try: # detect error ...
# here your code
print("here your code")
op = OpenName.split("/") # decode the path
op2 = op[-1].split(".") # decode the file name
nomF = op2[0] # the file name are isolated

App.Console.PrintMessage(str(nomF)+"\n") # the file name are displayed

for ligne in file: # read the file
X = ligne.rstrip('\n\r') #.split() # decode the line
print(X) # print the line in report view other method
# (Menu > Edit > preferences... > Output window > Redirect internal Python output (and errors) to report view checked)
except Exception: # if error detected to read
App.Console.PrintError("Error read file "+"\n") # detect error ... display the text in red (PrintError)
finally: # if error detected to read ... or not error the file is closed
file.close() # if error detected to read ... or not error the file is closed
except Exception: # if one error detected to read file
App.Console.PrintError("Error in Open the file "+OpenName+"\n") # if one error detected ... display the text in red (PrintError)

}}

==Use QColorDialog to get the color==
Complete code:
{{Code|code=
# -*- coding: utf-8 -*-
# https://deptinfo-ensip.univ-poitiers.fr/ENS/pyside-docs/PySide/QtGui/QColor.html
import PySide
from PySide import QtGui ,QtCore
from PySide.QtGui import *
from PySide.QtCore import *
path = FreeCAD.ConfigGet("UserAppData")

couleur = QtGui.QColorDialog.getColor()
if couleur.isValid():
red = int(str(couleur.name()[1:3]),16) # decode hexadecimal to int()
green = int(str(couleur.name()[3:5]),16) # decode hexadecimal to int()
blue = int(str(couleur.name()[5:7]),16) # decode hexadecimal to int()

print(couleur) #
print("hexadecimal ",couleur.name()) # color format hexadecimal mode 16
print("Red color ",red) # color format decimal
print("Green color ",green) # color format decimal
print("Blue color ",blue) # color format decimal

}}
==Use QColorDialog and create your palette colors (Standard and Customize)==

This example modify the Standard color and the Customize color with the Tango FreeCAD guide.

The complete code


{{Code|code=
# -*- coding: utf-8 -*-
# https://deptinfo-ensip.univ-poitiers.fr/ENS/pyside-docs/PySide/QtGui/QColor.html
import PySide
from PySide import QtGui ,QtCore
from PySide.QtGui import *
from PySide.QtCore import *

###############################################
## Window colors organisation ##
## __________________________ ##
## StandardColor: ##
## ##
## Colonnes: ##
## 1: 2: 3: 4: 5: 6: 7: 8: ##
## _______________________________ ##
## Line 1: 0 6 12 18 24 30 36 42 ##
## Line 2: 1 7 13 19 25 31 37 43 ##
## Line 3: 2 8 14 20 26 32 38 44 ##
## Line 4: 3 9 15 21 27 33 39 45 ##
## Line 5: 4 10 16 22 28 34 40 46 ##
## Line 6: 5 11 17 23 29 35 41 47 ##
## ##
## CustomColor: ##
## ##
## Colonnes: ##
## 1: 2: 3: 4: 5: 6: 7: 8: ##
## _______________________________ ##
## Line 1: 0 2 4 6 8 10 12 14 ##
## Line 2: 1 3 5 7 9 11 13 15 ##
## ##
###############################################

color_Dialog = QtGui.QColorDialog()
# FreeCAD-Tango
# Customize the colors in the standard box (in numeric mode)
#
#### Dialog line 1
color_Dialog.setStandardColor( 0, QtGui.QColor(252, 233, 79 , 0).rgba()) # Butte 1
color_Dialog.setStandardColor( 6, QtGui.QColor(237, 212, 0 , 0).rgba()) # Butte 2
color_Dialog.setStandardColor(12, QtGui.QColor(196, 160, 0 , 0).rgba()) # Butte 3
color_Dialog.setStandardColor(18, QtGui.QColor( 48, 43, 0 , 0).rgba()) # Butte 4

color_Dialog.setStandardColor(24, QtGui.QColor(138, 226, 52 , 0).rgba()) # Chameleo 1
color_Dialog.setStandardColor(30, QtGui.QColor(115, 210, 22 , 0).rgba()) # Chameleo 2
color_Dialog.setStandardColor(36, QtGui.QColor( 78, 154, 6 , 0).rgba()) # Chameleo 3
color_Dialog.setStandardColor(42, QtGui.QColor( 23, 42, 4 , 0).rgba()) # Chameleo 4
#### Dialog line 2
color_Dialog.setStandardColor( 1, QtGui.QColor(252, 175, 62 , 0).rgba()) # Orang 1
color_Dialog.setStandardColor( 7, QtGui.QColor(245, 121, 0 , 0).rgba()) # Orang 2
color_Dialog.setStandardColor(13, QtGui.QColor(206, 92, 0 , 0).rgba()) # Orang 3
color_Dialog.setStandardColor(19, QtGui.QColor( 50, 25, 0 , 0).rgba()) # Orang 4

color_Dialog.setStandardColor(25, QtGui.QColor(114, 159, 207 , 0).rgba()) # Sky Blu 1
color_Dialog.setStandardColor(31, QtGui.QColor( 52, 101, 164 , 0).rgba()) # Sky Blu 2
color_Dialog.setStandardColor(37, QtGui.QColor( 32, 74, 135 , 0).rgba()) # Sky Blu 3
color_Dialog.setStandardColor(43, QtGui.QColor( 11, 21, 33 , 0).rgba()) # Sky Blu 4
#### Dialog line 3
color_Dialog.setStandardColor( 2, QtGui.QColor(173, 127, 168 , 0).rgba()) # Plu 1
color_Dialog.setStandardColor( 8, QtGui.QColor(117, 80, 123 , 0).rgba()) # Plu 2
color_Dialog.setStandardColor(14, QtGui.QColor( 92, 53, 102 , 0).rgba()) # Plu 3
color_Dialog.setStandardColor(20, QtGui.QColor( 23, 16, 24 , 0).rgba()) # Plu 4

color_Dialog.setStandardColor(26, QtGui.QColor(233, 185, 110 , 0).rgba()) # Chocolat 1
color_Dialog.setStandardColor(32, QtGui.QColor(193, 125, 17 , 0).rgba()) # Chocolat 2
color_Dialog.setStandardColor(38, QtGui.QColor(143, 89, 2 , 0).rgba()) # Chocolat 3
color_Dialog.setStandardColor(44, QtGui.QColor( 39, 25, 3 , 0).rgba()) # Chocolat 4
#### Dialog line 4
color_Dialog.setStandardColor( 3, QtGui.QColor(239, 41, 41 , 0).rgba()) # Scarle Re 1
color_Dialog.setStandardColor( 9, QtGui.QColor(204, 0, 0 , 0).rgba()) # Scarle Re 2
color_Dialog.setStandardColor(15, QtGui.QColor(164, 0, 0 , 0).rgba()) # Scarle Re 3
color_Dialog.setStandardColor(21, QtGui.QColor( 40, 0, 0 , 0).rgba()) # Scarle Re 4

color_Dialog.setStandardColor(27, QtGui.QColor( 52, 224, 226 , 0).rgba()) # FreeTea 1
color_Dialog.setStandardColor(33, QtGui.QColor( 22, 208, 210 , 0).rgba()) # FreeTea 2
color_Dialog.setStandardColor(39, QtGui.QColor( 6, 152, 154 , 0).rgba()) # FreeTea 3
color_Dialog.setStandardColor(45, QtGui.QColor( 4, 42, 42 , 0).rgba()) # FreeTea 4
#### Dialog line 5
color_Dialog.setStandardColor( 4, QtGui.QColor(255, 255, 255 , 0).rgba()) # Snow White

color_Dialog.setStandardColor(10, QtGui.QColor(238, 238, 236 , 0).rgba()) # Aluminiu 1
color_Dialog.setStandardColor(16, QtGui.QColor(211, 215, 207 , 0).rgba()) # Aluminiu 2
color_Dialog.setStandardColor(22, QtGui.QColor(186, 189, 182 , 0).rgba()) # Aluminiu 3

color_Dialog.setStandardColor(28, QtGui.QColor(136, 138, 133 , 0).rgba()) # Aluminiu 4
color_Dialog.setStandardColor(34, QtGui.QColor( 85, 87, 83 , 0).rgba()) # Aluminiu 5
color_Dialog.setStandardColor(40, QtGui.QColor( 46, 52, 54 , 0).rgba()) # Aluminiu 6

color_Dialog.setStandardColor(46, QtGui.QColor( 0, 0, 0 , 0).rgba()) # Je Black
#### Dialog line 6
color_Dialog.setStandardColor( 5, QtGui.QColor(255, 255, 255 , 0).rgba()) # Snow White
color_Dialog.setStandardColor(11, QtGui.QColor(255, 0, 0 , 0).rgba()) # Aluminiu 1
color_Dialog.setStandardColor(17, QtGui.QColor( 0, 255, 0 , 0).rgba()) # Aluminiu 2
color_Dialog.setStandardColor(23, QtGui.QColor( 0, 0, 255 , 0).rgba()) # Aluminiu 3

color_Dialog.setStandardColor(29, QtGui.QColor(255, 255, 0 , 0).rgba()) # Aluminiu 4
color_Dialog.setStandardColor(35, QtGui.QColor(255, 0, 255 , 0).rgba()) # Aluminiu 5
color_Dialog.setStandardColor(41, QtGui.QColor( 0, 255, 255 , 0).rgba()) # Aluminiu 6
color_Dialog.setStandardColor(47, QtGui.QColor( 0, 0, 0 , 0).rgba()) # Je Black
color_Dialog.setStandardColor(47, QtGui.QColor( 0, 0, 0 , 0).rgba()) # Je Black

#### Customize the colors to Dialog CustomColor (in hexadecimal converted in numeric mode)
# Use the Yellow tones for tools that create objects.
# Dialog line 1
color_Dialog.setCustomColor(0, QtGui.QColor( int("fc",16),int("e9",16),int("4f",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(2, QtGui.QColor( int("ed",16),int("d4",16),int("00",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(4, QtGui.QColor( int("c4",16),int("a0",16),int("00",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(6, QtGui.QColor( int("30",16),int("2b",16),int("00",16) , 0).rgba()) # hexadecimal converted in int

# Use the Blue tones for tools that modify objects
color_Dialog.setCustomColor(8, QtGui.QColor( int("72",16),int("9f",16),int("cf",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(10,QtGui.QColor( int("34",16),int("65",16),int("a4",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(12,QtGui.QColor( int("20",16),int("4a",16),int("87",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(14,QtGui.QColor( int("0b",16),int("15",16),int("21",16) , 0).rgba()) # hexadecimal converted in int

# Use the Teal tones for view-related tools
# Dialog line 2
color_Dialog.setCustomColor(1, QtGui.QColor( int("34",16),int("e0",16),int("e2",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(3, QtGui.QColor( int("16",16),int("d0",16),int("d2",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(5, QtGui.QColor( int("06",16),int("98",16),int("9a",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(7, QtGui.QColor( int("04",16),int("2a",16),int("2a",16) , 0).rgba()) # hexadecimal converted in int

# Use the Red tones for Constraint related tools
color_Dialog.setCustomColor(9, QtGui.QColor( int("ef",16),int("29",16),int("29",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(11,QtGui.QColor( int("cc",16),int("00",16),int("00",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(13,QtGui.QColor( int("a4",16),int("00",16),int("00",16) , 0).rgba()) # hexadecimal converted in int
color_Dialog.setCustomColor(15,QtGui.QColor( int("28",16),int("00",16),int("00",16) , 0).rgba()) # hexadecimal converted in int

Color = color_Dialog.getColor() # Color.name() extract the color in Hexadecimal mode (#ad7fa8)

if Color.isValid():

print("__.name()___________")
print("hexadecimal ", Color.name()) # color format hexadecimal mode 16
red = int(str( Color.name()[1:3]),16 ) # decode hexadecimal to int()
green = int(str( Color.name()[3:5]),16 ) # decode hexadecimal to int()
blue = int(str( Color.name()[5:7]),16 ) # decode hexadecimal to int()

print("Red color decimal ", str( Color.name()[1:3]), red ) # color format hex to decimal
print("Green color decimal ", str( Color.name()[3:5]), green )# color format hex to decimal
print("Blue color decimal ", str( Color.name()[5:7]), blue ) # color format hex to decimal

print("__.red()____________")
print("Red color decimal ", Color.red() ) # extract the color RGBa with Qt (0 to 255)
print("Green color decimal ", Color.green() ) # extract the color RGBa with Qt (0 to 255)
print("Blue color decimal ", Color.blue() ) # extract the color RGBa with Qt (0 to 255)
print("Alpha decimal ", Color.alpha() ) # extract the color RGBa with Qt (0 to 255)

print("__.redF()___________")
print("Red color float ", Color.redF() ) # extract the color RGBa with Qt (0.0 to 1.0) as FreeCAD
print("Green color float ", Color.greenF() ) # extract the color RGBa with Qt (0.0 to 1.0) as FreeCAD
print("Blue color float ", Color.blueF() ) # extract the color RGBa with Qt (0.0 to 1.0) as FreeCAD
print("Alpha float ", Color.alphaF() ) # extract the color RGBa with Qt (0.0 to 1.0) as FreeCAD
print("__enjoy_____________")

else:
Color = ""

}}


==Display Image with QLabel and Gif animated with QMovie==

{{Code|code=
import PySide
from PySide import QtGui ,QtCore
from PySide.QtGui import QPixmap, QMovie, QLabel
from PySide.QtCore import *
class MyLabelPatience():
label = QtGui.QLabel()
label.setText("<img src=" + path_Name_Image + "><b><center>Wait please</center> \n\n<center>i search the fonts !\n\n</center></b>")
# center screen
ecran = FreeCADGui.getMainWindow().frameGeometry()
xF = 250; yF = 120
xW = (ecran.width()/2) - (xF/2)
yW = (ecran.height()/2)- (yF/2)
label.setGeometry(xW, yW, xF, yF)
####
label.setStyleSheet("QLabel {background-color : #F0C300;font: 12pt; }");
label.setWindowFlags(Qt.WindowFlags(Qt.FramelessWindowHint)) # pas de bords (not border)
### un-comment for use ###############
movie = QtGui.QMovie(path_Name_Image) # anime le fichier Gif anime (decommenter)
label.setMovie(movie)
movie.start()
##################

patience = MyLabelPatience().label
patience.show() #show the image
#patience.close() #close the Qlabel
#MyLabelPatience().movie.start() #start the animation (after patience.show())
#MyLabelPatience().movie.stop() #stop animation

}}

* Example QLabel with image and text

{{clear}}
[[File:Qlabel Image00.png|left|Example QLabel with image]]
{{clear}}

* Example QLabel with image animated Gif

{{clear}}
[[File:Qlabel Image Animee00.gif|left|Example animated Gif]]
{{clear}}
==Some useful commands==

{{Code|code=
# Here the code to display the icon on the '''pushButton''',
# change the name to another button, ('''radioButton, checkBox''') as well as the path to the icon,

# Displays an icon on the button PushButton
# self.image_01 = "C:\Program Files\FreeCAD0.13\icone01.png" # he name of the icon
self.image_01 = path+"icone01.png" # the name of the icon
icon01 = QtGui.QIcon()
icon01.addPixmap(QtGui.QPixmap(self.image_01),QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.pushButton.setIcon(icon01)
self.pushButton.setLayoutDirection(QtCore.Qt.RightToLeft) # This command reverses the direction of the button


# path = FreeCAD.ConfigGet("UserAppData") # gives the user path
path = FreeCAD.ConfigGet("AppHomePath") # gives the installation path of FreeCAD

# This command reverses the horizontal button, right to left
self.pushButton.setLayoutDirection(QtCore.Qt.RightToLeft) # This command reverses the horizontal button

# Displays an info button
self.pushButton.setToolTip(_translate("MainWindow", "Quitter la fonction", None)) # Displays an info button

# This function gives a color button
self.pushButton.setStyleSheet("background-color: red") # This function gives a color button

# This function gives a color to the text of the button
self.pushButton.setStyleSheet("color : #ff0000") # This function gives a color to the text of the button

# combinaison des deux, bouton et texte
self.pushButton.setStyleSheet("color : #ff0000; background-color : #0000ff;" ) # combination of the two, button, and text

# replace the icon in the main window
MainWindow.setWindowIcon(QtGui.QIcon('C:\Program Files\FreeCAD0.13\View-C3P.png'))

# connects a lineEdit on execute
self.lineEdit.returnPressed.connect(self.execute) # connects a lineEdit on "def execute" after validation on enter
# self.lineEdit.textChanged.connect(self.execute) # connects a lineEdit on "def execute" with each keystroke on the keyboard

# display text in a lineEdit
self.lineEdit.setText(str(val_X)) # Displays the value in the lineEdit (convert to string)

# extract the string contained in a lineEdit
val_X = self.lineEdit.text() # extract the (string) string contained in lineEdit
val_X = float(val_X0) # converted the string to an floating
val_X = int(val_X0) # convert the string to an integer

# This code allows you to change the font and its attributes
font = QtGui.QFont()
font.setFamily("Times New Roman")
font.setPointSize(10)
font.setWeight(10)
font.setBold(True) # same result with tags "<b>your text</b>" (in quotes)
self.label_6.setFont(font)
self.label_6.setObjectName("label_6")
self.label_6.setStyleSheet("color : #ff0000") # This function gives a color to the text
self.label_6.setText(_translate("MainWindow", "Select a view", None))
}}

By using the characters with accents, where you get the error :

<FONT COLOR="#FF0000">'''UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-2: invalid data'''</FONT>

Several solutions are possible.
{{Code|code=
# conversion from a lineEdit
App.activeDocument().CopyRight.Text = str(unicode(self.lineEdit_20.text() , 'ISO-8859-1').encode('UTF-8'))
DESIGNED_BY = unicode(self.lineEdit_01.text(), 'ISO-8859-1').encode('UTF-8')
}}
or with the procedure
{{Code|code=
def utf8(unio):
return unicode(unio).encode('UTF8')
}}

<FONT COLOR="#FF0000">'''UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 9: ordinal not in range(128)'''</FONT>

{{Code|code=
# conversion
a = u"Nom de l'élément : "
f.write('''a.encode('iso-8859-1')'''+str(element_)+"\n")
}}
or with the procedure
{{Code|code=
def iso8859(encoder):
return unicode(encoder).encode('iso-8859-1')
}}
or
{{Code|code=
iso8859(unichr(176))
}}
or
{{Code|code=
unichr(ord(176))
}}
or
{{Code|code=
uniteSs = "mm"+iso8859(unichr(178))
print(unicode(uniteSs, 'iso8859'))
}}

== Relevant Links ==
* [[Manual:Creating interface tools]]


<div class="mw-translate-fuzzy">
<div class="mw-translate-fuzzy">
Line 1,316: Line 294:
</div>
</div>


{{Powerdocnavi{{#translation:}}}}
{{Userdocnavi/sv}}
[[Category:Developer Documentation{{#translation:}}]]

[[Category:Poweruser Documentation/sv]]
[[Category:Python Code{{#translation:}}]]

[[Category:Python Code/sv]]

[[Category:Developer]]

[[Category:Developer Documentation]]

{{clear}}

Latest revision as of 16:25, 4 April 2024

Introduction

På denna sida kommer vi att visa hur man bygger en simpel Qt Dialog med Qt Designer, Qt's officiella verktyg för att designa gränssnitt, och sedan konvertera den till pythonkod, och sedan använda den inuti FreeCAD. Jag antar i exemplet att du redan vet hur du ska redigera och köra python skript, och att du kan göra enkla saker i ett terminalfönster som att navigera, etc. Du måste förstås också ha pyqt installerat.

In this example, the entire interface is defined in Python. Although this is possible for small interfaces, for larger interfaces the recommendation is to load the created .ui files directly into the program.

Two general methods to create interfaces, by including the interface in the Python file, or by using .ui files.

Designa dialogen

Att i CAD applikationer designa ett bra användargränssnitt är mycket viktigt. Nästan allt som användaren kommer att göra kommer att vara genom någon typ av gränssnitt: läsa dialogrutor, klicka på knappar, välja mellan ikoner, etc. Så det är mycket viktigt att noga tänka igenom vad du vill göra, hur du vill att användaren ska bete sig, och hur arbetsflödet i din aktion kommer att se ut.

In CAD applications, designing a good UI (User Interface) is very important. About everything the user will do will be through some piece of interface: reading dialog boxes, pressing buttons, choosing between icons, etc. So it is very important to think carefully to what you want to do, how you want the user to behave, and how will be the workflow of your action.

Det finns några koncept man bör känna till när man designar ett gränssnitt:

  • Modal/non-modal dialogs: En modal dialog kommer fram längst fram på skärmen, stoppar aktionen i huvudfönstret, och tvingar användare att svara på dialogen, emedan en icke-modal dialog inte stoppar dig från att arbeta med huvudfönstret. I en del fall så är det första bättre, i andra fall inte.
  • Identifiera vad som krävs och vad som är valbart: Försäkra dig om att användaren vet vad den måste göra. Etikettera allting med en riktig beskrivning, använd verktygstips, etc.
  • Separera kommandon från parametrar: Detta görs vanligtvis med knappar och textinmatningsfält. Användaren vet att om en knapp klickas så produceras en aktion emedan ändring av ett värde inuti ett textfält kommer att ändra en parameter någonstans. Nuförtidan så vet de flesta användarna vad en kanpp är, vad ett inmatningsfält är, etc. Det gränssnitts verktygskit vi använder, Qt, är en av de bästa verktygskiten, och vi behöver inte bry oss om så mycket om hur man klargör saker, eftersom de redan är mycket tydliga.

Så, nu när vi har definierat vad vi ska göra, så är det dags att öppna qt designer. Låt oss designa en mycket enkel dialog, som den här:

Vi kommer sedan använda denna dialog i FreeCAD till att producera ett fint rektangulärt plan. Du kanske tycker att det inte är så användbart att producera fina rektangulära plan, men det kommer vara lätt att senare ändra den till att göra mer komplexa saker. När du öppnar det, så ser Qt Designer ut så här:

Det är mycket enkelt att använda. I den vänstra lådan har du element som kan dras till din widget. på den högra sidan har du egenskapspanelerna som visar alla möjliga redigerbara egenskaper på de valda elementen. Så, börja med att skapa en ny widget. Välj "Dialog without buttons", eftersom vi inte vill ha standard Ok/Cancel knappar. Dra sedan3 labels, på din widget, en för titeln, en för att skriva "Höjd" och en för att skriva "Bredd". Labels är enkla texter som syns på din widget, bara för att informera användaren. Om du väljer en label, så kommer det fram flera egenskaper på den högra sidan som du kan ändra om du vill, som teckensnitt, höjd, etc.

Notera att jag här valde mycket enkla kontroller, men Qt har många fler alternativ, du kan till exempel använda Spinboxes istället för LineEdits, etc... Ta en titt på vad som finns tillgängligt, du kommer säkert att få andra ideer.

Det är ungefär allt vi behöver göra i Qt Designer. En sista sak bara, låt oss döpa om alla våra element till lättare namn, så blir det lättare att identifiera dem i våra skript:

Konvertera vår dialog till python

Låt oss nu spara vår widget någonstans. Den kommar att sparas som en .ui fil, som vi smidigt kan omvandla till python skript med pyuic. på windows, så är pyuic programmet hoppackat med pyqt (ska verifieras), på linux behöver du troligen installera den separat från din pakethanterare (på debian-baserade system, så är det en del av pyqt4-dev-tools paketet). För att göra konverteringen, så behöver du öppna ett terminalfönster (eller ett kommandoprompt fönster på windows), navigera till där du sparade din .ui file, och skriva:

pyuic mywidget.ui > mywidget.py

In Windows pyuic.py is located in "C:\Python27\Lib\site-packages\PyQt4\uic\pyuic.py" For conversion create a batch file called "compQt4.bat:

@"C:\Python27\python" "C:\Python27\Lib\site-packages\PyQt4\uic\pyuic.py" -x %1.ui > %1.py

In the DOS console type without extension

compQt4 myUiFile

In macOS, you can retrieve the appropriate version (the same that is used internally in FreeCAD 0.19) of QT and Pyside with these commands (pip required)

python3 -m pip install pyqt5
python3 -m pip install pySide2

This will install uic in the folder "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/uic", and Designer in "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/Designer.app". For convenience you can create a link of uic in /usr/local/bin to be able to call it simply with uic -g python ... instead of typing the whole path of the program, and a link to Designer to retrieve it in the mac's Applications folder with

sudo ln -s /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/uic /usr/local/bin
ln -s /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/Designer.app /Applications

Into Linux : to do

Since FreeCAD progressively moved away from PyQt after version 0.13, in favour of PySide (Choose your PySide install building PySide), to make the file based on PySide now you have to use:

pyside-uic mywidget.ui -o mywidget.py

In Windows uic.py are located in "C:\Python27\Lib\site-packages\PySide\scripts\uic.py" For create batch file "compSide.bat":

@"C:\Python27\python" "C:\Python27\Lib\site-packages\PySide\scripts\uic.py" %1.ui > %1.py

In the DOS console type without extension

compSide myUiFile

Into Linux : to do

På en del system så kallas programmet pyuic4 istället för pyuic. Detta kommer att konvertera .ui filen till ett python skript. Om vi öppnar mywidget.py filen, så är dess innehåll mycket lätt att förstå:

from PySide import QtCore, QtGui

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(187, 178)
        self.title = QtGui.QLabel(Dialog)
        self.title.setGeometry(QtCore.QRect(10, 10, 271, 16))
        self.title.setObjectName("title")
        self.label_width = QtGui.QLabel(Dialog)
        ...

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

   def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
        self.title.setText(QtGui.QApplication.translate("Dialog", "Plane-O-Matic", None, QtGui.QApplication.UnicodeUTF8))
        ...

Som du ser så har det en mycket enkel struktur: En klass benämnd Ui_Dialog skapas, som sparar din widgets gränssnittselement. Den klassen har två metoder, en fär att ställa in widgeten, och en för att översätta dess innehåll, som är en del av de allmäna Qt mekanismerna för översättning av gränssnittselement. Inställningsmetoden skapar, en och en, widgetarna som vi har definierat dem i Qt Designer, och sätter deras alternativ som vi bestämt tidigare. Sedan blir hela gränssnittet översatt, och slutligen, blir sloten anslutna (vi pratar om det senare).

Vi kan nu skapa en ny widget, och använda denna klass till att skapa dess gränssnitt. Vi kan redan se vår widget i aktion, genom att sätta vår mywidget.py fil på en plats där FreeCAD kommer att hitta den (i FreeCAD's bin katalog, eller i någon av underkatalogerna till Mod ), och i FreeCAD pythontolken skriva:

from PySide import QtGui
import mywidget
d = QtGui.QWidget()
d.ui = mywidget.Ui_Dialog()
d.ui.setupUi(d)
d.show()

Och vår dialog kommer fram! Notera att din pythontolk fortfarande fungerar, vi har en icke-modal dialog. Så, för att stänga den, så kan vi (förutom att klicka på dess stängningsikon, förstås) skriva:

d.hide()

Ordna så att vår dialog gör något

Nu när vi kan visa och gömma vår dialog, så behöver vi bara lägga till en sista bit: Att låta den göra något! Om du leker lite med Qt designer, så kommer du snabbt upptäcka ett helt avsnitt som kallas "signals and slots". I grunden så fungerar det så här: element på dina widgetar (i Qt terminologi, så är dessa element widgetar själva) kan sända signaler. Dessa signaler skiljer sig beroende på widget typ. Till exempel, en knapp kan sända en signal när den är nedtryckt och när den släpps. Dessa signaler kan anslutas till slots, vilka kan vara en speciell funktionalitet i andra widgetar (till exempel en dialog har en "stäng" slot till vilken du kan ansluta signalen från en stäng knapp), eller kan vara anpassade funktioner. PyQt Referensdokumentation listar alla qt widgetar, vad de kan göra, vilka signaler de kan sända , etc...

Vad vi kommer att göra här, är att skapa en ny funktion som kommer att skapa ett plan, baserat på höjd och bredd, och ansluta denna funktion till nedtryckt signalen som sänds av vår "Skapa!" button. Så, låt os börja med att importera våra FreeCAD moduler, genom att sätta följande rader i toppen på skriptet, där vi redan har importerat QtCore och QtGui:

import FreeCAD, Part

Låt oss sedan lägga till en ny funktion till vår Ui_Dialog klass:

def createPlane(self):
    try:
        # first we check if valid numbers have been entered
        w = float(self.width.text())
        h = float(self.height.text())
    except ValueError:
        print("Error! Width and Height values must be valid numbers!")
    else:
        # create a face from 4 points
        p1 = FreeCAD.Vector(0,0,0)
        p2 = FreeCAD.Vector(w,0,0)
        p3 = FreeCAD.Vector(w,h,0)
        p4 = FreeCAD.Vector(0,h,0)
        pointslist = [p1,p2,p3,p4,p1]
        mywire = Part.makePolygon(pointslist)
        myface = Part.Face(mywire)
        Part.show(myface)
        self.hide()

Sedan behöver vi informera Qt att ansluta knappen till funktionen, genom att placera följande rad precis innan QtCore.QMetaObject.connectSlotsByName(Dialog):

QtCore.QObject.connect(self.create,QtCore.SIGNAL("pressed()"),self.createPlane)

Detta ansluter, som du ser, pressed() signalen från vårt skapade objekt ("Skapa!" knappen), till en slot benämnd createPlane, som vi just definierade. Klart! Nu, som en slutlig justering, så kan vi lägga till lite funktion för att skapa dialogen, så kommer den bli lättare att anropa. Utanför Ui_Dialog klassan, så lägger vi till denna kod:

class plane():
   def __init__(self):
       self.d = QtGui.QWidget()
       self.ui = Ui_Dialog()
       self.ui.setupUi(self.d)
       self.d.show()

(Python reminder: the __init__ method of a class is automatically executed whenever a new object is created!)

Det enda vi sedan behöver göra från FreeCAD är:

import mywidget
myDialog = mywidget.plane()

Det var allt. Nu kan du försöka andra saker, som till exempel sätta in din widget i FreeCAD's gränssnitt (se kodbitar sidan), eller göra mycket mer avancerade verktyg, genom att använda andra element på din widget.

Det kompletta skriptet

För referens, så är det kompletta skriptet här:

# Form implementation generated from reading ui file 'mywidget.ui'
#
# Created: Mon Jun  1 19:09:10 2009
#      by: PyQt4 UI code generator 4.4.4
# Modified for PySide 16:02:2015 
# WARNING! All changes made in this file will be lost!

from PySide import QtCore, QtGui
import FreeCAD, Part 

class Ui_Dialog(object):
   def setupUi(self, Dialog):
       Dialog.setObjectName("Dialog")
       Dialog.resize(187, 178)
       self.title = QtGui.QLabel(Dialog)
       self.title.setGeometry(QtCore.QRect(10, 10, 271, 16))
       self.title.setObjectName("title")
       self.label_width = QtGui.QLabel(Dialog)
       self.label_width.setGeometry(QtCore.QRect(10, 50, 57, 16))
       self.label_width.setObjectName("label_width")
       self.label_height = QtGui.QLabel(Dialog)
       self.label_height.setGeometry(QtCore.QRect(10, 90, 57, 16))
       self.label_height.setObjectName("label_height")
       self.width = QtGui.QLineEdit(Dialog)
       self.width.setGeometry(QtCore.QRect(60, 40, 111, 26))
       self.width.setObjectName("width")
       self.height = QtGui.QLineEdit(Dialog)
       self.height.setGeometry(QtCore.QRect(60, 80, 111, 26))
       self.height.setObjectName("height")
       self.create = QtGui.QPushButton(Dialog)
       self.create.setGeometry(QtCore.QRect(50, 140, 83, 26))
       self.create.setObjectName("create")

       self.retranslateUi(Dialog)
       QtCore.QObject.connect(self.create,QtCore.SIGNAL("pressed()"),self.createPlane)
       QtCore.QMetaObject.connectSlotsByName(Dialog)

   def retranslateUi(self, Dialog):
       Dialog.setWindowTitle("Dialog")
       self.title.setText("Plane-O-Matic")
       self.label_width.setText("Width")
       self.label_height.setText("Height")
       self.create.setText("Create!")
       print("tyty")
   def createPlane(self):
       try:
           # first we check if valid numbers have been entered
           w = float(self.width.text())
           h = float(self.height.text())
       except ValueError:
           print("Error! Width and Height values must be valid numbers!")
       else:
           # create a face from 4 points
           p1 = FreeCAD.Vector(0,0,0)
           p2 = FreeCAD.Vector(w,0,0)
           p3 = FreeCAD.Vector(w,h,0)
           p4 = FreeCAD.Vector(0,h,0)
           pointslist = [p1,p2,p3,p4,p1]
           mywire = Part.makePolygon(pointslist)
           myface = Part.Face(mywire)
           Part.show(myface)

class plane():
  def __init__(self):
      self.d = QtGui.QWidget()
      self.ui = Ui_Dialog()
      self.ui.setupUi(self.d)
      self.d.show()

More examples

Relevant links


Line drawing function/sv
Licence/sv