Dialog creation/pl: Difference between revisions
(Updating to match new version of source page) |
No edit summary |
||
(55 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
<languages/> |
<languages/> |
||
{{Docnav/pl |
|||
|[[Interface_creation/pl|Tworzenie interfejsu]] |
|||
|[[License/pl|Licencja]] |
|||
}} |
|||
{{TOCright}} |
{{TOCright}} |
||
= |
<span id="Introduction"></span> |
||
==Wprowadzenie== |
|||
Na tej stronie pokażemy, jak zbudować prosty interfejs graficzny za pomocą [http://qt-project.org/doc/qt-4.8/designer-manual.html Qt Designer], oficjalnego narzędzia Qt do projektowania interfejsów. Przekonwertujemy okno dialogowe na kod [[Python/pl|Python]], a następnie będzie używane wewnątrz FreeCAD. Zakładamy, że użytkownik wie, jak edytować i uruchamiać [[Python/pl|Python]]. |
|||
W tym przykładzie cały interfejs jest zdefiniowany w środowisku [[Python|Python]]. Chociaż jest to możliwe w przypadku małych interfejsów, w przypadku większych interfejsów zaleca się ładowanie utworzonych plików {{FileName|.ui}} bezpośrednio do programu. |
|||
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. See [[Interface_creation_with_UI_files|Interface creation with UI files]] for more information. |
|||
[[File:FreeCAD_creating_interfaces.svg|600px]] |
[[File:FreeCAD_creating_interfaces.svg|600px]] |
||
{{Caption| |
{{Caption|Dwie ogólne metody tworzenia interfejsów, poprzez włączenie interfejsu do pliku Python lub poprzez użycie plików {{incode|.ui}}.}} |
||
<span id="Designing_the_dialog"></span> |
|||
== Designing the dialog == |
|||
==Projektujemy okno dialogowe== |
|||
W aplikacjach CAD zaprojektowanie dobrego interfejsu użytkownika ''(UI)'' jest bardzo ważne. Prawie wszystko, co użytkownik będzie robił, będzie odbywało się za pośrednictwem jakiegoś elementu interfejsu: czytanie okien dialogowych, naciskanie przycisków, wybieranie między ikonami itp. Dlatego bardzo ważne jest, aby dokładnie przemyśleć co chcesz zrobić, jak chcesz aby użytkownik postępował i jaki będzie przepływ pracy. |
|||
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. |
|||
Istnieje kilka pojęć, które należy znać podczas projektowania interfejsu: |
|||
There are a couple of concepts to know when designing interface: |
|||
* [http://en.wikipedia.org/wiki/Modal_window |
* [http://en.wikipedia.org/wiki/Modal_window Modalne/niemodalne okna dialogowe]: Modalne okno dialogowe pojawia się przed ekranem, zatrzymując działanie głównego okna, zmuszając użytkownika do odpowiedzi na okno dialogowe, podczas gdy niemodalne okno dialogowe nie przerywa pracy w głównym oknie. W niektórych przypadkach pierwsze rozwiązanie jest lepsze, w innych nie. |
||
* Określenie, co jest wymagane, a co opcjonalne: Upewnij się, że użytkownik wie, co musi zrobić. Oznacz wszystko odpowiednim opisem, użyj podpowiedzi itp. |
|||
* Identifying what is required and what is optional: Make sure the user knows what he must do. Label everything with proper description, use tooltips, etc. |
|||
* Oddzielanie poleceń od parametrów: Zazwyczaj robi się to za pomocą przycisków i pól wprowadzania tekstu. Użytkownik wie, że kliknięcie przycisku spowoduje akcję, podczas gdy zmiana wartości w polu tekstowym zmieni gdzieś parametr. Jednak w dzisiejszych czasach użytkownicy zwykle dobrze wiedzą, co jest przyciskiem, co jest polem wejściowym itp. Zestaw narzędzi interfejsu, którego używamy, Qt, jest najnowocześniejszym zestawem narzędzi i nie będziemy musieli się zbytnio martwić o wyjaśnianie rzeczy, ponieważ będą one już bardzo zrozumiałe same w sobie. |
|||
* Separating commands from parameters: This is usually done with buttons and text input fields. The user knows that clicking a button will produce an action while changing a value inside a text field will change a parameter somewhere. Nowadays, though, users usually know well what is a button, what is an input field, etc. The interface toolkit we are using, Qt, is a state-of-the-art toolkit, and we won't have to worry much about making things clear, since they will already be very clear by themselves. |
|||
Tak więc, teraz, gdy dobrze zdefiniowaliśmy, co będziemy robić, nadszedł czas, aby otworzyć projektanta QT. Zaprojektujmy bardzo proste okno dialogowe, takie jak to: |
|||
So, now that we have well defined what we will do, it's time to open the qt designer. Let's design a very simple dialog, like this: |
|||
[[Image:Qttestdialog.jpg]] |
[[Image:Qttestdialog.jpg]] |
||
Następnie użyjemy tego okna dialogowego w programie FreeCAD, aby utworzyć ładną prostokątną płaszczyznę. Może się okazać, że nie jest to zbyt przydatne do tworzenia ładnych prostokątnych płaszczyzn, ale łatwo będzie je później zmienić, aby robić bardziej złożone rzeczy. Po otwarciu Qt Designer wygląda następująco: |
|||
We will then use this dialog in FreeCAD to produce a nice rectangular plane. You might find it not very useful to produce nice rectangular planes, but it will be easy to change it later to do more complex things. When you open it, Qt Designer looks like this: |
|||
[[Image:Qtdesigner-screenshot.jpg]] |
[[Image:Qtdesigner-screenshot.jpg]] |
||
==Tworzymy okno dialogowe== |
|||
== Creating the dialog == |
|||
Qt Designer jest bardzo prosty w użyciu. Na lewym pasku znajdują się elementy, które można przeciągnąć na widżet. Po prawej stronie znajdują się panele właściwości wyświetlające wszystkie rodzaje edytowalnych właściwości wybranych elementów. Zacznijmy więc od utworzenia nowego widżetu. |
|||
Qt Designer is very simple to use. On the left bar you have elements that can be dragged on your widget. On the right side you have properties panels displaying all kinds of editable properties of selected elements. So, begin with creating a new widget. |
|||
# |
# Wybieramy "Dialog bez przycisków", ponieważ nie chcemy domyślnych przycisków {{KEY|OK}}/{{KEY|Cancel}}. |
||
# Potrzebujemy '''Etykiety'''. Etykiety to proste ciągi tekstowe, które pojawiają się na widżecie, aby poinformować użytkownika końcowego. Jeśli wybierzesz etykietę, zauważysz, że po prawej stronie pojawi się kilka właściwości, które możesz modyfikować, takich jak: styl czcionki, wysokość itp. Przeciągnijmy więc 3 oddzielne etykiety na nasz widżet: |
|||
# We need '''Labels''. Labels are simple text strings that appear on your widget to inform the end user. If you select a label, notice that on the right side there will appear several properties that you can modify such as: font style, height, etc... So lets drag 3 separate labels on to our widget: |
|||
#* Jedna etykieta dla tytułu |
|||
#* One label for the title |
|||
#* |
#* Kolejna etykieta do napisania "'''Wysokość'''" |
||
#* |
#* Kolejna etykieta do napisania "'''Szerokość'''" |
||
# Potrzebujemy teraz LineEdits ''(a właściwie 2 z nich)''. Przeciągnij dwa z nich na widżet. '''LineEdits''' to pola tekstowe, które użytkownik końcowy może wypełnić. Potrzebujemy więc jednego LineEdit dla "Wysokość" i jednego dla "Szerokość". Tutaj również możemy edytować właściwości. Na przykład, dlaczego nie ustawić wartości domyślnej, powiedzmy na przykład: 1.00 dla każdego. W ten sposób, gdy użytkownik zobaczy okno dialogowe, obie wartości będą już wypełnione. Jeśli użytkownik będzie zadowolony, może bezpośrednio nacisnąć przycisk, oszczędzając cenny czas. |
|||
# We now need LineEdits (2 of them actually). Drag two of them on to the widget. '''LineEdits''' are text fields that the end user can fill in. So we need one LineEdit for the ''Height'' and one for the ''Width''. Here too, we can edit properties. For example, why not set a default value say for example: 1.00 for each. This way, when the user will see the dialog, both values will be filled already. If the end user is satisfied, they can directly press the button, saving precious time. |
|||
# |
# Następnie dodajmy przycisk '''PushButton'''. Jest to przycisk, który użytkownik końcowy będzie musiał nacisnąć po wypełnieniu obu pól. |
||
''' |
'''Uwaga:''' wybraliśmy tutaj bardzo proste kontrolki. Qt ma o wiele więcej opcji, na przykład można użyć '''Spinboxes''' zamiast '''LineEdits''' itp. Przyjrzyj się temu, co jest dostępne, zbadaj... na pewno będziesz miał inne pomysły. |
||
To wszystko, co musimy zrobić w Qt Designer. Na koniec zmieńmy nazwy wszystkich elementów na prostsze, aby łatwiej było je zidentyfikować w naszych skryptach: |
|||
That's about all we need to do in Qt Designer. One last thing, though, let's rename all our elements with simpler names, so it will be easier to identify them in our scripts: |
|||
[[Image:Qtpropeditor.jpg]] |
[[Image:Qtpropeditor.jpg]] |
||
<span id="Converting_our_dialog_to_python"></span> |
|||
== Converting our dialog to python == |
|||
==Konwersja naszego okna dialogowego do środowiska Python== |
|||
Now, let's save our widget somewhere. It will be saved as an .ui file, that we will easily convert to python script with pyuic. On windows, the pyuic program is bundled with pyqt (to be verified), on linux you probably will need to install it separately from your package manager (on debian-based systems, it is part of the pyqt4-dev-tools package). To do the conversion, you'll need to open a terminal window (or a command prompt window on windows), navigate to where you saved your .ui file, and issue: |
|||
Teraz zapiszmy gdzieś nasz widget. Zostanie on zapisany jako plik .ui, który z łatwością przekonwertujemy na skrypt Pythona za pomocą pyuic. Na Windowsie program pyuic jest dołączony do pyqt ''(do sprawdzenia)'', na linuksie prawdopodobnie będziesz musiał zainstalować go osobno z menedżera pakietów ''(na systemach opartych na debianie jest on częścią pakietu pyqt4-dev-tools)''. Aby dokonać konwersji, należy otworzyć okno terminala (lub okno wiersza polecenia w systemie Windows), przejść do miejsca, w którym zapisano plik .ui i wydać polecenie: |
|||
{{Code|code= |
{{Code|code= |
||
pyuic mywidget.ui > mywidget.py |
pyuic mywidget.ui > mywidget.py |
||
}} |
}} |
||
W systemie Windows pyuic.py znajduje się w "C:\Python27\Lib\site-packages\PyQt4\uic\pyuic.py". |
|||
Do konwersji należy utworzyć plik wsadowy o nazwie "compQt4.bat": |
|||
{{Code|code= |
{{Code|code= |
||
@"C:\Python27\python" "C:\Python27\Lib\site-packages\PyQt4\uic\pyuic.py" -x %1.ui > %1.py |
@"C:\Python27\python" "C:\Python27\Lib\site-packages\PyQt4\uic\pyuic.py" -x %1.ui > %1.py |
||
}} |
}} |
||
W konsoli DOS wpisz bez rozszerzenia |
|||
In the DOS console type without extension |
|||
{{Code|code= |
{{Code|code= |
||
compQt4 myUiFile |
compQt4 myUiFile |
||
}} |
}} |
||
W systemie macOS można pobrać odpowiednią wersję ''(tę samą, która jest używana wewnętrznie w FreeCAD 0.19)'' QT i Pyside za pomocą następujących poleceń ''(wymagany program)'': |
|||
Into Linux : to do |
|||
{{Code|code= |
|||
python3 -m pip install pyqt5 |
|||
python3 -m pip install pySide2 |
|||
}} |
|||
Spowoduje to zainstalowanie uic w folderze "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/uic", a Designer w "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/Designer.app". |
|||
Dla wygody można utworzyć link do uic w /usr/local/bin, aby móc go wywołać po prostu za pomocą uic -g python ... zamiast wpisywania całej ścieżki programu, oraz link do Designera, aby pobrać go w folderze Aplikacje na komputerze Mac za pomocą: |
|||
{{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 |
|||
}} |
|||
W Linuksie: do zrobienia. |
|||
Ponieważ FreeCAD stopniowo odchodził od PyQt po wersji 0.13, na rzecz [http://qt-project.org/wiki/PySide PySide] ''(Wybierz instalację PySide [http://pyside.readthedocs.org/en/latest/building/ budowanie PySide])'', aby plik był oparty na PySide, musisz teraz użyć: |
|||
{{Code|code= |
{{Code|code= |
||
pyside-uic mywidget.ui -o mywidget.py |
pyside-uic mywidget.ui -o mywidget.py |
||
}} |
}} |
||
W systemie Windows plik uic.py znajduje się w katalogu "C:\Python27\Lib\site-packages\PySide\scripts\uic.py". |
|||
Aby utworzyć plik wsadowy "compSide.bat": |
|||
{{Code|code= |
{{Code|code= |
||
@"C:\Python27\python" "C:\Python27\Lib\site-packages\PySide\scripts\uic.py" %1.ui > %1.py |
@"C:\Python27\python" "C:\Python27\Lib\site-packages\PySide\scripts\uic.py" %1.ui > %1.py |
||
}} |
}} |
||
W konsoli DOS wpisz bez rozszerzenia: |
|||
In the DOS console type without extension |
|||
{{Code|code= |
{{Code|code= |
||
compSide myUiFile |
compSide myUiFile |
||
}} |
}} |
||
W Linuksie: do zrobienia. |
|||
Into Linux : to do |
|||
W niektórych systemach program nazywa się pyuic4 zamiast pyuic. Spowoduje to po prostu konwersję pliku .ui na skrypt Pythona. Jeśli otworzymy plik mywidget.py, jego zawartość jest bardzo przejrzysta: |
|||
{{Code|code= |
{{Code|code= |
||
from PySide import QtCore, QtGui |
from PySide import QtCore, QtGui |
||
Line 100: | Line 120: | ||
... |
... |
||
}} |
}} |
||
Jak widać, ma on bardzo prostą strukturę: tworzona jest klasa o nazwie Ui_Dialog, która przechowuje elementy interfejsu naszego widżetu. Ta klasa ma dwie metody, jedną do konfiguracji widżetu, a drugą do tłumaczenia jego zawartości, co jest częścią ogólnego mechanizmu Qt do tłumaczenia elementów interfejsu. Metoda konfiguracji po prostu tworzy, jeden po drugim, widżety tak, jak zdefiniowaliśmy je w Qt Designer i ustawia ich opcje tak, jak zdecydowaliśmy wcześniej. Następnie cały interfejs zostaje przetłumaczony, a na koniec sloty zostają połączone ''(o tym powiem później)''. |
|||
As you see it has a very simple structure: a class named Ui_Dialog is created, that stores the interface elements of our widget. That class has two methods, one for setting up the widget, and one for translating its contents, which is part of the general Qt mechanism for translating interface elements. The setup method simply creates, one by one, the widgets as we defined them in Qt Designer, and sets their options as we decided earlier. Then, the whole interface gets translated, and finally, the slots get connected (we'll talk about that later). |
|||
Możemy teraz utworzyć nowy widżet i użyć tej klasy do stworzenia jego interfejsu. Możemy już zobaczyć nasz widżet w akcji, umieszczając nasz plik mywidget.py w miejscu, w którym FreeCAD go znajdzie (w katalogu bin FreeCAD lub w dowolnym z podkatalogów Mod), a następnie w interpreterze python FreeCAD wydać polecenie: |
|||
{{Code|code= |
{{Code|code= |
||
from PySide import QtGui |
from PySide import QtGui |
||
Line 111: | Line 131: | ||
d.show() |
d.show() |
||
}} |
}} |
||
I pojawi się nasze okno dialogowe! Zauważ, że nasz interpreter Python nadal działa, mamy niemodalne okno dialogowe. Tak więc, aby je zamknąć, możemy ''(oprócz kliknięcia ikony zamknięcia, oczywiście)'' wydać polecenie: |
|||
And our dialog will appear! Note that our Python interpreter is still working, we have a non-modal dialog. So, to close it, we can (apart from clicking its close icon, of course) issue: |
|||
{{Code|code= |
{{Code|code= |
||
d.hide() |
d.hide() |
||
}} |
}} |
||
== Sprawiamy, by nasze okno dialogowe robiło coś == |
|||
== Making our dialog do something == |
|||
Teraz, gdy możemy pokazywać i ukrywać nasze okno dialogowe, musimy tylko dodać ostatnią część: Sprawić, by coś robiło! Jeśli pobawisz się trochę Qt Designerem, szybko odkryjesz całą sekcję o nazwie "sygnały i sloty". Zasadniczo działa to w następujący sposób: elementy na widżetach ''(w terminologii Qt te elementy są same w sobie widżetami)'' mogą wysyłać sygnały. Sygnały te różnią się w zależności od typu widżetu. Na przykład przycisk może wysyłać sygnał po naciśnięciu i zwolnieniu. Sygnały te mogą być podłączone do slotów, które mogą być specjalnymi funkcjami innych widżetów ''(na przykład okno dialogowe ma slot "zamknij", do którego można podłączyć sygnał z przycisku zamykania)'' lub mogą być funkcjami niestandardowymi. Dokumentacja [http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/classes.html PyQt Reference] zawiera listę wszystkich widżetów qt, co mogą robić, jakie sygnały mogą wysyłać itd. |
|||
Now that we can show and hide our dialog, we just need to add one last part: To make it do something! If you play a bit with Qt designer, you'll quickly discover a whole section called "signals and slots". Basically, it works like this: elements on your widgets (in Qt terminology, those elements are themselves widgets) can send signals. Those signals differ according to the widget type. For example, a button can send a signal when it is pressed and when it is released. Those signals can be connected to slots, which can be special functionality of other widgets (for example a dialog has a "close" slot to which you can connect the signal from a close button), or can be custom functions. The [http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/classes.html PyQt Reference Documentation] lists all the qt widgets, what they can do, what signals they can send, etc... |
|||
To, co tutaj zrobimy, to utworzenie nowej funkcji, która utworzy płaszczyznę na podstawie wysokości i szerokości oraz podłączenie tej funkcji do sygnału naciśnięcia emitowanego przez nasz przycisk "Utwórz!". Zacznijmy więc od zaimportowania naszych modułów FreeCAD, umieszczając następującą linię na górze skryptu, gdzie już zaimportowaliśmy QtCore i QtGui: |
|||
What we will do here, is to create a new function that will create a plane based on height and width, and to connect that function to the pressed signal emitted by our "Create!" button. So, let's begin with importing our FreeCAD modules, by putting the following line at the top of the script, where we already import QtCore and QtGui: |
|||
{{Code|code= |
{{Code|code= |
||
import FreeCAD, Part |
import FreeCAD, Part |
||
}} |
}} |
||
Następnie dodajmy nową funkcję do naszej klasy Ui_Dialog: |
|||
{{Code|code= |
{{Code|code= |
||
def createPlane(self): |
def createPlane(self): |
||
Line 144: | Line 164: | ||
self.hide() |
self.hide() |
||
}} |
}} |
||
Następnie musimy poinformować Qt, aby podłączył przycisk do funkcji, umieszczając następującą linię tuż przed QtCore.QMetaObject.connectSlotsByName(Dialog): |
|||
{{Code|code= |
{{Code|code= |
||
QtCore.QObject.connect(self.create,QtCore.SIGNAL("pressed()"),self.createPlane) |
QtCore.QObject.connect(self.create,QtCore.SIGNAL("pressed()"),self.createPlane) |
||
}} |
}} |
||
To, jak widać, łączy sygnał pressed() naszego obiektu create ''(przycisk "Create!")'' ze slotem o nazwie createPlane, który właśnie zdefiniowaliśmy. To wszystko! Teraz, jako ostatni akcent, możemy dodać małą funkcję do tworzenia okna dialogowego, która będzie łatwiejsza do wywołania. Dodajmy ten kod poza klasą Ui_Dialog: |
|||
{{Code|code= |
{{Code|code= |
||
class plane(): |
class plane(): |
||
Line 157: | Line 177: | ||
self.d.show() |
self.d.show() |
||
}} |
}} |
||
''(Przypomnienie Pythona: metoda __init__ klasy jest automatycznie wykonywana za każdym razem, gdy tworzony jest nowy obiekt)''! |
|||
(Python reminder: the __init__ method of a class is automatically executed whenever a new object is created!) |
|||
Następnie, z FreeCAD, musimy tylko zrobić: |
|||
{{Code|code= |
{{Code|code= |
||
import mywidget |
import mywidget |
||
myDialog = mywidget.plane() |
myDialog = mywidget.plane() |
||
}} |
}} |
||
To wszystko... Teraz możesz spróbować różnych rzeczy, takich jak na przykład wstawianie widżetu do interfejsu FreeCAD ''(zobacz stronę [[Code_snippets/pl|wycinki kodu]])'' lub tworzenie znacznie bardziej zaawansowanych narzędzi niestandardowych, używając innych elementów na widżecie. |
|||
That's all Folks... Now you can try all kinds of things, like for example inserting your widget in the FreeCAD interface (see the [[Code snippets]] page), or making much more advanced custom tools, by using other elements on your widget. |
|||
== |
== Kompletny skrypt == |
||
To jest kompletny skrypt, dla porównania: |
|||
This is the complete script, for reference: |
|||
{{Code|code= |
{{Code|code= |
||
# Form implementation generated from reading ui file 'mywidget.ui' |
# Form implementation generated from reading ui file 'mywidget.ui' |
||
Line 239: | Line 259: | ||
}} |
}} |
||
<span id="More_examples"></span> |
|||
==More examples == |
|||
==Więcej przykładów== |
|||
* [[Dialog_creation_with_various_widgets| |
* [[Dialog_creation_with_various_widgets/pl|Tworzenie dialogów z różnymi widżetami]] with {{incode|QPushButton}}, {{incode|QLineEdit}}, {{incode|QCheckBox}}, {{incode|QRadioButton}}, and others. |
||
* [[Dialog_creation_reading_and_writing_files| |
* [[Dialog_creation_reading_and_writing_files/pl|Tworzenie dialogów odczyt i zapis plików]] with {{incode|QFileDialog}}. |
||
* [[Dialog_creation_setting_colors| |
* [[Dialog_creation_setting_colors/pl|Tworzenie okna dialogowego ustawienie kolorów]] with {{incode|QColorDialog}}. |
||
* [[Dialog_creation_image_and_animated_GIF| |
* [[Dialog_creation_image_and_animated_GIF/pl|Tworzenie dialogu grafika i animowany GIF]] with {{incode|QLabel}} and {{incode|QMovie}}. |
||
* [[PySide_usage_snippets|PySide |
* [[PySide_usage_snippets/pl|PySide przydatne wycinki]]. |
||
* [[Qt_Example/pl|Przykłady Qt]] |
|||
<span id="Relevant_links"></span> |
|||
== Relevant links == |
|||
==Istotne odnośniki internetowe== |
|||
* [[Manual:Creating interface tools]] |
* [[Manual:Creating interface tools/pl|Podręcznik:Tworzenie narzędzi interfejsu]] |
||
* [[Interface_creation_with_UI_files|Interface creation with UI files]] |
|||
{{Docnav/pl |
|||
|[[Interface_creation/pl|Tworzenie interfejsu]] |
|||
|[[License/pl|Licencja]] |
|||
}} |
|||
{{Powerdocnavi{{#translation:}}}} |
{{Powerdocnavi{{#translation:}}}} |
||
[[Category:Developer Documentation{{#translation:}}]] |
[[Category:Developer Documentation{{#translation:}}]] |
||
[[Category:Python Code{{#translation:}}]] |
[[Category:Python Code{{#translation:}}]] |
||
{{clear}} |
Latest revision as of 06:30, 6 April 2024
Wprowadzenie
Na tej stronie pokażemy, jak zbudować prosty interfejs graficzny za pomocą Qt Designer, oficjalnego narzędzia Qt do projektowania interfejsów. Przekonwertujemy okno dialogowe na kod Python, a następnie będzie używane wewnątrz FreeCAD. Zakładamy, że użytkownik wie, jak edytować i uruchamiać Python.
W tym przykładzie cały interfejs jest zdefiniowany w środowisku Python. Chociaż jest to możliwe w przypadku małych interfejsów, w przypadku większych interfejsów zaleca się ładowanie utworzonych plików .ui bezpośrednio do programu.
Dwie ogólne metody tworzenia interfejsów, poprzez włączenie interfejsu do pliku Python lub poprzez użycie plików .ui
.
Projektujemy okno dialogowe
W aplikacjach CAD zaprojektowanie dobrego interfejsu użytkownika (UI) jest bardzo ważne. Prawie wszystko, co użytkownik będzie robił, będzie odbywało się za pośrednictwem jakiegoś elementu interfejsu: czytanie okien dialogowych, naciskanie przycisków, wybieranie między ikonami itp. Dlatego bardzo ważne jest, aby dokładnie przemyśleć co chcesz zrobić, jak chcesz aby użytkownik postępował i jaki będzie przepływ pracy.
Istnieje kilka pojęć, które należy znać podczas projektowania interfejsu:
- Modalne/niemodalne okna dialogowe: Modalne okno dialogowe pojawia się przed ekranem, zatrzymując działanie głównego okna, zmuszając użytkownika do odpowiedzi na okno dialogowe, podczas gdy niemodalne okno dialogowe nie przerywa pracy w głównym oknie. W niektórych przypadkach pierwsze rozwiązanie jest lepsze, w innych nie.
- Określenie, co jest wymagane, a co opcjonalne: Upewnij się, że użytkownik wie, co musi zrobić. Oznacz wszystko odpowiednim opisem, użyj podpowiedzi itp.
- Oddzielanie poleceń od parametrów: Zazwyczaj robi się to za pomocą przycisków i pól wprowadzania tekstu. Użytkownik wie, że kliknięcie przycisku spowoduje akcję, podczas gdy zmiana wartości w polu tekstowym zmieni gdzieś parametr. Jednak w dzisiejszych czasach użytkownicy zwykle dobrze wiedzą, co jest przyciskiem, co jest polem wejściowym itp. Zestaw narzędzi interfejsu, którego używamy, Qt, jest najnowocześniejszym zestawem narzędzi i nie będziemy musieli się zbytnio martwić o wyjaśnianie rzeczy, ponieważ będą one już bardzo zrozumiałe same w sobie.
Tak więc, teraz, gdy dobrze zdefiniowaliśmy, co będziemy robić, nadszedł czas, aby otworzyć projektanta QT. Zaprojektujmy bardzo proste okno dialogowe, takie jak to:
Następnie użyjemy tego okna dialogowego w programie FreeCAD, aby utworzyć ładną prostokątną płaszczyznę. Może się okazać, że nie jest to zbyt przydatne do tworzenia ładnych prostokątnych płaszczyzn, ale łatwo będzie je później zmienić, aby robić bardziej złożone rzeczy. Po otwarciu Qt Designer wygląda następująco:
Tworzymy okno dialogowe
Qt Designer jest bardzo prosty w użyciu. Na lewym pasku znajdują się elementy, które można przeciągnąć na widżet. Po prawej stronie znajdują się panele właściwości wyświetlające wszystkie rodzaje edytowalnych właściwości wybranych elementów. Zacznijmy więc od utworzenia nowego widżetu.
- Wybieramy "Dialog bez przycisków", ponieważ nie chcemy domyślnych przycisków OK/Cancel.
- Potrzebujemy Etykiety. Etykiety to proste ciągi tekstowe, które pojawiają się na widżecie, aby poinformować użytkownika końcowego. Jeśli wybierzesz etykietę, zauważysz, że po prawej stronie pojawi się kilka właściwości, które możesz modyfikować, takich jak: styl czcionki, wysokość itp. Przeciągnijmy więc 3 oddzielne etykiety na nasz widżet:
- Jedna etykieta dla tytułu
- Kolejna etykieta do napisania "Wysokość"
- Kolejna etykieta do napisania "Szerokość"
- Potrzebujemy teraz LineEdits (a właściwie 2 z nich). Przeciągnij dwa z nich na widżet. LineEdits to pola tekstowe, które użytkownik końcowy może wypełnić. Potrzebujemy więc jednego LineEdit dla "Wysokość" i jednego dla "Szerokość". Tutaj również możemy edytować właściwości. Na przykład, dlaczego nie ustawić wartości domyślnej, powiedzmy na przykład: 1.00 dla każdego. W ten sposób, gdy użytkownik zobaczy okno dialogowe, obie wartości będą już wypełnione. Jeśli użytkownik będzie zadowolony, może bezpośrednio nacisnąć przycisk, oszczędzając cenny czas.
- Następnie dodajmy przycisk PushButton. Jest to przycisk, który użytkownik końcowy będzie musiał nacisnąć po wypełnieniu obu pól.
Uwaga: wybraliśmy tutaj bardzo proste kontrolki. Qt ma o wiele więcej opcji, na przykład można użyć Spinboxes zamiast LineEdits itp. Przyjrzyj się temu, co jest dostępne, zbadaj... na pewno będziesz miał inne pomysły.
To wszystko, co musimy zrobić w Qt Designer. Na koniec zmieńmy nazwy wszystkich elementów na prostsze, aby łatwiej było je zidentyfikować w naszych skryptach:
Konwersja naszego okna dialogowego do środowiska Python
Teraz zapiszmy gdzieś nasz widget. Zostanie on zapisany jako plik .ui, który z łatwością przekonwertujemy na skrypt Pythona za pomocą pyuic. Na Windowsie program pyuic jest dołączony do pyqt (do sprawdzenia), na linuksie prawdopodobnie będziesz musiał zainstalować go osobno z menedżera pakietów (na systemach opartych na debianie jest on częścią pakietu pyqt4-dev-tools). Aby dokonać konwersji, należy otworzyć okno terminala (lub okno wiersza polecenia w systemie Windows), przejść do miejsca, w którym zapisano plik .ui i wydać polecenie:
pyuic mywidget.ui > mywidget.py
W systemie Windows pyuic.py znajduje się w "C:\Python27\Lib\site-packages\PyQt4\uic\pyuic.py". Do konwersji należy utworzyć plik wsadowy o nazwie "compQt4.bat":
@"C:\Python27\python" "C:\Python27\Lib\site-packages\PyQt4\uic\pyuic.py" -x %1.ui > %1.py
W konsoli DOS wpisz bez rozszerzenia
compQt4 myUiFile
W systemie macOS można pobrać odpowiednią wersję (tę samą, która jest używana wewnętrznie w FreeCAD 0.19) QT i Pyside za pomocą następujących poleceń (wymagany program):
python3 -m pip install pyqt5
python3 -m pip install pySide2
Spowoduje to zainstalowanie uic w folderze "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/uic", a Designer w "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PySide2/Designer.app". Dla wygody można utworzyć link do uic w /usr/local/bin, aby móc go wywołać po prostu za pomocą uic -g python ... zamiast wpisywania całej ścieżki programu, oraz link do Designera, aby pobrać go w folderze Aplikacje na komputerze Mac za pomocą:
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
W Linuksie: do zrobienia.
Ponieważ FreeCAD stopniowo odchodził od PyQt po wersji 0.13, na rzecz PySide (Wybierz instalację PySide budowanie PySide), aby plik był oparty na PySide, musisz teraz użyć:
pyside-uic mywidget.ui -o mywidget.py
W systemie Windows plik uic.py znajduje się w katalogu "C:\Python27\Lib\site-packages\PySide\scripts\uic.py". Aby utworzyć plik wsadowy "compSide.bat":
@"C:\Python27\python" "C:\Python27\Lib\site-packages\PySide\scripts\uic.py" %1.ui > %1.py
W konsoli DOS wpisz bez rozszerzenia:
compSide myUiFile
W Linuksie: do zrobienia.
W niektórych systemach program nazywa się pyuic4 zamiast pyuic. Spowoduje to po prostu konwersję pliku .ui na skrypt Pythona. Jeśli otworzymy plik mywidget.py, jego zawartość jest bardzo przejrzysta:
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))
...
Jak widać, ma on bardzo prostą strukturę: tworzona jest klasa o nazwie Ui_Dialog, która przechowuje elementy interfejsu naszego widżetu. Ta klasa ma dwie metody, jedną do konfiguracji widżetu, a drugą do tłumaczenia jego zawartości, co jest częścią ogólnego mechanizmu Qt do tłumaczenia elementów interfejsu. Metoda konfiguracji po prostu tworzy, jeden po drugim, widżety tak, jak zdefiniowaliśmy je w Qt Designer i ustawia ich opcje tak, jak zdecydowaliśmy wcześniej. Następnie cały interfejs zostaje przetłumaczony, a na koniec sloty zostają połączone (o tym powiem później).
Możemy teraz utworzyć nowy widżet i użyć tej klasy do stworzenia jego interfejsu. Możemy już zobaczyć nasz widżet w akcji, umieszczając nasz plik mywidget.py w miejscu, w którym FreeCAD go znajdzie (w katalogu bin FreeCAD lub w dowolnym z podkatalogów Mod), a następnie w interpreterze python FreeCAD wydać polecenie:
from PySide import QtGui
import mywidget
d = QtGui.QWidget()
d.ui = mywidget.Ui_Dialog()
d.ui.setupUi(d)
d.show()
I pojawi się nasze okno dialogowe! Zauważ, że nasz interpreter Python nadal działa, mamy niemodalne okno dialogowe. Tak więc, aby je zamknąć, możemy (oprócz kliknięcia ikony zamknięcia, oczywiście) wydać polecenie:
d.hide()
Sprawiamy, by nasze okno dialogowe robiło coś
Teraz, gdy możemy pokazywać i ukrywać nasze okno dialogowe, musimy tylko dodać ostatnią część: Sprawić, by coś robiło! Jeśli pobawisz się trochę Qt Designerem, szybko odkryjesz całą sekcję o nazwie "sygnały i sloty". Zasadniczo działa to w następujący sposób: elementy na widżetach (w terminologii Qt te elementy są same w sobie widżetami) mogą wysyłać sygnały. Sygnały te różnią się w zależności od typu widżetu. Na przykład przycisk może wysyłać sygnał po naciśnięciu i zwolnieniu. Sygnały te mogą być podłączone do slotów, które mogą być specjalnymi funkcjami innych widżetów (na przykład okno dialogowe ma slot "zamknij", do którego można podłączyć sygnał z przycisku zamykania) lub mogą być funkcjami niestandardowymi. Dokumentacja PyQt Reference zawiera listę wszystkich widżetów qt, co mogą robić, jakie sygnały mogą wysyłać itd.
To, co tutaj zrobimy, to utworzenie nowej funkcji, która utworzy płaszczyznę na podstawie wysokości i szerokości oraz podłączenie tej funkcji do sygnału naciśnięcia emitowanego przez nasz przycisk "Utwórz!". Zacznijmy więc od zaimportowania naszych modułów FreeCAD, umieszczając następującą linię na górze skryptu, gdzie już zaimportowaliśmy QtCore i QtGui:
import FreeCAD, Part
Następnie dodajmy nową funkcję do naszej klasy Ui_Dialog:
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()
Następnie musimy poinformować Qt, aby podłączył przycisk do funkcji, umieszczając następującą linię tuż przed QtCore.QMetaObject.connectSlotsByName(Dialog):
QtCore.QObject.connect(self.create,QtCore.SIGNAL("pressed()"),self.createPlane)
To, jak widać, łączy sygnał pressed() naszego obiektu create (przycisk "Create!") ze slotem o nazwie createPlane, który właśnie zdefiniowaliśmy. To wszystko! Teraz, jako ostatni akcent, możemy dodać małą funkcję do tworzenia okna dialogowego, która będzie łatwiejsza do wywołania. Dodajmy ten kod poza klasą Ui_Dialog:
class plane():
def __init__(self):
self.d = QtGui.QWidget()
self.ui = Ui_Dialog()
self.ui.setupUi(self.d)
self.d.show()
(Przypomnienie Pythona: metoda __init__ klasy jest automatycznie wykonywana za każdym razem, gdy tworzony jest nowy obiekt)! Następnie, z FreeCAD, musimy tylko zrobić:
import mywidget
myDialog = mywidget.plane()
To wszystko... Teraz możesz spróbować różnych rzeczy, takich jak na przykład wstawianie widżetu do interfejsu FreeCAD (zobacz stronę wycinki kodu) lub tworzenie znacznie bardziej zaawansowanych narzędzi niestandardowych, używając innych elementów na widżecie.
Kompletny skrypt
To jest kompletny skrypt, dla porównania:
# 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()
Więcej przykładów
- Tworzenie dialogów z różnymi widżetami with
QPushButton
,QLineEdit
,QCheckBox
,QRadioButton
, and others. - Tworzenie dialogów odczyt i zapis plików with
QFileDialog
. - Tworzenie okna dialogowego ustawienie kolorów with
QColorDialog
. - Tworzenie dialogu grafika i animowany GIF with
QLabel
andQMovie
. - PySide przydatne wycinki.
- Przykłady Qt
Istotne odnośniki internetowe
- Tworzenie skryptów FreeCAD: Python, Wprowadzenie do środowiska Python, Poradnik: Tworzenie skryptów Python, Podstawy tworzenia skryptów FreeCAD
- Moduły: Moduły wbudowane, Jednostki miar, Ilość
- Środowiska pracy: Tworzenie Środowiska pracy, Polecenia Gui, Polecenia, Instalacja większej liczby Środowisk pracy
- Siatki i elementy: Skrytpy w Środowisku Siatek, v, Konwerska Mesh na Part, PythonOCC
- Obiekty parametryczne: Obiekty tworzone skryptami, Obsługa obrazu (Ikonka niestandardowa w widoku drzewa)
- Scenegraph: Coin (Inventor) scenegraph, Pivy
- Interfejs graficzny: Stworzenie interfejsu, Kompletne stworzenie interfejsu w środowisku Python (1, 2, 3, 4, 5), PySide, PySide examples początkujący, średniozaawansowany, zaawansowany
- Makrodefinicje: Makrodefinicje, Instalacja makrodefinicji
- Osadzanie programu: Osadzanie programu FreeCAD, Osadzanie GUI FreeCAD
- Pozostałe: Wyrażenia, Wycinki kodu, Funkcja kreślenia linii, Biblioteka matematyczna FreeCAD dla wektorów (deprecated)
- Węzły użytkowników: Centrum użytkownika, Centrum Power użytkowników, Centrum programisty