Dialog creation/de

Auf dieser Seite zeigen wir, wie man einen einfachen Qt Dialog aufbaut mit Qt-Designer, das offizielle Werkzeug von Qt, um Schnittstellen zu entwerfen. Das Ergebnis wandeln wir dann um in Python-Code, dann verwenden Sie es innerhalb FreeCAD. Ich werde in diesem Beispiel davon ausgehen, dass Sie bereits wissen, wie man Python-Skripte bearbeitet und ausführt, und dass Sie einfache Dinge in einem Terminal-Fenster wie navigieren, etc. ebenfalls können. Ebenso muss natürlich auch pyqt installiert sein.

Das Entwerfen des Dialogs
In CAD-Anwendungen ist es sehr wichtig, eine gute UI (Benutzerschnittstelle)zu entwerfend. Beinahe alles das der Benutzer tun wird, wird über ein Teil der Schnittstelle passieren: das Lesen von Dialog-Kästen, drücken von Knöpfen, die Auswahl zwischen Ikonen, usw. So ist es sehr wichtig, genau darüber nachzudenken, was Sie tun wollen, wie Sie wollen, dass sich der Benutzer verhält, und wie der Arbeitsablauf Ihrer Handlung sein wird.

Ein paar Konzepte sollte man kennen, bei der Gestaltung der Schnittstelle:
 * Dialoge: Ein modaler Dialog erscheint auf Ihrem Schirm, unterbricht die Handlung des Hauptfensters, zwingt den Benutzer auf den Dialog zu antworten, während ein nichtmodaler Dialog Sie nicht hindert, am Hauptfenster weiter zu arbeiten. In einigen Fällen der erste ist besser, in anderen Fällen nicht.
 * Erkennen, was erforderlich ist, und was ist optional: Stellen Sie sicher, dass der Benutzer weiß, was er tun muss. Etikettieren Sie alles mit der richtigen Beschreibung, verwenden Sie tooltips usw.
 * Die Trennung von Befehlen und Parametern: Das wird gewöhnlich mit Knöpfen und Texteingangsfeldern getan. Der Benutzer weiß, dass das Klicken eines Knopfs eine Handlung erzeugen wird, indem er einen Wert innerhalb eines Textfeldes ändern wird, wird irgendwo ein Parameter geändert. Heutzutage, aber wissen Benutzer gewöhnlich gut, was ein Knopf ist, was ein Eingangsfeld usw ist. Das Schnittstellen-Werkzeug das wir verwenden, Qt, ist eines der modernsten Werkzeuge, und wir werden uns nicht viel darum sorgen müssen, Dinge verständlich zu machen, da sie bereits in sich selbst sehr klar sein werden.

Also, jetzt wo wir gut definiert haben, was wir tun werden, ist es Zeit, den Qt Designer zu öffnen. Lassen Sie uns einen sehr einfachen Dialog entwerfen:



Wir werden dann mit diesem Dialog in FreeCAD eine schöne rechteckige Ebene zu erzeugen. Vielleicht finden Sie es nicht sehr nützlich, nette rechteckige Fläche zu produzieren, aber es wird leicht sein sie später zu ändern, um komplexere Dinge zu tun. Wenn Sie es öffnen, sieht Qt Designer wie folgt aus:



Die Bedienung ist recht einfach. Auf der linken Leiste haben Sie Elemente, die Sie auf Ihr Widget ziehen können. Rechts haben Sie Eigenschaften-Tafeln, die alle Arten von änderbaren Eigenschaften von ausgewählten Elementen zeigen. Also, beginnen Sie mit dem erstellen eines neuen Widget. Wählen Sie "Dialog ohne Knöpfe", da wir nicht die Standard-OK/Abbrechen Knöpfe wollen. Jetzt ziehen auf Ihr Widget 3 Label, eins für den Titel, eins mit Namen "Höhe" und eins mit Namen "Breite". Labels sind einfache Texte, die auf Ihrem Widget angezeigt werden, nur um den Benutzer zu informieren. Wenn Sie ein Label auswählen, werden auf der rechten Seite mehrere Eigenschaften erscheinen, die Sie ändern können wenn Sie wollen, wie Schriftart, Größe, usw.

