Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
470 / 103 / 26
Регистрация: 28.02.2013
Сообщений: 500
1

Просьба о рецензировании кода формы PyQt5

01.07.2021, 09:54. Показов 771. Ответов 10
Метки нет (Все метки)

Добрый день! Просьба о рецензировании кода Форма сама по себе работает, просто хочется услышать стороннее мнение по оформлению кода, может лишнего чего пишу или не так оформляю...

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
import sys
import os
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import win32com.client
from pathlib import Path
 
 
#local import
from evaporation import class_evaporation_liguid
 
class Calc_GUI(QWidget):
   def __init__(self):
       super().__init__()
       self.initUI()
       # запустим эксель
       self.Excel = win32com.client.Dispatch("Excel.Application")
       self.wb = self.Excel.Workbooks.Add()
       self.Excel.Visible = 1
       self.sheet = self.wb.ActiveSheet
       #создадим заголовки таблицы (row,col)
       self.sheet.Cells(1, 1).value = 'Мол.масса, кг/кмоль'
       self.sheet.Cells(2, 1).value = 'Pн, кПа'
       self.sheet.Cells(3, 1).value = 'S, м2'
       self.sheet.Cells(4, 1).value = 'Мж, кг'
       self.sheet.Cells(5, 1).value = 't, c'
       self.sheet.Cells(6, 1).value = 'Мисп, кг'
       self.sheet.Range("A1").ColumnWidth = 20
 
 
   def initUI(self):
       # Заголовок и иконка для GUI
       self.setWindowTitle('Расчет испарения вещества (СП 12.13130-2009)')
       self.setWindowIcon(QIcon(str(Path(os.getcwd()).parents[0]) +'/ico/calc_ico.png'))
       #  Создаем валидаторы для полей ввода
       onlyInt = QIntValidator()  # only int
       onlyDouble = QDoubleValidator()  # only float
 
       # создаем сетку из двух колонок
       # окно для текста help
       # окно для ввода данных
       grid = QGridLayout(self)
       grid.setColumnStretch(0, 1)
       grid.setColumnStretch(1, 1)
 
 
       # создаем окошки для ввода данных
       self.molecular_weight = QLineEdit()               #Мол.масса, кмоль/кг
       self.molecular_weight.setValidator(onlyDouble)
       self.molecular_weight.setPlaceholderText("Мол.масса, кмоль/кг")
 
 
       self.vapor_pressure = QLineEdit()               # Давление пара, кПа
       self.vapor_pressure.setValidator(onlyDouble)
       self.vapor_pressure.setPlaceholderText("Давление пара, кПа")
 
       self.spill_area = QLineEdit()               # Площадь пролива, м2
       self.spill_area.setValidator(onlyDouble)
       self.spill_area.setPlaceholderText("Площадь пролива, м2")
 
       self.max_mass = QLineEdit()               # Макс.масса вещества, кг
       self.max_mass.setValidator(onlyDouble)
       self.max_mass.setPlaceholderText("Макс.масса вещества, кг")
 
       self.time = QLineEdit()               # Время испарения, с
       self.time.setValidator(onlyDouble)
       self.time.setPlaceholderText("Время испарения, с")
 
       #  создаем радио кнопки для выбора действия
       self.write_excel = QRadioButton('Записать в Excel')
       self.write_excel.setChecked(True)
       self.plot_graph = QRadioButton('Построить график испарения')
       # создаем кнопку расчета которая на основе радио кнопок
       # произведет нужный расчет или построит график
       self.btn_calc = QPushButton("Расчет")
       self.btn_calc.clicked.connect(self.btn_calc_func)
       # основно текст help окна
       self.help_txt = QTextEdit("<b>СП 12.13130-2009 </b><br>"
                                 "<b>Основные исходные данные:</b><br>"
                                 "- Мол.масса, кмоль/кг<br>"
                                 "- Давление пара, кПа<br>"
                                 "- Площадь пролива, м2 <br>"
                                 "- Макс.масса вещества, кг <br>"
                                 "- Время испарения, с <br>"
                                 "<b>Основные выходные данные:</b><br>"
                                 "- Расчет испарения в Excel<br>"
                                 "- График испарения вещества<br>")
       self.help_txt.setReadOnly(True)
 
 
       # упаковываем в контейнер и в сетку
       vbox = QVBoxLayout(self)
       vbox.setContentsMargins(0, 0, 0, 0)
       box = QGroupBox(self)
       vbox.addWidget(self.molecular_weight)
       vbox.addWidget(self.vapor_pressure)
       vbox.addWidget(self.spill_area)
       vbox.addWidget(self.max_mass)
       vbox.addWidget(self.time)
       vbox.addWidget(self.write_excel)
       vbox.addWidget(self.plot_graph)
       vbox.addWidget(self.btn_calc)
       box.setLayout(vbox)
 
       vbox_help = QVBoxLayout(self)
       vbox_help.setContentsMargins(0, 0, 0, 0)
       box_help = QGroupBox(self)
       vbox_help.addWidget(self.help_txt)
       box_help.setLayout(vbox_help)
 
 
       verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
 
       grid.addWidget(box_help, 0, 0, -1, 1)
       grid.addWidget(box, 0, 1, 1, 1)
       grid.addItem(verticalSpacer, 1, 1, 1, 1)
 
       self.setLayout(grid)
 
       self.move(300, 200)
       self.show()
 
 
 
   def btn_calc_func(self):
       # Получить значения из полей
       molecular_weight = str(self.molecular_weight.displayText())
       vapor_pressure = str(self.vapor_pressure.displayText())
       spill_area = str(self.spill_area.displayText())
       max_mass = str(self.max_mass.displayText())
       time = str(self.time.displayText())
       # замена разделителей если вдруг запятая
       molecular_weight = molecular_weight.replace(",", ".")
       vapor_pressure = vapor_pressure.replace(",", ".")
       spill_area = spill_area.replace(",", ".")
       max_mass = max_mass.replace(",", ".")
       time = time.replace(",", ".")
 
       # Проверка заполнения полей, что бы не было пустым,
       # пока поля не будут заполнены никакие расчеты произведены не будут
       check_filling = [molecular_weight, vapor_pressure, spill_area, max_mass, time]
       if "" in check_filling:
           msg = QMessageBox(self)
           msg.setIcon(QMessageBox.Warning)
           msg.setWindowTitle("Информация")
           msg.setText("Указананы не все исходные данные!")
           msg.exec()
           return
 
       # превращаем переменные в числа после
       # считывания с полей ввода
       molecular_weight = float(molecular_weight)
       vapor_pressure = float(vapor_pressure)
       spill_area = float(spill_area)
       max_mass = float(max_mass)
       time = float(time)
       # смотря какой check нажат рисуем график/заполняем excel
       if self.write_excel.isChecked():
           # запишем данные в эксель
           sheet = self.wb.ActiveSheet
           mass = class_evaporation_liguid.Evapor_liqud().evapor_liguid(molecular_weight, vapor_pressure, spill_area, max_mass, time)
 
           res_list = []
           res_list.append(molecular_weight)
           res_list.append(vapor_pressure)
           res_list.append(spill_area)
           res_list.append(max_mass)
           res_list.append(time)
           res_list.append(mass)
 
           # ищем пустой столбец для записи в файле экселя
           i = 1
           while i < 1000:
               # т.е. строка постоянно 1, а столбец мы ищем перебором
               val = sheet.Cells(1, i).value
               if val == None:
                   break
               i = i + 1
           # когда мы нашли пустой столбец
           # нам в цикле нужно его заполнить
           # данными из списка radius_CZA
           k = 1
           for rec in res_list:
               sheet.Cells(k, i).value = rec
               k = k + 1
 
       elif self.plot_graph.isChecked():
           # нужно построить график на основании данных которые
           # есть в полях
           class_evaporation_liguid.Evapor_liqud().evapor_plot(molecular_weight,vapor_pressure,spill_area,max_mass)
 
 
   def closeEvent(self, e):
       """
       Функция закрытия окна с дополнительным диалогом
       на закрытие файла (да/нет)
       """
       result = QMessageBox.question(self, "Подтверждение закрытия окна",
                                     "Вы действительно хотите закрыть окно? Excel не будет сохранен.",
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
       if result == QMessageBox.Yes:
            self.wb.Close(SaveChanges=False)
               # Закроем COM объект
            self.Excel.Quit()
            e.accept()
            QWidget.closeEvent(self, e)
       else:
            e.ignore()
 
def my_excepthook(type, value, tback):
   #  функция отлова ошибок на PyQt5
   QMessageBox.critical(
       window, "CRITICAL ERROR", str(value),
       QMessageBox.Cancel
   )
 
   sys.__excepthook__(type, value, tback)
 
 
sys.excepthook = my_excepthook
 
 
if __name__ == '__main__':
   app = QApplication(sys.argv)
   ex = Calc_GUI()
   sys.exit(app.exec_())
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.07.2021, 09:54
Ответы с готовыми решениями:

Масштабирование размеров формы PYQT5
Доброго дня! Проблема такова. Создаю форму в pyQdesigner размерами 1024х768(ФИКСИРОВАНО). Вроде...

Просьба уточнить часть кода.
Доброго дна. Хотел бы уточнить что выполняет строка: Ranch-&gt;Fly(); Код функции: ...

Просьба описать код точнее выполнение кода в программе
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics,...

Все методы и атрибуты PyQt5.QtGui PyQt5.Qtwdigets и QtCore
На официальной документации модуля я не нашёл все методы и атрибуты PyQt5. может дадите источник со...

10
Модератор
Эксперт Python
1647 / 999 / 362
Регистрация: 21.02.2017
Сообщений: 2,894
Записей в блоге: 1
01.07.2021, 10:47 2
Михалыч,

1) У каждого виджета должен быть родитель (кроме главного окна).
2) Зачем использовать QLineEdit и прикреплять валидаторы, если есть готовые виджеты? (QDoubleSpinEdit, QSpinEdit отпадет надобность проверять запятые и прочие вещи, значения будут сразу в нужном типе данных.)
3) У QGridLayout есть методы чтобы устанавливать space-item'ы.
4) В MessageBox, можно все параметры сразу инициализировать, а не вызывать методы после.

