Comments 11
Несмотря на простоту калькулятора, его реализация не совсем простая: фактически это state machine.
почему взяли pyside,а не qt6 ?
Не хочу распинаться про лицензии, быстродействие и остальное, поэтому отвечу просто - захотел PySide, сделал на PySide.
Хотя сейчас прихожу к выводу, что для open-source проектов лучше использовать PyQt.
у меня были сложности при совмещении двух фреймворков. например, из окна, написанного на pyqt5 открыть окно, написанное на pyside5. пришлось переписать на pyqt5. было у вас что-то похожее ?
Пока что не приходилось совмещать, да я и не придумаю такой ситуации, где мне это понадобилось бы.
допустим, есть окно-родитель на pyqt5 с кнопкой, при нажатии на которою, открывается дочернее окно на pyside5:
окно
# app.py
import sys
from PySide2.QtWidgets import (
QWidget, QLineEdit, QScrollArea, QMainWindow,
QApplication, QVBoxLayout, QSpacerItem, QSizePolicy, QCompleter
)
from PySide2.QtCore import Qt
from customwidgets2 import OnOffWidget
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__()
self.controls = QWidget() # Controls container widget.
self.controlsLayout = QVBoxLayout() # Controls container layout.
# List of names, widgets are stored in a dictionary by these keys.
#ряды
a = map(str, range(0, 10))
#print(a)
widget_names = a
self.widgets = []
# Iterate the names, creating a new OnOffWidget for
# each one, adding it to the layout and
# and storing a reference in the self.widgets dict
for name in widget_names:
item = OnOffWidget(name)
self.controlsLayout.addWidget(item)
self.widgets.append(item)
spacer = QSpacerItem(1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.controlsLayout.addItem(spacer)
self.controls.setLayout(self.controlsLayout)
# Scroll Area Properties.
self.scroll = QScrollArea()
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll.setWidgetResizable(True)
self.scroll.setWidget(self.controls)
# Search bar.
self.searchbar = QLineEdit()
self.searchbar.textChanged.connect(self.update_display)
# Adding Completer.
self.completer = QCompleter(widget_names)
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.searchbar.setCompleter(self.completer)
# Add the items to VBoxLayout (applied to container widget)
# which encompasses the whole window.
container = QWidget()
containerLayout = QVBoxLayout()
containerLayout.addWidget(self.searchbar)
containerLayout.addWidget(self.scroll)
container.setLayout(containerLayout)
self.setCentralWidget(container)
self.setGeometry(600, 100, 800, 600)
self.setWindowTitle('Инвентаризация. Работа.')
def update_display(self, text):
for widget in self.widgets:
if text.lower() in widget.name.lower():
widget.show()
else:
widget.hide()
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
# customwidgets.py
from PySide2.QtWidgets import (QWidget, QLabel, QPushButton,
QHBoxLayout)
class OnOffWidget(QWidget):
def __init__(self, name):
super(OnOffWidget, self).__init__()
self.name = name
self.is_on = False
self.is_pause = True
self.is_off = False
self.lbl = QLabel(self.name)
self.lbl2 = QLabel('')
self.btn_on = QPushButton("Старт")
self.btn_pause = QPushButton("Пауза")
self.btn_off = QPushButton("Завершить ряд")
self.hbox = QHBoxLayout()
self.hbox.addWidget(self.lbl)
self.hbox.addWidget(self.lbl2)
self.hbox.addWidget(self.btn_on)
self.hbox.addWidget(self.btn_pause)
self.hbox.addWidget(self.btn_off)
self.btn_on.clicked.connect(self.on)
self.btn_pause.clicked.connect(self.on_pause)
self.btn_off.clicked.connect(self.off)
self.setLayout(self.hbox)
self.update_button_state()
def show(self):
"""
Show this widget, and all child widgets.
"""
for w in [self, self.lbl, self.btn_on, self.btn_off]:
w.setVisible(True)
def hide(self):
"""
Hide this widget, and all child widgets.
"""
for w in [self, self.lbl, self.btn_on, self.btn_off]:
w.setVisible(False)
#действия кнопок
def on(self): #старт
self.is_on = True
self.is_pause = False
self.is_off = False
self.update_button_state()
def off(self): #завершить ряд
self.is_on = False
self.is_pause = False
self.update_button_state()
def on_pause(self): #пауза
self.is_pause = True
self.is_on = False
self.is_off = False
self.update_button_state()
#обновление цвета кнопок согласно статуса
def update_button_state(self):
if self.is_on == True:
self.btn_on.setStyleSheet("background-color: #4CAF50; color: #fff;")
self.btn_pause.setStyleSheet("background-color: none; color: none;")
self.btn_off.setStyleSheet("background-color: none; color: none;")
self.lbl2.setText("В процессе") # self.name - № ряда
elif self.is_pause == True:
self.btn_on.setStyleSheet("background-color: none; color: none;")
self.btn_pause.setStyleSheet("background-color: #316ad3; color: #fff;")
self.btn_off.setStyleSheet("background-color: none; color: none;")
self.lbl2.setText("На паузе")
else:
self.btn_on.setStyleSheet("background-color: none; color: none;")
self.btn_pause.setStyleSheet("background-color: none; color: none;")
self.btn_off.setStyleSheet("background-color: #D32F2F; color: #fff;")
self.lbl2.setText("Ряд завершен")
pyside5 приложение также использует class MainWindow(QMainWindow). А должно быть что-то вроде class Ui_object(object): для целей pyqt5. Попытка склеить эти два фреймворка.
Статейка очень классная, но у меня сразу возникает вопрос, как работать с длинными числами Прошу прощения если скажу не правильно, но имел ввиду числа больше BigInteger.
В Python нет таких понятий, как big integer, long integer, есть только integer, и он поддерживает настолько длинные числа, насколько вы захотите.
К сожалению, в калькуляторе из статьи есть проблемы с вычислениями длинных чисел, не реализовал правильно. Еще есть очевиднейшая проблема с обрезанием чисел до максимальной длины поля в 16 символов. Ее можно решить округлением, но тогда возникнет проблема с экспоненциальной записью числа. Да и вообще лучше переделать нативные вычисления.
Посчитал, что уже и так достаточно сделал. Да и до сих пор так считаю :)

Простой GUI калькулятор на Python #3. Backspace, отрицание и регулировка размера шрифта