Dann fügen Sie 2 LineEdits ein, dies sind Textfelder, die die Benutzer ausfüllen, eins für die Höhe und eins für die Breite. Auch hier können wir Eigenschaften bearbeiten. Warum nicht, zum Beispiel, einen Standardwert vorgeben? Zum Beispiel 1,00 für jeden. Auf diese Weise, werden beide Werte bereits ausgefüllt sein, wenn der Benutzer den Dialog sieht, und wenn es so stimmt, kann er den Knopf direkt drücken und spart wertvolle Zeit. Dann fügen Sie einen PushButton hinzu, das ist die Schaltfläche die der Benutzer drücken muss, nachdem er die 2 Felder füllte.

Beachten Sie, dass ich sehr einfache Steuerungen gewählt habe, aber Qt noch viele andere Optionen hat, zum Beispiel, könnten Sie Spinboxes statt LineEdits usw. verwenden.. Werfen Sie doch einen Blick darauf, was verfügbar ist, vielleicht kommen Ihnen dabei noch weitere Ideen.

Das ist soweit alles, dass wir im Qt Designer tun müssen. Eine letzte Sache, wir sollten alle unsere Elemente mit einfachen Namen umbenennen, so wird es leichter sein, sie in unseren Skripten zu identifizieren:



Umwandeln unseres Dialogs zu Python
Jetzt werden wir unser Widget irgendwo speichern. Er wird als Ui-Datei gespeichert, die wir einfach mittels pyuic zu einem Python-Skript wandeln werden. Unter Windows ist das pyuic-Programm meistens mit pyqt gebündelt (zu überprüfen), auf linux werden Sie es wahrscheinlich extra mit Ihrem Paketmanager installieren müssen (auf Debian-beruhenden Systemen, ist es ein Teil des pyqt4-dev-tools Pakets). Fürdie Konvertierung, müssen Sie ein Terminal-Fenster (oder ein Fenster der Eingabeaufforderung unter Windows) öffnen, in welchem Sie zu Ihrer ui-Datei navigieren, und dort dann folgendes eingeben:

pyuic mywidget.ui > mywidget.py

Das wird die .ui-Datei in ein Python-Skript umwandeln. Auf einigen Systemen wird das Programm pyuic4 statt pyuic heissen.

pyuic4 mywidget.ui > mywidget.py

Wenn wir die mywidget.py-Datei öffnen, ist er Inhalt sehr leicht zu verstehen:

from PyQt4 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)) ... Wie Sie sehen, hat es eine sehr einfache Struktur: eine Klasse genannt Ui_Dialog wird erstellt, die die Elemente der Benutzeroberfläche unseres Widgets speichert. Diese Klasse hat zwei Methoden, eine für die Einrichtung des Widgets und eine für die Übersetzung ihres Inhalts, dass ist ein Teil des allgemeinen Qt-Mechanismus für die Übersetzung von Interface-Elementen. Das Setup-Verfahren erzeugt einfach eins nach dem anderen, die Widgets, wie wir sie in Qt Designer definiert haben, und setzt ihre Optionen, die wir ebenfalls gewählt haben. Dann wird die ganze Schnittstelle schließlich übersetzt, die SLOTS werden verbunden (wir werden darüber später sprechen).

Wir können jetzt ein neues Widget erstellen und diese Klasse verwenden, um seine Schnittstelle zu schaffen. Wir können bereits unser Widget in Aktion sehen, indem wir unsere mywidget.py Datei an einem Ort speichern, wo FreeCAD es findet(im FreeCAD bin-Verzeichnis, oder in einem der Mod Unterverzeichnisse), und dann im FreeCAD Python-Interpreter, eintippen:

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

Und unser Dialog wird erscheinen! Bemerken Sie, dass unsere Python-Interpreter immer noch arbeitet, wir haben einen nichtmodalen Dialog. Also, um es zu schließen, können wir (abgesehen von einem Klick auf das Schließen-Symbol, natürlich) eingeben: d.hide

