Achsabstand abfragen

Dann wollen wir nun mal etwas spannenderes versuchen. Im nächsten Schritt wollen wir lernen wie man den Achsabstand aus der 3D Konstruktion ausliest und in der Maske anzeigt. Das ganze bereiten wir so vor, dass wir dann ein Out-Skript erstellen können, mit dem wir den Achsabstand dann auch einstellen können.

Dazu müssen wir unsere Demo.ui mittels QT-Designer öffnen und ein paar Steuerelemente einzeichnen. Dazu ziehe ich mir zuerst aus der linken Seite ein Label in meine Maske hinein.

Per Doppelklick auf das Element kann man die Beschriftung ändern.  Dann brauche ich noch eine Spin Box. Das ist ein Objekt, mit dem man recht bequem Zahlen eingeben kann.

Keine Sorge, es darf ruhig etwas schief aussehen. Das Layout lassen wir nachher automatisch erzeugen.

Diese Spin-Box werden wir in unserem Skript benötigen. Wir wollen ja den Achsabstand dort hinein schreiben. Um die Spin-Box zu identifizieren, braucht diese einen Namen. Das steht auf der rechten Seite bei der Eigenschaft objectName. Derweil heißt unsere Spin-Box einfach spinBox. Das ist wenig aussagekräftig, daher benenne ich diese einfach um.

Das Wort spin behalte ich bei. Das ist eine persönliche Sache, weil es mir dadurch leichter fällt in den Skripten zu erkennen, was für ein Typ Objekt ich da gerade am Wickel habe (ein Label, eine Spin Box, ein Text-Feld, eine Combo-Box, …) Daher schreibe ich mir am Anfang immer den Typ in Kurzform vor den eigentlichen Namen. Muss nicht sein, ich finde es aber praktisch.

Wenn wir gerade schon bei den Eigenschaften sind. Im weiteren Verlauf werden wir sicherlich immer wieder auf den Begriff „Properties“ stoßen. Properties sind eben genau die Eigenschaften die wir in dem Eigenschaftenfenster sehen können.

Bei Spin-Boxen können wir als Property einen Wert festlegen und auch einen Mindest- sowie Maximalwert definieren. Genauso kann ich die Schrittweite und einen Suffix vorgeben.

Wenn wir jetzt die Maske ausführen, sehen wir die Maske genau wie angegeben.

Aber es wäre sicherlich besser, wenn wir die Maske ein wenig ausrichten könnten. Auch das geht recht einfach über die sogenannten Layouts.

Und die kann ich auf verschiedene Weise benutzen. Zum einen kann ich ein Layout-Objekt einfach von der linken Leiste in meine Maske ziehen.

 

Layouts funktionieren wie folgt: Alle Objekte in einem Layout werden gemäß dem Layout automatisch angeordnet.

Bei dem vertical Layout werden alle Objekte untereinander angeordnet (so wie das Icon es auch andeutet)

Beim horizontal Layout werden alle Objekte nebeneinander angeordnet.

Beim Grid-Layout werden alle Objekte in einer Tabelle angeordnet

Und schließlich beim Formular-Layout erhält man die Anordnung einer 2-spaltigen Tabelle.

Also ziehe ich meine Objekte einfach mal in das Layout hinein.

Die beiden Objekte sind dann immer nebeneinander angeordnet und bekommen stets die gleiche Länge (wobei sich das über die Properties der jeweiligen Objekte auch anpassen lässt).

Da bei mir die Reihenfolge noch falsch ist, schiebe  ich das Label auf die linke Seite. Da mein (vertical-) Layout selbst aber in keinem Layout steckt, bleibt dieser Bereich starr stehen. Also braucht unser Widget selbst auch ein Layout. Wenn wir nämlich oben rechts in die Hierarchie schauen, können wir kennen, das das Widget kein Layout besitzt.

Dazu benutzen wir jetzt einfach mal die andere Methode, um ein Layout zu definieren und klicken auf die freie Fläche unseres Widgets (alternativ klickst Du das einfach in der Hierarchie an) und wählst dann oben aus der Leiste ein Layout, welches dir zusagt.

Wenn wir nun die Maske im KKP anzeigen lassen, können wir die Größe ändern und die Objekte darin passen sich automatisch an. Allerdings sieht das so noch nicht gut aus. Schöne wäre es, wenn die Objekte oben am Fensterrand stehen würden. Und dafür kann man einen Spacer benutzen. So wie eine Sprungfeder schiebt ein Spacer zwei Elemente auseinander.

Für den Anfang ist das okay. Als Tipp kann ich nur empfehlen viel mit Formular-Layouts zu arbeiten, da diese einem beim Ausrichten noch einmal sehr viel Arbeit erleichtern.