Добавлено через 42 секунды
5) Скролящийся код.
1
470 / 103 / 26
Регистрация: 28.02.2013
Сообщений: 500
01.07.2021, 11:07  [ТС] 3
Цитата Сообщение от Fudthhh Посмотреть сообщение
1) У каждого виджета должен быть родитель (кроме главного окна).
Я понимаю примерно, про что вы говорите. Но как это должно выглядеть? Если можно небольшой пример приведите, пожалуйста. Так сказать для наглядности
Цитата Сообщение от Fudthhh Посмотреть сообщение
2) Зачем использовать QLineEdit и прикреплять валидаторы, если есть готовые виджеты? (QDoubleSpinEdit, QSpinEdit отпадет надобность проверять запятые и прочие вещи, значения будут сразу в нужном типе данных.)
Согласен. Переделаю)
Цитата Сообщение от Fudthhh Посмотреть сообщение
3) У QGridLayout есть методы чтобы устанавливать space-item'ы.
Почитаю)
Цитата Сообщение от Fudthhh Посмотреть сообщение
5) Скролящийся код.
Это как?) Не могли бы вы дать пояснение?

Добавлено через 6 минут
Цитата Сообщение от Fudthhh Посмотреть сообщение
4) В MessageBox, можно все параметры сразу инициализировать, а не вызывать методы после.
Это вы про этот кусок?
Python
1
2
3
4
5
6
7
       if "" in check_filling:
           msg = QMessageBox(self)
           msg.setIcon(QMessageBox.Warning)
           msg.setWindowTitle("Информация")
           msg.setText("Указананы не все исходные данные!")
           msg.exec()
           return
