الفكرة العامة
- QSpinBox: إدخال أعداد صحيحة مع أسهم زيادة/نقصان.
- QDoubleSpinBox: إدخال أعداد عشرية (قابلة لتحديد عدد المنازل العشرية).
أهم الخواص/الدوال
setRange(min, max)— تحديد المجال.setSingleStep(step)— خطوة الزيادة/النقصان.setPrefix("$ ")/setSuffix(" kg")— بادئة/لاحقة للعرض فقط.setDecimals(n)— لعدد المنازل العشرية في QDoubleSpinBox.- الإشارة
valueChanged— للتفاعل الفوري مع تغيّر القيم.
مثال عملي: حساب إجمالي السعر (كمية × سعر)
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QSpinBox, QDoubleSpinBox, QGridLayout
class PriceCalculator(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("الدرس 13 - QSpinBox & QDoubleSpinBox")
self.resize(360, 160)
layout = QGridLayout(self)
# الكمية (صحيحة)
layout.addWidget(QLabel("الكمية:"), 0, 0)
self.qty = QSpinBox()
self.qty.setRange(1, 1000)
self.qty.setSingleStep(1)
self.qty.setValue(1)
layout.addWidget(self.qty, 0, 1)
# سعر الوحدة (عشري)
layout.addWidget(QLabel("سعر الوحدة:"), 1, 0)
self.unit = QDoubleSpinBox()
self.unit.setRange(0.00, 100000.00)
self.unit.setDecimals(2)
self.unit.setSingleStep(0.50)
self.unit.setPrefix("$ ")
self.unit.setValue(10.00)
layout.addWidget(self.unit, 1, 1)
# الإجمالي
layout.addWidget(QLabel("الإجمالي:"), 2, 0)
self.total = QLabel("$ 10.00")
layout.addWidget(self.total, 2, 1)
# التحديث عند تغيّر أي قيمة
self.qty.valueChanged.connect(self.update_total)
self.unit.valueChanged.connect(self.update_total)
self.update_total()
def update_total(self):
total_value = self.qty.value() * self.unit.value()
self.total.setText(f"$ {total_value:.2f}")
if __name__ == "__main__":
app = QApplication(sys.argv)
w = PriceCalculator()
w.show()
sys.exit(app.exec_())
نقاط مهمة في المثال
- استخدمنا QSpinBox للكمية (قيمة صحيحة)، وQDoubleSpinBox للسعر (قيمة عشرية).
- ربطنا
valueChangedبدالةupdate_totalلحساب الإجمالي مباشرةً.
تمرين تطبيقي
المطلوب: صِغ برنامجًا يحسب مؤشر كتلة الجسم (BMI):
- الوزن (QDoubleSpinBox) بالكيلوغرام، مجال 20 → 300، منزلتين عشريتين.
- الطول (QDoubleSpinBox) بالسنتيمتر، مجال 100 → 230، منزلة عشرية واحدة.
- عند تغيير الوزن أو الطول، احسب BMI = الوزن (كجم) / (الطول بالمتر)^2
وأظهر التصنيف: (نقص وزن / طبيعي / زيادة وزن / سمنة).
الحل المقترح
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QDoubleSpinBox, QGridLayout
class BMICalc(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("تمرين - حساب BMI")
self.resize(360, 160)
layout = QGridLayout(self)
# الوزن
layout.addWidget(QLabel("الوزن (كجم):"), 0, 0)
self.weight = QDoubleSpinBox()
self.weight.setRange(20.0, 300.0)
self.weight.setDecimals(2)
self.weight.setSingleStep(0.5)
self.weight.setValue(70.0)
layout.addWidget(self.weight, 0, 1)
# الطول
layout.addWidget(QLabel("الطول (سم):"), 1, 0)
self.height = QDoubleSpinBox()
self.height.setRange(100.0, 230.0)
self.height.setDecimals(1)
self.height.setSingleStep(0.5)
self.height.setValue(170.0)
layout.addWidget(self.height, 1, 1)
# النتائج
layout.addWidget(QLabel("BMI:"), 2, 0)
self.bmi_label = QLabel("0.00")
layout.addWidget(self.bmi_label, 2, 1)
layout.addWidget(QLabel("التصنيف:"), 3, 0)
self.class_label = QLabel("—")
layout.addWidget(self.class_label, 3, 1)
# تحديث عند أي تغيير
self.weight.valueChanged.connect(self.update_bmi)
self.height.valueChanged.connect(self.update_bmi)
self.update_bmi()
def update_bmi(self):
h_m = self.height.value() / 100.0 # تحويل سم إلى متر
if h_m <= 0:
self.bmi_label.setText("—")
self.class_label.setText("—")
return
bmi = self.weight.value() / (h_m ** 2)
self.bmi_label.setText(f"{bmi:.2f}")
self.class_label.setText(self.classify(bmi))
def classify(self, bmi):
if bmi < 18.5:
return "نقص وزن"
elif bmi < 25:
return "طبيعي"
elif bmi < 30:
return "زيادة وزن"
else:
return "سمنة"
if __name__ == "__main__":
app = QApplication(sys.argv)
w = BMICalc()
w.show()
sys.exit(app.exec_())