Um das einmal zu zeigen lösche alle Layouts und Spacer wieder heraus und lasse nur das Label und die Spin Box übrig. (Man kann auf ganz oft Strg+Z = rückgängig drücken).

Danach klicke ich einfach auf die freie Fläche in meinem Widget und wähle oben aus der Leiste das Layout Formular-Layout aus. Das Ergebnis sieht dann so aus:

Jetzt wird es aber höchste Zeit die SpinBox mit einem Wert zu befüllen. Dazu arbeiten wir in unserem In-Skript. Dort erstelle ich mir zuerst eine Funktion, damit ich auch in Zukunft weiß, dass diese Funktion dazu dienen soll, den Achsabstand in die Maske einzutragen.

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import sys
sys.path.append(kkp.Get_Systemgeberdir() + „/ui“)
XML_PARAM = „“““““
def initAchsabstand(sc):
    pass
def createXML():
    try: iObjNr = int(XML_PARAM)
    except: iObjNr = 0
    sc = SC.SegmentConfig(iObjNr)
    sc.setWindowTitle(„Hello UI!“)
    initAchsabstand(sc)
    sXml = sc.toXml()
    return sXml
if __name__ == ‚__main__‘:
    sXml = createXML()
    print(sXml)

 

Der Funktion initAchsabstand gebe ich das Objekt sc (SegmentConfig) mit. Dadurch kann ich dann in der Funktion die Systemkonfiguration für die Spin-Box fertig machen.

Um das zu bewerkstellen muss man eine Eigenschaft der Spin-Box verändern. Wenn wir im Qt-Designer nachschauen, heißt unser Objekt spinAchsabstand und die „Property“ heißt value.

sc.setProperty(„spinAchsabstand“ , „value“ , „960“)

Über die Funktion setProperty kann man eine Eigenschaft (Property) für ein bestimmtes Objekt festlegen. Dazu muss man den Objektnamen übergeben, den Namen der Eigenschaft und den neuen Wert der Eigenschaft. Der Wert muss immer als String (Text) übergeben werden!

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import sys
sys.path.append(kkp.Get_Systemgeberdir() + „/ui“)
XML_PARAM = „“““““
def initAchsabstand(sc):
    sc.setProperty(„spinAchsabstand“ , „value“ , „960“)
    pass
def createXML():
    try: iObjNr = int(XML_PARAM)
    except: iObjNr = 0
    sc = SC.SegmentConfig(iObjNr)
    sc.setWindowTitle(„Hello UI!“)
    initAchsabstand(sc)
    sXml = sc.toXml()
    return sXml
if __name__ == ‚__main__‘:
    sXml = createXML()
    print(sXml)

Wenn wir nun die Maske öffnen, wird der Wert nicht bei 850 stehen, sondern bei 960.

Jetzt müssen wir also aus dem KKP den Achsabstand abfragen und diesen Wert in die Spin-Box schreiben. Der Achsabstand ist über einen Parameter gegeben.

Also fragen wir diesen Parameter doch einfach mal ab.

tplAchsabstand = kkp.Get_Parameter(100 , „998.998.9998“) #Achsabstand abfragen
    if len(tplAchsabstand) > 0: #Wenn vorhanden
        dAchsabstand = tplAchsabstand[0] #Wert auslesen
        strAchsabstand = str(dAchsabstand) #Wert in String (Text) konvertieren
        kkp.MsgBox(strAchsabstand , 0) #Zum Testen als MessageBox ausgeben
# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import sys
sys.path.append(kkp.Get_Systemgeberdir() + „/ui“)
XML_PARAM = „“““““
def initAchsabstand(sc):
    tplAchsabstand = kkp.Get_Parameter(100 , „998.998.9998“) #Achsabstand abfragen
    if len(tplAchsabstand) > 0: #Wenn vorhanden
        dAchsabstand = tplAchsabstand[0] #Wert auslesen
        strAchsabstand = str(dAchsabstand) #Wert in String (Text) konvertieren
        kkp.MsgBox(strAchsabstand , 0) #Zum Testen als MessageBox ausgeben
    sc.setProperty(„spinAchsabstand“ , „value“ , „960“)
    pass
def createXML():
    try: iObjNr = int(XML_PARAM)
    except: iObjNr = 0
    sc = SC.SegmentConfig(iObjNr)
    sc.setWindowTitle(„Hello UI!“)
    initAchsabstand(sc)
    sXml = sc.toXml()
    return sXml
if __name__ == ‚__main__‘:
    sXml = createXML()
    print(sXml)