0
Модератор
Эксперт Python
1647 / 999 / 362
Регистрация: 21.02.2017
Сообщений: 2,894
Записей в блоге: 1
01.07.2021, 11:24 4
Михалыч, пример для родителей и QMessageBox:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from PySide2 import QtWidgets, QtCore, QtGui
 
 
class Example(QtWidgets.QWidget):
    def __init__(self, parent: QtWidgets.QWidget = None):
        QtWidgets.QWidget.__init__(self, parent)
 
        self.line_edit = QtWidgets.QLineEdit(self)
 
        self.spin_box = QtWidgets.QSpinBox(self)
        self.spin_box.setRange(10, 100)
        self.spin_box.setSuffix(" человек/час")
 
        self.double_spin_box = QtWidgets.QDoubleSpinBox(self)
        self.double_spin_box.setDecimals(6)
        self.double_spin_box.setRange(0, 10)
        self.double_spin_box.setSingleStep(0.000025)
 
        self.radio_button_1 = QtWidgets.QRadioButton("Радиокнопка 1", self)
        self.radio_button_2 = QtWidgets.QRadioButton("Радиокнопка 2", self)
 
        layout = QtWidgets.QFormLayout(self)
        layout.addRow("Line Edit", self.line_edit)
        layout.addRow("Spin Box", self.spin_box)
        layout.addRow("Double Spin Box", self.double_spin_box)
        layout.addRow(self.radio_button_1)
        layout.addRow(self.radio_button_2)
        layout.setLabelAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
 
        if not parent:
            self.show()
 
    def closeEvent(self, event: QtGui.QCloseEvent) -> None:
        messageBox = QtWidgets.QMessageBox(
            QtWidgets.QMessageBox.Question,
            "Выход из программы",
            "Сохранить данные перед выходом?",
            (QtWidgets.QMessageBox.Yes
             | QtWidgets.QMessageBox.No
             | QtWidgets.QMessageBox.Cancel)
        )
        messageBox.setButtonText(QtWidgets.QMessageBox.Yes, "Да")
        messageBox.setButtonText(QtWidgets.QMessageBox.No, "Нет")
        messageBox.setButtonText(QtWidgets.QMessageBox.Cancel, "Отмена")
 
        resultCode = messageBox.exec_()
        if resultCode == QtWidgets.QMessageBox.Cancel:
            return event.ignore()
        elif resultCode == QtWidgets.QMessageBox.Yes:
            ...
        return QtWidgets.QWidget.closeEvent(self, event)
 
 
