Manual:Creating interface tools/ru: Difference between revisions

From FreeCAD Documentation
(Created page with "* Теперь наш виджет готов, осталось убедиться в последней вещи. Поскольку FreeCAD должен иметь дост...")
(Updating to match new version of source page)
(26 intermediate revisions by 3 users not shown)
Line 1: Line 1:
<languages/>
{{Docnav/ru
|[[Manual:Creating parametric objects/ru|Creating parametric objects]]
|[[Manual:The Community/ru|The Community]]
|[[Manual:Introduction/ru|Manual start]]
|IconC=Crystal Clear manual.png
}}

{{Manual:TOC/ru}}
{{Manual:TOC/ru}}


Line 12: Line 20:
Тем не менее, для этого нужна запущенная консоль Python, и при запуске нашего кода как макроса мы не всегда уверены, что консоль Python работает на пользовательской машине.
Тем не менее, для этого нужна запущенная консоль Python, и при запуске нашего кода как макроса мы не всегда уверены, что консоль Python работает на пользовательской машине.


[https://ru.wikipedia.org/wiki/Графический_интерфейс_пользователя Графический интерфейс пользователя], или ГИП, GUI, то есть все части FreeCAD, отображаемые на экране (меню, панели инструментов, окно трёхмерного вида и так далее) как раз для этого: взаимодействия с пользователем. Интерфейс FreeCAD построен на [https://ru.wikipedia.org/wiki/Qt Qt], широко распространённая библиотека ГИП, предоставляющая огромный набор инструментов вроде диалоговых боксов, кнопок, панелей, меток, полей ввода, или ниспадающих меню (все они в целом называются "виджетами").
[https://ru.wikipedia.org/wiki/Графический_интерфейс_пользователя Графический интерфейс пользователя], или ГИП, GUI, то есть все части FreeCAD, отображаемые на экране (меню, панели инструментов, окно трёхмерного вида и так далее) как раз для этого: взаимодействия с пользователем. Интерфейс FreeCAD построен на [https://ru.wikipedia.org/wiki/Qt Qt], широко распространённая библиотека ГИП, предоставляющая широкий набор инструментов вроде диалоговых боксов, кнопок, панелей, меток, полей ввода, или ниспадающих меню. В целом они все называются "виджетами".


Инструменты Qt очень легко использовать из Python, благодаря модулю Python, называемому [https://ru.wikipedia.org/wiki/PySide Pyside] (есть и другие модули Python для взаимодействия с Qt из Python). Этот модуль обеспечивает создание и взаимодействовать с виджетами, считывать что пользователи делают с ними (что вписывают в текстовые боксы) или делать что-то когда, например, нажимается кнопка.
Инструменты Qt очень легко использовать из Python, благодаря модулю Python, называемому [https://ru.wikipedia.org/wiki/PySide Pyside] (есть и другие модули Python для взаимодействия с Qt из Python). Этот модуль обеспечивает создание и взаимодействовать с виджетами, считывать что пользователи делают с ними (что вписывают в текстовые боксы) или делать что-то когда, например, нажимается кнопка.
Line 22: Line 30:
[[Image:Exercise_python_07.jpg]]
[[Image:Exercise_python_07.jpg]]


Начнём с создания виджета. Запустите Qt Creator, затем меню '''File -> New File or Project -> Files and Classes -> Qt -> Qt Designer Form -> Dialog without buttons'''. Кликните '''Next''', задайте имя файла для сохранения, кликните '''Next''', оставьте все поля проекта со значениями по умолчанию ("<none>"), затем '''Create'''. Система задач FreeCAD автоматически добавит кнопки OK/Cancel, поэтому мы выбрали здесь диалог без кнопок.
Начнём с создания виджета. Запустите Qt Creator, затем меню '''File New File or Project Files and Classes Qt Qt Designer Form Dialog without buttons'''. Кликните '''Next''', задайте имя файла для сохранения, кликните '''Next''', оставьте все поля проекта со значениями по умолчанию ("<none>"), затем '''Create'''. Система задач FreeCAD автоматически добавит кнопки OK/Cancel, поэтому мы выбрали здесь диалог без кнопок.


[[Image:Exercise_python_06.jpg]]
[[Image:Exercise_python_06.jpg]]


* Найдём в списке на левой панели '''Label''', и перетащим её на полотно нашего виджета. Дважды кликнем размещённую метку, и изменим её текст на '''Length'''.
* Найдём в списке на левой панели '''Label''', и перетащим её на полотно нашего виджета. Дважды кликнем размещённую метку, и изменим её текст на '''Length'''.
* Правым кликом на холсте виджета выберем '''Lay out-> Lay out in a Grid'''. Это превратит наш виджет в сетку с пока ещё только одной ячейкой, занятой нашей первой меткой. Мы теперь можем добавить следующий элемент слева, справа, сверху или снизу от нашей первой метки, и сетка автоматически расширится.
* Правым кликом на холсте виджета выберем '''Lay out→ Lay out in a Grid'''. Это превратит наш виджет в сетку с пока ещё только одной ячейкой, занятой нашей первой меткой. Мы теперь можем добавить следующий элемент слева, справа, сверху или снизу от нашей первой метки, и сетка автоматически расширится.
* Добавим ещё две метки под первой, и изменим их текст на Width и Height:
* Добавим ещё две метки под первой, и изменим их текст на Width и Height:


[[Image:Exercise_python_08.jpg]]
[[Image:Exercise_python_08.jpg]]


* Теперь поместим 3 виджета '''Double Spin Box''' вблизи наших меток Length, Width и Height. Для каждой из них в нижней левой панели, которые показывают доступные установки для выбранных виджетов, найдите '''Suffix''' и установите суффикс в '''mm'''. У FreeCADа есть более совершенный виджет, который может поддерживать различные единицы, но он не доступен в Qt Creator по умолчанию (но может быть [[CompileOnUnix/ru#Qt_designer_plugin|вкомпилирован]]), так что теперь мы будем использовать станданртный Double Spin Box, и мы добавим суффикс "mm", чтобы пользователи знали, в каких единицах они работают:
* Теперь поместим 3 виджета '''Double Spin Box''' вблизи наших меток Length, Width и Height. Для каждой из них в нижней правой панели, которые показывают доступные установки для выбранных виджетов, найдите '''Suffix''' и установите суффикс в '''mm'''. У FreeCADа есть более совершенный виджет, который может поддерживать различные единицы, но он не доступен в Qt Creator по умолчанию (но может быть [[Compile_on_Linux/Unix/ru#Qt_designer_plugin|вкомпилирован]]), так что теперь мы будем использовать станданртный Double Spin Box, и мы добавим суффикс "mm", чтобы пользователи знали, в каких единицах они работают:


[[Image:Exercise_python_09.jpg]]
[[Image:Exercise_python_09.jpg]]
Line 40: Line 48:
[[Image:Exercise_python_10.jpg]]
[[Image:Exercise_python_10.jpg]]


* Save the file, you can now close Qt Creator, the rest will be done in Python.
* Сохраните файл, и можете закрыть Qt Creator, остальное будет сделано в Python.
* Откройте FreeCAD и создайте новый макрос из меню '''Макросы → Макрос'''
* Open FreeCAD and create a new macro from menu '''Macro -> Macros -> Create'''
* Вставьте следующий код. Убедитесь, что Вы изменили путь к файлу на тот, где вы сохранили файл .ui, созданный в QtCreator:
* Paste the following code. Make sure you change the file path to match where you saved the .ui file created in QtCreator:


{{Code|code=
import FreeCAD,FreeCADGui,Part
import FreeCAD,FreeCADGui,Part
# CHANGE THE LINE BELOW
# CHANGE THE LINE BELOW
path_to_ui = "C:\Users\yorik\Documents\dialog.ui"
path_to_ui = "C:\Users\yorik\Documents\dialog.ui"
class BoxTaskPanel:
class BoxTaskPanel:
def __init__(self):
def __init__(self):
# this will create a Qt widget from our ui file
# this will create a Qt widget from our ui file
self.form = FreeCADGui.PySideUic.loadUi(path_to_ui)
self.form = FreeCADGui.PySideUic.loadUi(path_to_ui)
def accept(self):
def accept(self):
length = self.form.BoxLength.value()
length = self.form.BoxLength.value()
width = self.form.BoxWidth.value()
width = self.form.BoxWidth.value()
height = self.form.BoxHeight.value()
height = self.form.BoxHeight.value()
if (length == 0) or (width == 0) or (height == 0):
if (length == 0) or (width == 0) or (height == 0):
print("Error! None of the values can be 0!")
print("Error! None of the values can be 0!")
# we bail out without doing anything
# we bail out without doing anything
return
return
box = Part.makeBox(length,width,height)
box = Part.makeBox(length,width,height)
Part.show(box)
Part.show(box)
FreeCADGui.Control.closeDialog()
FreeCADGui.Control.closeDialog()
panel = BoxTaskPanel()
panel = BoxTaskPanel()
FreeCADGui.Control.showDialog(panel)
FreeCADGui.Control.showDialog(panel)
}}


In the code above, we used a convenience function (PySideUic.loadUi) from the FreeCADGui module. That function loads a .ui file, creates a Qt Widget from it, and maps names, so we can easily access the subwidget by their names (ex: self.form.BoxLength).
В вышеуказанном коде мы использовали общую функцию (PySideUic.loadUi) из модуля FreeCADGui. Эта функция загружает файл .ui, создаёт из него виджет Qt, и сопоставляет имена, так что мы можем легко добираться до подвиджетов по их именам (пример: self.form.BoxLength).


Функция "accept" это так же удобство, предлагаемое Qt. Когда в диалоге есть кнопка "OK" (которая есть по умолчанию при использовании панели задач FreeCAD), любая функция, называемая "accept" автоматически выполняется когда нажата кнопка "OK". Соответственно, Вы можете так же добавить функцию "reject", которая будет исполняться когда будет нажата кнопка "Cancel". В нашем случае мы опустили эту функцию, так что нажатие "Cancel" обрабатывается по умолчанию (ничего не делает и закрывает диалог).
The "accept" function is also a convenience offered by Qt. When there is an "OK" button in a dialog (which is the case by default when using the FreeCAD Tasks panel), any function named "accept" will automatically be executed when the "OK" button is pressed. Similarly, you can also add a "reject" function which gets executed when the "Cancel" button is pressed. In our case, we omitted that function, so pressing "Cancel" will do the default behaviour (do nothing and close the dialog).


Если мы создадим функции accept или reject, их действие по умолчанию (ничего не делать и закрыть) больше не сработает. Так что нам надо закрывать панель Task самостоятельно. Это делается с помощью:
If we implement any of the accept or reject functions, their default behaviour (do nothing and close) will not occur anymore. So we need to close the Task panel ourselves. This is done with:


{{Code|code=
FreeCADGui.Control.closeDialog()
FreeCADGui.Control.closeDialog()
}}


Once we have our BoxTaskPanel that has 1- a widget called "self.form" and 2- if needed, accept and reject functions, we can open the task panel with it, which is done with these two last lines:
Когда у нас есть BoxTaskPanel, в которой: 1- виджет "self.form", и 2- при необходимости функции accept и reject, мы можем открыть с её помощью панель задач, что делается этими двумя последними строчками:


{{Code|code=
panel = BoxTaskPanel()
panel = BoxTaskPanel()
FreeCADGui.Control.showDialog(panel)
FreeCADGui.Control.showDialog(panel)
}}


Заметьте, что создаваемый PySideUic.loadUi виджет не специффичен для FreeCAD, это стандартный виджет Qt, который может использоваться в других инструментах Qt. Например, мы можем показывать отдельное диалоговое окно с его помощью. Попробуем это в консоли Python FreeCADа (разумеется, используя правильный путь к вашему файлу .ui):
Note that the widget created by PySideUic.loadUi is not specific to FreeCAD, it is a standard Qt widget which can be used with other Qt tools. For example, we could have shown a separate dialog box with it. Try this in the Python Console of FreeCAD (using the correct path to your .ui file of course):


{{Code|code=
from PySide import QtGui
from PySide import QtGui
w = FreeCADGui.PySideUic.loadUi("C:\Users\yorik\Documents\dialog.ui")
w = FreeCADGui.PySideUic.loadUi("C:\Users\yorik\Documents\dialog.ui")
w.show()
w.show()
}}


Разумеется, мы не добавляем в наш диалог никакую кнопку "OK" или "Cancel", поскольку сделан для использования из панели Task FreeCADа, которая содержит эти кнопки. Так что этот диалог нельзя закрыть (кроме как нажав кнопку закрытия окна). Но функция show() создаёт немодальный диалог, то есть он не блокирует остальной интерфейс. Поэтому, когда диалог всё ещё открыт, мы можем читать значения полей:
Of course we didn't add any "OK" or "Cancel" button to our dialog, since it was made to be used from the FreeCAD Task panel, which already provides such buttons. So there is no way to close the dialog (other than pressing its Window Close button). But the function show() creates a non-modal dialog, which means it doesn't block the rest of the interface. So, while our dialog is still open, we can read the values of the fields:


{{Code|code=
w.BoxHeight.value()
w.BoxHeight.value()
}}


Это очень полезно для тестирования.
This is very useful for testing.


Finally, don't forget there is much more documentation about using Qt widgets on the FreeCAD Wiki, in the [[Power_users_hub|Python Scripting]] section, which contains a [[Dialog_creation|dialog creation tutorial]], a special 3-part [[PySide|PySide tutorial]] that covers the subject extensively.
В итоге, не забудьте, что в FreeCAD Wiki гораздо больше документации об использовании виджетов Qt, в секции [[Power_users_hub/ru|Python Scripting]], которая содержит [[Dialog_creation/ru|руководство по созданию диалогов]], специальное [[PySide/ru|руководство по PySide]], которое шире описывает тему.


== Связанные ссылки ==
'''Читать далее'''
* [https://en.wikipedia.org/wiki/Qt_Creator Документация Qt Creator]

* [https://en.wikipedia.org/wiki/Qt_Creator Qt Creator]
* [https://www.qt.io/ide/ Установка Qt Creator]
* [https://www.qt.io/ide/ Установка Qt Creator]
* [[Power_users_hub/ru|Документация по скриптам на Python]]
* [[Power_users_hub/ru|Документация по скриптам на Python в FreeCAD]]
* [[Dialog_creation/ru|Учебник создания диалогов]]
* [[Dialog_creation/ru|Учебник создания диалогов FreeCAD]]
* [[PySide/ru|Учебник PySide]]
* [[PySide/ru|Учебник PySide для FreeCAD]]
* [http://srinikom.github.io/pyside-docs/index.html Документация PySide]
* [http://srinikom.github.io/pyside-docs/index.html Документация PySide]


{{Docnav/ru
<languages/>
|[[Manual:Creating parametric objects/ru|Creating parametric objects]]
|[[Manual:The Community/ru|The Community]]
|[[Manual:Introduction/ru|Manual start]]
|IconC=Crystal Clear manual.png
}}

{{Powerdocnavi{{#translation:}}}}
[[Category:Developer Documentation{{#translation:}}]]
[[Category:Python Code{{#translation:}}]]
{{clear}}

Revision as of 19:42, 23 August 2020

Other languages:

В последних двух главах мы видели как создать геометрию Part и создавать параметрический объекты. Чтобы получить полный контроль за FreeCAD, осталось одно: создание инструментов, взаимодействующими с пользователем.

В большинстве случаев не стоит подвергать пользователя испытанию, когда объект конструируется с нулевыми значениями, как мы делали с прямоугольником в предыдущей главе, и затем спрашивать пользователя заполнить значения Height и Width в панели Properties. Это работает для очень малого числа объектов, но становится утомительным когда надо создать их во множестве. Лучше иметь возможность задавать Height и Width при создании прямоугольника.

Python предоставляет базовые инструменты для ввода пользовательского текста на экране:

text = raw_input("Height of the rectangle?")
print("The entered height is ",text)

Тем не менее, для этого нужна запущенная консоль Python, и при запуске нашего кода как макроса мы не всегда уверены, что консоль Python работает на пользовательской машине.

Графический интерфейс пользователя, или ГИП, GUI, то есть все части FreeCAD, отображаемые на экране (меню, панели инструментов, окно трёхмерного вида и так далее) как раз для этого: взаимодействия с пользователем. Интерфейс FreeCAD построен на Qt, широко распространённая библиотека ГИП, предоставляющая широкий набор инструментов вроде диалоговых боксов, кнопок, панелей, меток, полей ввода, или ниспадающих меню. В целом они все называются "виджетами".

Инструменты Qt очень легко использовать из Python, благодаря модулю Python, называемому Pyside (есть и другие модули Python для взаимодействия с Qt из Python). Этот модуль обеспечивает создание и взаимодействовать с виджетами, считывать что пользователи делают с ними (что вписывают в текстовые боксы) или делать что-то когда, например, нажимается кнопка.

В Qt так же есть другой интересный инструмент, называемый Qt Designer, полностью встроенный в большое приложение Qt Creator. Он позволяет проектировать диалоговые боксы и интерфейсные панели графически, вместо того чтобы делать это вручную. В этой главе мы будем использовать Qt Creator для проектирование панельного виджета, который использует панель Task FreeCAD. Так что Вам надо скачать и установить Qt Creator с их официальной страницы, если Вы на Windows или Mac (в Linux он обычно доступен из менеджера приложений).

В следующем примере мы сначала с помощью Qt Creator создадим панель, которая будет запрашивать длину, ширину и высоту, затем создадим вокруг неё класс Python, который читает введённые значения, и создадим куб с данными размерами. Класс Python затем будет использоваться FreeCAD для показа и управления панели задач:

Начнём с создания виджета. Запустите Qt Creator, затем меню File → New File or Project → Files and Classes → Qt → Qt Designer Form → Dialog without buttons. Кликните Next, задайте имя файла для сохранения, кликните Next, оставьте все поля проекта со значениями по умолчанию ("<none>"), затем Create. Система задач FreeCAD автоматически добавит кнопки OK/Cancel, поэтому мы выбрали здесь диалог без кнопок.

  • Найдём в списке на левой панели Label, и перетащим её на полотно нашего виджета. Дважды кликнем размещённую метку, и изменим её текст на Length.
  • Правым кликом на холсте виджета выберем Lay out→ Lay out in a Grid. Это превратит наш виджет в сетку с пока ещё только одной ячейкой, занятой нашей первой меткой. Мы теперь можем добавить следующий элемент слева, справа, сверху или снизу от нашей первой метки, и сетка автоматически расширится.
  • Добавим ещё две метки под первой, и изменим их текст на Width и Height:

  • Теперь поместим 3 виджета Double Spin Box вблизи наших меток Length, Width и Height. Для каждой из них в нижней правой панели, которые показывают доступные установки для выбранных виджетов, найдите Suffix и установите суффикс в mm. У FreeCADа есть более совершенный виджет, который может поддерживать различные единицы, но он не доступен в Qt Creator по умолчанию (но может быть вкомпилирован), так что теперь мы будем использовать станданртный Double Spin Box, и мы добавим суффикс "mm", чтобы пользователи знали, в каких единицах они работают:

  • Теперь наш виджет готов, осталось убедиться в последней вещи. Поскольку FreeCAD должен иметь доступ к нему и читать значения Length, Width и Height, нам надо дать этим виджетам подходящие имена, чтобы мы могли легко получить их из FreeCAD. Кликните каждый из этих полей ввода, и в верхнем правом окне дважды кликните их Object Name, и измените его во что-то лёгкое для запоминания, например: BoxLength, BoxWidth и BoxHeight:

  • Сохраните файл, и можете закрыть Qt Creator, остальное будет сделано в Python.
  • Откройте FreeCAD и создайте новый макрос из меню Макросы → Макрос
  • Вставьте следующий код. Убедитесь, что Вы изменили путь к файлу на тот, где вы сохранили файл .ui, созданный в QtCreator:
import FreeCAD,FreeCADGui,Part
 
# CHANGE THE LINE BELOW
path_to_ui = "C:\Users\yorik\Documents\dialog.ui"
 
class BoxTaskPanel:
   def __init__(self):
       # this will create a Qt widget from our ui file
       self.form = FreeCADGui.PySideUic.loadUi(path_to_ui)
 
   def accept(self):
       length = self.form.BoxLength.value()
       width = self.form.BoxWidth.value()
       height = self.form.BoxHeight.value()
       if (length == 0) or (width == 0) or (height == 0):
           print("Error! None of the values can be 0!")
           # we bail out without doing anything
           return
       box = Part.makeBox(length,width,height)
       Part.show(box)
       FreeCADGui.Control.closeDialog()
        
panel = BoxTaskPanel()
FreeCADGui.Control.showDialog(panel)

В вышеуказанном коде мы использовали общую функцию (PySideUic.loadUi) из модуля FreeCADGui. Эта функция загружает файл .ui, создаёт из него виджет Qt, и сопоставляет имена, так что мы можем легко добираться до подвиджетов по их именам (пример: self.form.BoxLength).

Функция "accept" это так же удобство, предлагаемое Qt. Когда в диалоге есть кнопка "OK" (которая есть по умолчанию при использовании панели задач FreeCAD), любая функция, называемая "accept" автоматически выполняется когда нажата кнопка "OK". Соответственно, Вы можете так же добавить функцию "reject", которая будет исполняться когда будет нажата кнопка "Cancel". В нашем случае мы опустили эту функцию, так что нажатие "Cancel" обрабатывается по умолчанию (ничего не делает и закрывает диалог).

Если мы создадим функции accept или reject, их действие по умолчанию (ничего не делать и закрыть) больше не сработает. Так что нам надо закрывать панель Task самостоятельно. Это делается с помощью:

FreeCADGui.Control.closeDialog()

Когда у нас есть BoxTaskPanel, в которой: 1- виджет "self.form", и 2- при необходимости функции accept и reject, мы можем открыть с её помощью панель задач, что делается этими двумя последними строчками:

panel = BoxTaskPanel()
 FreeCADGui.Control.showDialog(panel)

Заметьте, что создаваемый PySideUic.loadUi виджет не специффичен для FreeCAD, это стандартный виджет Qt, который может использоваться в других инструментах Qt. Например, мы можем показывать отдельное диалоговое окно с его помощью. Попробуем это в консоли Python FreeCADа (разумеется, используя правильный путь к вашему файлу .ui):

from PySide import QtGui
 w = FreeCADGui.PySideUic.loadUi("C:\Users\yorik\Documents\dialog.ui")
 w.show()

Разумеется, мы не добавляем в наш диалог никакую кнопку "OK" или "Cancel", поскольку сделан для использования из панели Task FreeCADа, которая содержит эти кнопки. Так что этот диалог нельзя закрыть (кроме как нажав кнопку закрытия окна). Но функция show() создаёт немодальный диалог, то есть он не блокирует остальной интерфейс. Поэтому, когда диалог всё ещё открыт, мы можем читать значения полей:

w.BoxHeight.value()

Это очень полезно для тестирования.

В итоге, не забудьте, что в FreeCAD Wiki гораздо больше документации об использовании виджетов Qt, в секции Python Scripting, которая содержит руководство по созданию диалогов, специальное руководство по PySide, которое шире описывает тему.

Связанные ссылки