Als Ergebnis bekommen wir eine Messagebox, die den Wert 1000.0 anzeigt. Unsere SpinBox kann keine Zahlen mit einer Nachkommastelle annehmen. Dafür hätten wir die Double-Spin-Box benötigt. Also müssen wird unsere Fließkommazahl dAchsabstand erst in eine ganze Zahl formatieren und dann in einen Text.

dAchsabstand = tplAchsabstand[0] #Wert auslesen
        iAchsabstand = int(dAchsabstand)
        strAchsabstand = str(iAchsabstand) #Wert in String (Text) konvertieren

Man kann das auch etwas kürzer schreiben, indem man einfach einen formatierten String verwendet.

strAchsabstand = „%.0f“ % tplAchsabstand[0]
        sc.setProperty(„spinAchsabstand“ , „value“ , strAchsabstand)

Nun müssen wir diesen Wert in die Spin-Box hineinschreiben.

Ziemlich cool oder?

Und was ist, wenn wir eine Konstruktion haben in der gar kein Achsabstand drin ist? Tja, dann könnten wir doch die Spin-Box einfach unsichtbar schalten oder vielleicht auch einfach deaktivieren.

Dazu müssen wir ebenfalls einfach nur eine Eigenschaft ändern. Die Eigenschaft „aktiviert“ oder „deaktiviert“ können wir bei den Properties sehen.

def initAchsabstand(sc):
    tplAchsabstand = kkp.Get_Parameter(100 , „998.998.9998“) #Achsabstand abfragen
    #if len(tplAchsabstand) > 0: #Wenn vorhanden
    if 1 > 2: #Für den Test
        strAchsabstand = „%.0f“ % tplAchsabstand[0]
        sc.setProperty(„spinAchsabstand“ , „value“ , strAchsabstand)
    else:
        sc.setProperty(„spinAchsabstand“ , „enabled“ , „false“)
    pass

Alternativ kann man das Feld aber ganz unsichtbar schalten. Diese Property wird leider nicht im Designer angezeigt, sie lautet „visible“.

def initAchsabstand(sc):
    tplAchsabstand = kkp.Get_Parameter(100 , „998.998.9998“) #Achsabstand abfragen
    #if len(tplAchsabstand) > 0: #Wenn vorhanden
    if 1 > 2: #Für den Test
        strAchsabstand = „%.0f“ % tplAchsabstand[0]
        sc.setProperty(„spinAchsabstand“ , „value“ , strAchsabstand)
    else:
        sc.setProperty(„spinAchsabstand“ , „visible“ , „false“)
    pass

Tja, und weil dann das Label so ganz alleine dasteht, machen wir das dann auch gleich unsichtbar. Und weil mein Label zur Zeit einfach nur „label“ heißt, benenne ich es vorher noch um in „lblAchsabstand“

def initAchsabstand(sc):
    tplAchsabstand = kkp.Get_Parameter(100 , „998.998.9998“) #Achsabstand abfragen
    #if len(tplAchsabstand) > 0: #Wenn vorhanden
    if 1 > 2: #Für den Test
        strAchsabstand = „%.0f“ % tplAchsabstand[0]
        sc.setProperty(„spinAchsabstand“ , „value“ , strAchsabstand)
    else:
        sc.setProperty(„spinAchsabstand“ , „visible“ , „false“)
        sc.setProperty(„lblAchsabstand“ , „visible“ , „false“)
    pass

Zum Schluss mache ich meine if Bedingung noch wieder richtig. Dann sieht das komplette Skript so aus:

# -*- coding: utf-8 -*-
import kkp
import SegmentConfig as SC
import sys
sys.path.append(kkp.Get_Systemgeberdir() + „/ui“)
XML_PARAM = „“““““
def initAchsabstand(sc):
    tplAchsabstand = kkp.Get_Parameter(100 , „998.998.9998“) #Achsabstand abfragen
    if len(tplAchsabstand) > 0: #Wenn vorhanden
        strAchsabstand = „%.0f“ % tplAchsabstand[0]
        sc.setProperty(„spinAchsabstand“ , „value“ , strAchsabstand)
    else:
        sc.setProperty(„spinAchsabstand“ , „visible“ , „false“)
        sc.setProperty(„lblAchsabstand“ , „visible“ , „false“)
    pass
def createXML():
    try: iObjNr = int(XML_PARAM)
    except: iObjNr = 0
    sc = SC.SegmentConfig(iObjNr)
    sc.setWindowTitle(„Hello UI!“)
    initAchsabstand(sc)
    sXml = sc.toXml()
    return sXml
if __name__ == ‚__main__‘:
    sXml = createXML()
    print(sXml)

Okay, zugegeben, am Anfang ist das viel Arbeit. Aber wenn man das mit ein paar Objekten erst einmal gemacht hat, geht es recht schnell und man kann dem Anwender dadurch das Leben deutlich erleichtern.