Lassen wir unseren Dialog etwas tun
Wo wir jetzt unseren Dialog schon anzeigen und ausblenden können, gibt es nur eines zu tun: Es muss auch etwas ausführen! Wenn Sie ein bisschen mit dem Qt designer spielen, entdecken Sie schnell eine ganze Abteilung genannt "Signale und slots". Grundsätzlich funktioniert es so: Elemente auf Ihren Widgets (in Qt Terminologie, diese Elemente sind selbst Widgets) können Signale senden. Diese Signale unterscheiden sich je nach Widget-Typ. Zum Beispiel kann eine Taste ein Signal senden, wenn sie gedrückt wird, und wenn sie losgelassen wird. Diese Signale können zu Slots, die spezielle Funktionen von anderen Widgets (z. B. einen Dialog, einen "close"-slot auf dem Sie das Signal von einem Schließen-Button verbinden) kann angeschlossen werden, oder können benutzerdefinierte Funktionen sein. Die Seite PyQt Reference Documentation listet alle Qt-Widgets, was sie tun können, welche Signale sie senden können, etc.

Was wir hier tun werden ist, eine neue Funktion erstellen, die eine Ebene erzeugt,beruhend auf Höhe und Breite, und in Verbindung steht diese Funktion mit dem "gedrückt"-Signal, das unser "Create"-Knopf abgibt. Also, wollen wir mit dem Importieren unserer FreeCAD Module beginnen, indem Sie die folgende Zeile am Anfang des Skripts, wo wir bereits QtCore und QtGui importieren, einfügen:

import FreeCAD, Part

Jetzt werden wir eine neue Funktion in unsere Ui_Dialog-Klasse einfügen:

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

Nun müssen wir Qt klarmachen, dass der Knopf mit der Funktion verbunden werden muss. Dazu geben wir die folgende Zeile ein, aber VOR der Zeile QtCore.QMetaObject.connectSlotsByName(Dialog):

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

Dies, wie Sie sehen, verbindet das pressed-Signal unseres create-Objekts(den "Create!" button), zu einem Slot mit Namen createPlane, den wir gerade definiert haben. Das ist alles! Jetzt, als eine Feinschliff, können wir eine kleine Funktion hinzufügen um den Dialog zu erzeugen, dadurch wird der Aufruf erleichtert. Außerhalb der Ui_Dialog Klasse, wollen wir diesen Code hinzufügen:

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

Dann brauchen wir in FreeCAD(Pythonkonsole) nur noch folgendes zu tun:

import mywidget mywidget.plane

Das ist alles, Leute ... Jetzt können Sie alle möglichen Dinge versuchen,, wie zum Beispiel das Einfügen Ihres Widgets in die FreeCAD-Oberfläche (siehe Code snippets-Seite), oder erstellen Sie weitere, fortgeschrittene benutzerdefinierte Tools, durch die Verwendung anderer Elemente auf Ihrem Widget.

Das komplette Script
Dies ist das komplette Script, nur als Referenz:

# # from PyQt4 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(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8)) self.title.setText(QtGui.QApplication.translate("Dialog", "Plane-O-Matic", None, QtGui.QApplication.UnicodeUTF8)) self.label_width.setText(QtGui.QApplication.translate("Dialog", "Width", None, QtGui.QApplication.UnicodeUTF8)) self.label_height.setText(QtGui.QApplication.translate("Dialog", "Height", None, QtGui.QApplication.UnicodeUTF8)) self.create.setText(QtGui.QApplication.translate("Dialog", "Create!", None, QtGui.QApplication.UnicodeUTF8)) 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: d = QtGui.QWidget d.ui = Ui_Dialog d.ui.setupUi(d) d.show
 * 1) -*- coding: utf-8 -*-
 * 1) Form implementation generated from reading ui file 'mywidget.ui'
 * 1) Created: Mon Jun  1 19:09:10 2009
 * 2)      by: PyQt4 UI code generator 4.4.4
 * 1) WARNING! All changes made in this file will be lost!