app = QtWidgets.QApplication()
main = Example()
app.exec_()
"Скролящийся код" - длинна строки не должна превышать 79(99) символов, иначе приходится дергать ползунок чтобы увидеть конец строки.

Добавлено через 3 минуты
Поясню на счет родителей: виджеты должны сохранять иерархию, это не только для общего понимания где, какой виджет валяется (в какой форме), ну и для методов поиска нужного виджета из родительских виджетов, так же дочерние виджеты черпают значения некоторых параметров из родительских (например при стилизации приложения).
1
470 / 103 / 26
Регистрация: 28.02.2013
Сообщений: 500
01.07.2021, 12:02  [ТС] 5
Цитата Сообщение от Fudthhh Посмотреть сообщение
пример для родителей
Что-то не хочет работать...
Пишет: TypeError: QApplication(List[str]): not enough arguments

Добавлено через 2 минуты
А не все норм
Просто добавил для PyQt5:
Python
1
import sys
и в конце поменял
Python
1
app = QtWidgets.QApplication(sys.argv)
Добавлено через 26 минут
Fudthhh, не могли бы вы перевести на русский следующие строки:

Python
1
2
3
class Example(QtWidgets.QWidget):
    def __init__(self, parent: QtWidgets.QWidget = None):
        QtWidgets.QWidget.__init__(self, parent)
Т.е. создаем класс Example, который наследует QtWidgets.QWidget, это понятно.
Почему конструкторе parent: QtWidgets.QWidget = None? (А если не None, что еще может быть и зачем?)
А потом QtWidgets.QWidget.__init__(self, parent)? Откуда появился parent и что делает эта строка?

Добавлено через 4 минуты
Python
1
2
        if not parent:
            self.show()
и зачем вот это? Т.е. если не родитель, то покажи себя?

Лучше сам gui писать в конструкторе?
0
Модератор
Эксперт Python
1647 / 999 / 362
Регистрация: 21.02.2017
Сообщений: 2,894
Записей в блоге: 1
01.07.2021, 13:11 6
Цитата Сообщение от Михалыч Посмотреть сообщение
Почему конструкторе parent: QtWidgets.QWidget = None? (А если не None, что еще может быть и зачем?)
Каждый виджет принимает не обязательный аргумент parent. Если при создании виджета ты укажешь родительский виджет, то с помощью функции children() (в родительском виджете), ты сможешь найти дочерние элементы, а с помощью функции parent() (в дочернем виджете) ты сможешь узнать его родителя.

