Version 17 (modified by 7 years ago) (diff) | ,
---|
SALOME
Namestitev
Za namestitev SALOME-a shranite Windows paket SALOME-8.3.0-WIN64.exe ki se nahaja na spodnji povezavi:
http://www.salome-platform.org/downloads/current-version
Odpakirajte Windows paket SALOME-8.3.0-WIN64.exe kot administrator (desni klik --> Run as Administrator) v C:\Program Files.
Program SALOME se zažene s skriptom run_salome.bat ki se nahaja v C:\Program Files\SALOME-8.3.0-WIN64\WORK.
Struktura programa v programskem jeziku Python
Uporabljali bomo navodila za Salome 8.3. Za programiranje v geometrijskem modulu si poglejte Geometry module Python Interface.
V glavi programa je potrebno inicializirati knjižnico salome, ki nam omogoči preprosto manipulacijo predstavljenega objekta (glava dokumenta):
import salome salome.salome_init()
Nato je potrebno uvoziti python-ov modul GEOM, ki vsebuje funkcije, s katerimi izdelujemo geometrijske modele.
import GEOM from salome.geom import geomBuilder geompy = geomBuilder.New(salome.myStudy)
Osnovni program - Izdelava skatle
Funkcija geompy.MakeBox() sprejme koordinate dveh tock, ki lezita na diagonali.
import salome import GEOM from salome.geom import geomBuilder geompy = geomBuilder.New(salome.myStudy) box = geompy.MakeBox(10.0,10.0,10.0, 20, 20, 20) # Dodamo novo spremenljivko v studijo geompy.addToStudy(box, 'Skatla') salome.sg.updateObjBrowser(True)
Osnovni program - Primer izdelave izvleka v prostor (Extrusion)
Postopek modeliranja v komercialnih modelirnikih (SolidWorks?, Creo, Catia, NX, ProEngineer?, Inventor,...) je sledeči:
- izbira ravnine, na katero se nariše skica
- izris oblike skice (kvadrat)
- definiranje skice (dimenzije, geometrijske relacije, pozicija v prostoru)
- izbira ustrezne značilke za izdelavo 3D objekta (Izvlek- Extrude)
- določitev parametrov izvleka (smer, dolžina izvleka)
- model je zmodeliran
V okolju Salome poteka izris objekta nekoliko drugače. Razložen je preprosti postopek izdelave kocke, ki poteka v večih korakih. Pri izdelavi je potrebno manualno določiti vse parametre, ki jih komercialni modelirnik običajno določi namesto nas.
Korak 1: Uvoz knjiznic
Z uvozom knjiznic je omogocena uporaba vseh funkcij, ki jih potrebujemo za izdelavo kocke.
import salome salome.salome_init() import GEOM from salome.geom import geomBuilder geompy = geomBuilder.New(salome.myStudy) gg = salome.ImportComponentGUI("GEOM")
Korak 2: Izdelava tock
V prostoru je potrebno definirati tocke. Definiramo jih s funkcijo geompy.MakeVertex().
p1 = geompy.MakeVertex( 0., 0., 0.) p2 = geompy.MakeVertex( 100., 0., 0.) p3 = geompy.MakeVertex( 100., 100., 0.) p4 = geompy.MakeVertex( 0., 100., 0.)
Za prikaz objektov v modulu Geometry v okolju Salome uporabimo naslednje ukaze
# Dodamo nove tocke v studijo geompy.addToStudy(p1,"point1") geompy.addToStudy(p2,"point2") geompy.addToStudy(p3,"point3") geompy.addToStudy(p4,"point4") salome.sg.updateObjBrowser(True)
Korak 3: Izdelava krivulje, ki povezuje vse tocke
Z ukazom geompy.MakePolyline() izdelamo krivuljo, ki je sestavljena iz stirih daljic.
polyline = geompy.MakePolyline([p1, p2, p3, p4, p1]) # Dodamo novo krivuljo v studijo geompy.addToStudy(polyline,"polyline") # Posodobimo drevesno strukturo salome.sg.updateObjBrowser(True)
Korak 4: Izdelava povrsine.
Sedaj je potrebno izdelati povrsino, ki bo omejena s prej izdelano krivuljo. To storimo z ukazom geompy.MakeFace(). Ta funkcija sprejme zaprto krivuljo (polyline). Nato je spremenljivko potrebno dodati v studijo modula GEOM z ukazom addToStudy().
face = geompy.MakeFace(polyline, True) # Dodamo novo povrsino v studijo geompy.addToStudy(face, "face") # Posodobimo drevesno strukturo salome.sg.updateObjBrowser(True)
Drevesno strukturo posodobimo, ce zelimo prikazati nove geometrijske elemente v modelnem oknu.
Korak 5: Izvlek povrsine
Izvlek povrsine izvedemo z ukazom geompy.MakePrism(). Omenjeni ukaz sprejme tri argumente(povrsina, tocka1, tocka2), pri cemer sta tocka1 in tocka2 tocki, ki definirata vektor.
p5 = geompy.MakeVertex(0.,0.,100.) prism1 = geompy.MakePrism(face, p1, p5) # Dodamo nov izvlek v studijo geompy.addToStudy(prism1, "prism1") # Posodobimo drevesno strukturo salome.sg.updateObjBrowser(True)
Celoten postopek izdelave izvleka je v priponki (salomePrismExample.py).
Primer izdelave panela v fuzijskem reaktorju ITER
V tem primeru bo prikazana izdelava krivulj v 3D prostoru in izvlek krivulj, s katerim generiramo površino v prostoru. Končni cilj je izdelava panela, prikazanega na sliki. V datoteki data.txt imamo podane koordinate točk (x, y in z), iz katerih bomo generirali krivujo. To krivuljo bomo nato izvlekli v prostor s pomočjo daljic, ki so prav tako definirana s točkami (xe, ye in ze). Podatki so podani v formatu
x1 y1 z1 x2 y2 z2 x3 y3 z3 ... xn yn zn
Korak 1: Uvoz modulov
Najprej je potrebno v python uvoziti vse knjižnice, ki jih bomo uporabili v Salome okolju. Nato pa je potrebno definirati novo študijo.
# Uvoz knjiznic import salome import GEOM from salome.geom import geomBuilder geompy = geomBuilder.New(salome.myStudy)
Korak 2: Uvoz podatkov v Python
Podatke v stolpcih v tekstovnem formatu lahko preberemo na vec načinov, v tem primeru smo uporabili funkcijo open
. Podatke za krivuljo shranimo v spremenljivko tipa list
z imenoma coord_x in coord_y. Nato te točke zrcalimo preko ravnine y-z, da dobimo krivuljo še za levo stran panela, in jih shranimo v spremenljivki coord_x_mirror
in coord_y_mirror
. Nato izvedemo iteracijo s for zanko in shranimo točke kot geompy.MakeVertex()
ter jih shranimo v python-ov seznam.
# Load data # If file is not opened, determine path with os library # import os # os.chdir(os.path.expanduser('~/')) with open('data.txt','r') as f: fileread = f.readlines() content = [x.strip() for x in fileread] # Define data list data = [] for coord in content: data.append([x.strip() for x in coord.split(" ")]) f.close() coord_x = [] coord_y = [] # convert coordinates to mm and to float type for i in range(len(data)): data[i][0] = float(data[i][0])*(1000) data[i][1] = float(data[i][1])*(1000) data[i][2] = float(data[i][1])*(1000) coord_x.append(data[i][0]) coord_y.append(data[i][1]) # mirror x coordinatex over yz - plane coord_mirror_x = coord_x[::-1] for n in range(len(coord_mirror_x)): coord_mirror_x[n] = coord_mirror_x[n]*(-1) coord_mirror_y = coord_y[::-1] # Iterate over coord_x and create geompy vertices and store those # vertices into python list. points_x = [] for i in range(len(coord_x)): point_x = geompy.MakeVertex(coord_x[i],coord_y[i],0) points_x.append(point_x) points_y = [] for i in range(len(coord_x)): point_y = geompy.MakeVertex(coord_mirror_x[i],coord_mirror_y[i],0) points_y.append(point_y)
Korak 3: Izdelava krivulj
Nato generiramo B-zlepek krivuljo s pomočjo metode geompy.MakeInterpol()
, ki sprejme seznam točk, na katerih izvede interpolacijo. Rezultat je polinom, ki predstavlja podano krivuljo. Nato izračunano krivuljo dodamo v študijo.
# Create B-Spline curve on the set of points with # geompy.MakeInterpol() and add curve to Salome study. b_spline = geompy.MakeInterpol(points_x) b_splineID = geompy.addToStudy(b_spline,"b_spline_ft") b_spline_mirror = geompy.MakeInterpol(points_y) b_splineID_mirror = geompy.addToStudy(b_spline_mirror,"b_spline_ft_mirrored")
Sedaj je potrebno kreirati še daljico, s katero bomo povezali obe krivulji (na sliki označena z rumeno barvo).
# Create line between both curves. ml_point1 = geompy.MakeVertex(-coord_x[0],coord_y[0],0) ml_point2 = geompy.MakeVertex(coord_x[0],coord_y[0],0) middle_line = geompy.MakeLineTwoPnt(ml_point1,ml_point2) middle_lineID = geompy.addToStudy(middle_line,"middle_line")
Nato je potrebno vse tri komponente združiti v skupen objekt, ki ga bomo izvlekli v prostor. To storimo z metodo geompy.MakeWire()
, ki sprejme seznam krivulj, robov in daljic, ki jih želimo združiti v en objekt.
# Create wire out of all three components wire = geompy.MakeWire([b_spline_mirror,middle_line,b_spline]) wireID = geompy.addToStudy(wire,"wire")
Korak 4: Izdelava krivulje za izvlek
Nato izdelamo še krivuljo za izvlek, ki je prikazana na sliki. Ponovno uvozimo točke in jih shranimo v spremenljivke tipa list
.
# Load data for extrusion dataExtrusion = [] with open('dataPolyline.txt','r') as f: fileread = f.readlines() content = [x.strip() for x in fileread] # Define data list for coord in content: dataExtrusion.append([x.strip() for x in coord.split(" ")]) f.close() # Read data for extrusion coord_xe = [] coord_ye = [] coord_ze = [] for n in range(len(dataExtrusion)): coord_xe.append(float(dataExtrusion[n][0])) coord_ye.append(float(dataExtrusion[n][1])) coord_ze.append(float(dataExtrusion[n][2]))
Koordinate ponovno pretvorimo v točke tipa geompy
z ukazom geompy.MakeVertex()
ter nato generiramo polyline.
# Convert data to geompy point and store it in a list. points_e = [] for point_e in range(len(coord_xe)): point_e = geompy.MakeVertex(coord_xe[point_e],coord_ye[point_e],coord_ze[point_e]) points_e.append(point_e) # Create polyline for extrusion and add it to study. polylineVert = geompy.MakePolyline(points_e) polylineVertID = geompy.addToStudy(polylineVert,"b_spline_ft_vert")
Korak 5: Izvlek iz krivulj
Na koncu ustvarimo izvlek iz obeh danih krivulj. Izvlek dodamo v študijo in posodobimo drevesno strukturo.
# Create panel shape panel_FW = geompy.MakePipe(polylineVert, wire) geompy.addToStudy(panel_FW,'Panel') salome.sg.updateObjBrowser(True)
Celoten postopek izdelave izvleka je v priponki (salomePanelExample.py).
Razširitev programa panela na grafični vmesnik
Celoten program lahko razširimo na grafični vmesnik, da bo lahko uporabnik lažje uporabljal napisani program. Grafični vmesnik je napisan s pomočjo knjižnice PyQt5. Vmesnik bo uporabljal vertikalno razporeditev grafičnih elementov, ki so QPushButton, QLineEdit in QLabel.
- QPushButton predstavlja gumb. S klikom nanj se izvede funkcija, ki opravi določeno nalogo.
- QLineEdit omogoča vnos teksta v program.
- QLabel služi za prikaz besedila in je statični element, ki podaja neko informacijo.
Na sliki je prikazan primer izgleda uporabniškega vmesnika, ki ga bomo napisali v tem poglavju. Ta vmesnik grafične elemente razporedi v vertikalni smeri z metodo QVBoxLayout(). Na vrhu je definiran QLabel, pod njim pa gumb QPushButton. S klikom nanj se izvede funkcija, ki izriše panel in ga pozicionira v prostoru. Nato lahko panel še rotiramo in naredimo kopije panela. V QLineEdit pod Set name: zapišemo imena rotiranih panelov, v QLineEdit pod Set rotation angle:: zapišemo kot rotacije okoli z-osi tipa float
, v QLineEdit pod Set number of rotations: pa število panelov tipa int
.
Na začetku ponovno uvozimo vse potrebne knjižnice, tokrat tudi grafično knjižnico PyQt5
.
# import libraries import salome import GEOM from salome.geom import geomBuilder import os from functools import partial # GUI library from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import *
Sedaj lahko definiramo obe funkciji, kise bosta izvedli, ko bomo pritisnili na oba gumba tipa QPushButton. Funkcija, ki izdela panel in ga premakne v y osi za -4200 milimetrov, se imenuje createPanel in je v osnovi isti program kot pri izdelavi panela, le da je shranjen v funkcijo.
def createPanel(): global panelIsMade panelIsMade = True # If file is not opened, determine path with os library os.chdir(os.path.expanduser('d:/vaje_KT/')) with open('data.txt','r') as f: fileread = f.readlines() content = [x.strip() for x in fileread] # Define data list data = [] for coord in content: data.append([x.strip() for x in coord.split(" ")]) f.close() coord_x = [] coord_y = [] # convert coordinates to mm and to float type for i in range(len(data)): data[i][0] = float(data[i][0])*(1000) data[i][1] = float(data[i][1])*(1000) data[i][2] = float(data[i][1])*(1000) coord_x.append(data[i][0]) coord_y.append(data[i][1]) # mirror x coordinatex over yz - plane coord_mirror_x = coord_x[::-1] for n in range(len(coord_mirror_x)): coord_mirror_x[n] = coord_mirror_x[n]*(-1) coord_mirror_y = coord_y[::-1] # Iterate over coord_x and create geompy vertices and store those # vertices into python list. points_x = [] for i in range(len(coord_x)): point_x = geompy.MakeVertex(coord_x[i],coord_y[i],0) points_x.append(point_x) points_y = [] for i in range(len(coord_x)): point_y = geompy.MakeVertex(coord_mirror_x[i],coord_mirror_y[i],0) points_y.append(point_y) # Create B-Spline curve on the set of points with # geompy.MakeInterpol() and add curve to Salome study. b_spline = geompy.MakeInterpol(points_x) b_splineID = geompy.addToStudy(b_spline,"b_spline_ft") b_spline_mirror = geompy.MakeInterpol(points_y) b_splineID_mirror = geompy.addToStudy(b_spline_mirror,"b_spline_ft_mirrored") # Create line between both curves. ml_point1 = geompy.MakeVertex(-coord_x[0],coord_y[0],0) ml_point2 = geompy.MakeVertex(coord_x[0],coord_y[0],0) middle_line = geompy.MakeLineTwoPnt(ml_point1,ml_point2) middle_lineID = geompy.addToStudy(middle_line,"middle_line") # Create wire out of all three components wire = geompy.MakeWire([b_spline_mirror,middle_line,b_spline]) wireID = geompy.addToStudy(wire,"wire") # Load data for extrusion dataExtrusion = [] with open('dataPolyline.txt','r') as f: fileread = f.readlines() content = [x.strip() for x in fileread] # Define data list for coord in content: dataExtrusion.append([x.strip() for x in coord.split(" ")]) f.close() # Read data for extrusion coord_xe = [] coord_ye = [] coord_ze = [] for n in range(len(dataExtrusion)): coord_xe.append(float(dataExtrusion[n][0])) coord_ye.append(float(dataExtrusion[n][1])) coord_ze.append(float(dataExtrusion[n][2])) # Convert data to geompy point and store it in a list. points_e = [] for coord_e in range(len(coord_xe)): point_e = geompy.MakeVertex(coord_xe[coord_e],coord_ye[coord_e],coord_ze[coord_e]) points_e.append(point_e) # Create polyline for extrusion and add it to study. polylineVert = geompy.MakePolyline(points_e) polylineVertID = geompy.addToStudy(polylineVert,"polyline_ft_vert") panel_FW = geompy.MakePipe(wire, polylineVert) panel_FW = geompy.MakeTranslation(panel_FW, 0,-4200,0) geompy.addToStudy(panel_FW,'Panel') salome.sg.updateObjBrowser(True)
Nato zapišemo še funkcijo createNewPanel, ki se izvede ob pritisku na gumb Apply, in izdela zasukane panele. Omenjena funkcija kot vhodne argumente prejme tri spremenljivke tipa QLineEdit. V našem primeru je lin1 objekt razreda QLineEdit, ki sprejme tekst, ki predstavlja ime zasukanih panelov, lin2 predstavlja kot rotacije panelov, lin3 pa število zasukanih panelov. Do teskta dostopamo z metodo QLineEdit.text()
, npr. lin1.text()
vrne spremenljivko, ki vsebuje vnešen tekst v omenjeni QLineEdit(). Omenjena funkcija bo zdelala zasukane panele, če bo uporabnik predhodno izdelal panel, ki ga definira gumb Create panel.
def createNewPanel(lin1, lin2, lin3): # If panel is not made, there is nothing to rotate # If lin2.text() is not float, angle cannot be determined # If lin3.text() is not int, number of rotated panels cannot be determined if panelIsMade and float(lin2.text()) and int(lin3.text()): p1 = geompy.MakeVertex(0, 0, 0) p2 = geompy.MakeVertex(0, 0, 1) v = geompy.MakeVector(p1, p2) # This for loop iterates over number of roteted panels and # adds angle to every new panel. Result is panel_FW_rotated # Name of panel is given by user + angle of rotation for nr in range(1,int(lin3.text())+1): panel_FW_rotated = geompy.MakeRotation(panel_FW, v, math.pi/180*nr*float(str(lin2.text()))) panel_name = str(lin1.text())+"_rotated_"+str(float(str(lin2.text()))*nr)+"_deg" geompy.addToStudy(panel_FW_rotated,panel_name) salome.sg.updateObjBrowser(True)
Sedaj lahko izdelamo uporabniški vmesnik. Vsak uporabniški vmesnik je definiran kot objekt. Pri knjižnici PyQt5 je to objekt, definiran kot QtWidgets?.QWidget(). Objekt ima svoje metode, kot so npr. setFixedSize()
, ki definira točno velikost dialoga, ter setWindowTitle()
, ki definira naslov dialoga.
widgetHDF = QtWidgets.QWidget() widgetHDF.setFixedSize(500, 250) widgetHDF.setWindowTitle('Rotate panel')
Nato definiramo uporabljene grafične elemente. Spremenljivka panelIsMade je uporabljena v funkciji createNewPanel. Če je njena vrednost False
, se funkcija ne izvede, saj to pomeni, da predhodni panel, ki ga kopiramo, ni bil izdelan.
lblPanel = QLabel('Create panel:') btnPanel = QPushButton('Create Panel') lbl1 = QLabel('Set name for rotation panels:') lin1 = QLineEdit('panel4') lbl2 = QLabel('Set rotation angle:') lin2 = QLineEdit('0') lbl3 = QLabel('Set number of rotations:') lin3 = QLineEdit('1') btn = QPushButton('Apply') panelIsMade = False
Metoda setToolTip
prikaže namig, če kurzor premaknemo na gumb. Ko kliknemo na gumb, se mora izvesti neka funkcija. V PyQt5 knjižnici ima gumb metodo clicked.connect()
, ki kot vhodni argument sprejme ime funkcije, ki se mora izvesti. Gumb btnPanel razreda QPushButton pokliče funkcijo createPanel(), ki ne sprejme nobenega vhodnega argumenta, saj je njena naloga samo izrisati predhodno določen in pozicioniran panel. Drugače je pri gumbu btn. Ta kliče funkcijo createNewPanel(), ki sprejme tri vhodne argumente, ki so ime panelov, kot in število panelov. Metoda clicked.connect()
pa sprejme samo en argument. To rešimo s funkcijo partial
. Prvi argument te funkcije je createNewPanel, ostali argumenti pa so vhodni argumenti za našo funkcijo. Funkcija partial()
tako vhodne argumente poda v createNewPanel. in rezultat prenese v clicked.connect()
.
btnPanel.setToolTip('Create panel') btn.setToolTip('Create rotated panels') btnPanel.clicked.connect(btnPanel.clicked.connect(createPanel)) btn.clicked.connect(partial(createNewPanel,lin1,lin2,lin3))
Sedaj lahko definiramo razporeditev grafičnih elementov v našem dialogu. Možne izbire so QGridLayout(), kar pomeni mrežna razporeditev elementov, QHBoxLayout(), ki elemente razporedi horizontalno in QVBoxLayout(), ki elemente razporedi vertikalno. V našem primeru uporabimo QVBoxLayout(), ki grafične elemente glede na zaporedje dodajanja v dialog razvršča vertikalno od zgoraj navzdol (prvi element, ki je dodan v dialog, v našem primeru lblPanel tipa QLabel, je na vrhu, nato sledijo drugi).
layout = QtWidgets.QVBoxLayout() layout.addWidget(lblPanel) layout.addWidget(btnPanel) layout.addWidget(lbl1) layout.addWidget(lin1) layout.addWidget(lbl2) layout.addWidget(lin2) layout.addWidget(lbl3) layout.addWidget(lin3) layout.addWidget(btn)
Na koncu v objekt, ki definira dialog, namestimo porazdelitev grafičnih elementov. Z metodo move()
lahko določimo, kje na ekranu bo pozicioniran dialog, z metodo show()
pa dokončno prikažemo dialog na zaslonu.
widgetHDF.setLayout(layout) widgetHDF.move(500, 500) widgetHDF.show()
Attachments (27)
-
data.txt (36.6 KB) - added by 7 years ago.
Tekstovna datoteka, ki vsebuje točke za izdelavo krivulje za panel
-
dataPolyline.txt (125 bytes) - added by 7 years ago.
Tekstovna datoteka, ki vsebuje točke za izdelavo krivulje za izvlek za panel
-
salomePrismExample.py (767 bytes) - added by 7 years ago.
Program za primer izdelave izvleka v prostor.
-
b_splineSalomePanelExample.png (7.3 KB) - added by 7 years ago.
Slika, ki prikazuje krivulji za primer izdelave panela.
-
prismSalomePrismExample.png (5.6 KB) - added by 7 years ago.
Slika, ki prikazuje izvlek kvadrata v prostor (kocka).
-
faceSalomePrismExample.png (5.0 KB) - added by 7 years ago.
Slika, ki prikazuje površino kvadrata.
-
polylineSalomePrismExample.png (5.5 KB) - added by 7 years ago.
Slika, ki prikazuje kvadrat za izvlek.
-
pointsSalomePrismExample.png (7.2 KB) - added by 7 years ago.
Slika, ki prikazuje točke, ki definirajo kvadrat.
-
modelSalomePanelExample.png (15.3 KB) - added by 7 years ago.
Slika, ki prikazuje model panela.
-
polylineSalomePanelExample.png (10.4 KB) - added by 7 years ago.
Prikaz krivulje za izvlek pri izdelavi panela.
-
salomePanelExample.py (3.0 KB) - added by 7 years ago.
Primer za izdelavo panela. Brez numpy knjiznice.
-
salomePanelDialogExample.png (4.5 KB) - added by 7 years ago.
Dialog za izdelavo panela.
-
salomePanelsRotatedExample.png (42.7 KB) - added by 7 years ago.
Prikaz rotiranih panelov.
-
salomeDialogPanelExample.py (5.6 KB) - added by 7 years ago.
Koda za izdelavo dialoga, ki izdela zasuke panela.
-
divertor_dlg.ui (3.7 KB) - added by 7 years ago.
Dialog za Qt designer
-
divertor.qrc (104 bytes) - added by 7 years ago.
Qt Resouce description v obliki XML
-
divertor.png (141.8 KB) - added by 7 years ago.
Slika divertorja
-
salomeDialogImageExample.png (19.8 KB) - added by 7 years ago.
Prikaz GUI-ja z izdelavo QtDesignerja?.
-
salomeDialogImageExample.py (197.5 KB) - added by 7 years ago.
Koda za izdelavo GUI-ja s sliko.
-
salomeDivertorGuiExample.png (47.8 KB) - added by 7 years ago.
Primer Gui-ja za divertor.
-
divertor.py (3.5 MB) - added by 7 years ago.
Koda izdelave GUI-ja za divertor.
-
salomeDivertorGuiExampleImage.png (103.0 KB) - added by 7 years ago.
Primer Gui-ja za divertor s sliko.
-
svessel.py (380.0 KB) - added by 7 years ago.
Program za magnete
-
ms.qrc (96 bytes) - added by 7 years ago.
Magnet System Resource file
-
vv.ui (5.9 KB) - added by 7 years ago.
Primer dialoga
-
ms.png (89.3 KB) - added by 7 years ago.
Slika magnetov
-
signal_primer.py (757 bytes) - added by 7 years ago.
Primer povezovanja signalov v PyQt5