Цитата Сообщение от Михалыч Посмотреть сообщение
А потом QtWidgets.QWidget.__init__(self, parent)? Откуда появился parent и что делает эта строка?
parent мы передаем при инициализации класса (или нет, в таком случае parent является None), и передаем в конструктор класса. Это строка аналогична - super().__init__(), только несет больше смысловой нагрузки (по моему мнению), чем конструкция super.


Цитата Сообщение от Михалыч Посмотреть сообщение
и зачем вот это? Т.е. если не родитель, то покажи себя?
Я так привык писать, тут уже дело вкуса.


Если у тебя будет миллион форм, и миллиард виджетов, искать необходимый виджет станет болью. По этому если ты укажешь родителей и дашь виджету имя (objectName), то с помощью функции findChild (findChildren) сможешь находить свои виджеты в очень отдаленных дочерних окнах, даже из главного окна.
1
470 / 103 / 26
Регистрация: 28.02.2013
Сообщений: 500
01.07.2021, 17:13  [ТС] 7
Спасибо огромное! Пойду читать про это

Добавлено через 3 часа 38 минут
Цитата Сообщение от Fudthhh Посмотреть сообщение
Если у тебя будет миллион форм, и миллиард виджетов, искать необходимый виджет станет болью.
АААА... До меня дошло!!! Это же просто офигительно!!!
Это сколько всего тут можно наворотить)))

PS. Для себя: Python 3 и PyQt Разработка приложений. Прохоренок Н. А. стр.403-407.
0
470 / 103 / 26
Регистрация: 28.02.2013
Сообщений: 500
02.07.2021, 11:52  [ТС] 8
Цитата Сообщение от Fudthhh Посмотреть сообщение
messageBox.setButtonText(QtWidgets.QMessageBox.Yes, "Да")
        messageBox.setButtonText(QtWidgets.QMessageBox.No, "Нет")
        messageBox.setButtonText(QtWidgets.QMessageBox.Cancel, "Отмена")
Fudthhh, а у вас тут PySide2 сразу кнопки переводит на русский?
0
Модератор
Эксперт Python
1647 / 999 / 362
Регистрация: 21.02.2017
Сообщений: 2,894
Записей в блоге: 1
05.07.2021, 07:18 9
Михалыч, PySide2 не причем, это встроенный метод QMessageBox. PySide2(6) и PyQt5(6) отличаются только лицензированием. Там конечно есть отличии в названии методов (не особо много) и нет пару классов в PySide2 (не критично), но в PySide более читабельные аннотации.
1
470 / 103 / 26
Регистрация: 28.02.2013
Сообщений: 500
05.07.2021, 09:47  [ТС] 10
Fudthhh, спасибо огромное!)
Цитата Сообщение от Fudthhh Посмотреть сообщение
PySide2 не причем
в PyQt5 я так не смог сделать нагуглил только такой способ QMessageBox перевести кнопки Yes и No
0
470 / 103 / 26
Регистрация: 28.02.2013
Сообщений: 500
09.07.2021, 09:53  [ТС] 11
К вопросу об "усыновлении сирот" в PyQt5. iamvic
https://www.cyberforum.ru/blog... g7180.html
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.07.2021, 09:53

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Просьба объяснить работу std::thread в двух коротких примерах кода
Доброго времени суток! Я использую std::thread чтобы поднять два разных потока. В первом случае...

Unable to import 'PyQt5' / No module named 'PyQt5' /
Здравствуйте. Имеется Ubuntu 18.04. Хочу использовать pyside2. Установил PyQt5. :~$ pip install...

PyQt5 Error while finding module specification for 'PyQt5.uic.pyuic' (ModuleNotFoundError: No module named 'PyQt
В общем поставил pyqt5 и python3.7 пишу в консоль python -m PyQt5.uic.pyuic Выдает ошибку Error...

В режиме кода появляется код формы, вместо самой формы
Здравствуйте. Возникла проблема: не могу визуально посмотреть форму. То есть при дабл клике по...

Вместо редактора формы - редактор кода формы
Редактор формы куда-то пропал в обозревателе. программа компилируется и запускается с Form1 окном....

Взаимодействия кода и формы
Каким образом взаимодействует форма и программный код на С#?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.