تُستخدم أداة QCalendarWidget في PyQt لعرض تقويم شهري تفاعلي، حيث يمكن للمستخدم اختيار تاريخ معيّن، كما يمكنك برمجياً تحديد التاريخ الافتراضي أو معرفة التاريخ الذي تم اختياره.
إنشاء نافذة تحتوي على QCalendarWidget
في المثال التالي، سننشئ نافذة بها تقويم، وعندما يختار المستخدم تاريخاً، سيتم عرضه في QLabel.
الكود
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QCalendarWidget, QLabel
from PyQt5.QtCore import QDate
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("مثال على QCalendarWidget")
self.setGeometry(200, 200, 400, 300)
layout = QVBoxLayout()
# إنشاء التقويم
self.calendar = QCalendarWidget()
self.calendar.setGridVisible(True) # عرض خطوط الشبكة
self.calendar.clicked.connect(self.show_date) # عند اختيار تاريخ
# إنشاء التسمية
self.label = QLabel("اختر تاريخًا من التقويم")
self.label.setStyleSheet("font-size: 16px;")
# إضافة العناصر إلى التخطيط
layout.addWidget(self.calendar)
layout.addWidget(self.label)
self.setLayout(layout)
def show_date(self, date):
# عرض التاريخ المختار
self.label.setText(f"التاريخ المختار: {date.toString('dd/MM/yyyy')}")
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
شرح الكود
-
إنشاء QCalendarWidget
self.calendar = QCalendarWidget()
هذا ينشئ التقويم داخل النافذة.
-
إظهار خطوط الشبكة
self.calendar.setGridVisible(True)
لجعل التقويم أكثر وضوحاً.
-
التفاعل مع اختيار التاريخ
self.calendar.clicked.connect(self.show_date)
عندما يختار المستخدم تاريخًا، يتم تنفيذ الدالة
show_date
. -
عرض التاريخ المختار في QLabel
self.label.setText(f"التاريخ المختار: {date.toString('dd/MM/yyyy')}")
حيث يتم تنسيق التاريخ ليظهر بالشكل يوم/شهر/سنة.
أهم خصائص QCalendarWidget
-
تغيير التاريخ الافتراضي
self.calendar.setSelectedDate(QDate(2025, 1, 1))
يحدد تاريخًا افتراضيًا.
-
تحديد أقل وأعلى تاريخ
self.calendar.setMinimumDate(QDate(2020, 1, 1)) self.calendar.setMaximumDate(QDate(2030, 12, 31))
-
إخفاء أو إظهار الشبكة
self.calendar.setGridVisible(False)
📌 التمرين:
أنشئ برنامج باستخدام PyQt5 يحتوي على:
-
QTableWidget بعدد 3 أعمدة و 4 صفوف.
-
ضع أسماء الأعمدة: "الاسم"، "العمر"، "المدينة".
-
أضف زر "إضافة بيانات" وعند الضغط عليه يتم إدخال البيانات التالية في الجدول:
-
أحمد — 25 — القاهرة
-
سارة — 30 — الإسكندرية
-
علي — 22 — الجيزة
-
مريم — 28 — بورسعيد
-
-
أضف زر "مسح البيانات" لمسح محتوى الجدول.
💻 الحل:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QTableWidget, QTableWidgetItem
class TableExample(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("تمرين QTableWidget")
self.resize(400, 300)
layout = QVBoxLayout()
# إنشاء الجدول
self.table = QTableWidget()
self.table.setRowCount(4) # 4 صفوف
self.table.setColumnCount(3) # 3 أعمدة
self.table.setHorizontalHeaderLabels(["الاسم", "العمر", "المدينة"])
# زر إضافة البيانات
self.add_button = QPushButton("إضافة بيانات")
self.add_button.clicked.connect(self.add_data)
# زر مسح البيانات
self.clear_button = QPushButton("مسح البيانات")
self.clear_button.clicked.connect(self.clear_data)
# إضافة العناصر للتخطيط
layout.addWidget(self.table)
layout.addWidget(self.add_button)
layout.addWidget(self.clear_button)
self.setLayout(layout)
def add_data(self):
data = [
["أحمد", "25", "القاهرة"],
["سارة", "30", "الإسكندرية"],
["علي", "22", "الجيزة"],
["مريم", "28", "بورسعيد"]
]
for row, row_data in enumerate(data):
for col, value in enumerate(row_data):
self.table.setItem(row, col, QTableWidgetItem(value))
def clear_data(self):
self.table.clearContents()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TableExample()
window.show()
sys.exit(app.exec_())
سنقوم بتطوير التمرين بحيث:
-
تستطيع تعديل أي خلية مباشرة من الجدول.
-
يوجد زر "حفظ البيانات" يقوم بطباعة البيانات المعدلة في الـ Terminal (كمحاكاة لعملية الحفظ في قاعدة بيانات أو ملف).
💻 التمرين المطوّر:
import sys
from PyQt5.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QPushButton, QTableWidget, QTableWidgetItem
)
class TableExample(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("تمرين QTableWidget المطور")
self.resize(450, 320)
layout = QVBoxLayout()
# إنشاء الجدول
self.table = QTableWidget()
self.table.setRowCount(4) # 4 صفوف
self.table.setColumnCount(3) # 3 أعمدة
self.table.setHorizontalHeaderLabels(["الاسم", "العمر", "المدينة"])
self.table.setEditTriggers(QTableWidget.AllEditTriggers) # السماح بالتعديل
# زر إضافة البيانات
self.add_button = QPushButton("إضافة بيانات")
self.add_button.clicked.connect(self.add_data)
# زر مسح البيانات
self.clear_button = QPushButton("مسح البيانات")
self.clear_button.clicked.connect(self.clear_data)
# زر حفظ البيانات
self.save_button = QPushButton("حفظ البيانات")
self.save_button.clicked.connect(self.save_data)
# إضافة العناصر للتخطيط
layout.addWidget(self.table)
layout.addWidget(self.add_button)
layout.addWidget(self.clear_button)
layout.addWidget(self.save_button)
self.setLayout(layout)
def add_data(self):
data = [
["أحمد", "25", "القاهرة"],
["سارة", "30", "الإسكندرية"],
["علي", "22", "الجيزة"],
["مريم", "28", "بورسعيد"]
]
for row, row_data in enumerate(data):
for col, value in enumerate(row_data):
self.table.setItem(row, col, QTableWidgetItem(value))
def clear_data(self):
self.table.clearContents()
def save_data(self):
rows = self.table.rowCount()
cols = self.table.columnCount()
all_data = []
for row in range(rows):
row_data = []
for col in range(cols):
item = self.table.item(row, col)
if item:
row_data.append(item.text())
else:
row_data.append("")
all_data.append(row_data)
print("📌 البيانات المحفوظة:")
for row in all_data:
print(row)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TableExample()
window.show()
sys.exit(app.exec_())
🔹 في هذا الإصدار:
-
يمكنك تعديل أي خلية مباشرة.
-
بعد التعديل، اضغط "حفظ البيانات" وسيتم عرض كل البيانات في الـ Terminal.
-
يمكن تطويره لاحقًا لحفظ البيانات في ملف Excel أو قاعدة بيانات.
📌 تمرين: حفظ بيانات جدول إلى ملف Excel
الفكرة
-
إنشاء نافذة تحتوي على جدول (QTableWidget) يمكن للمستخدم إدخال البيانات فيه.
-
زر "حفظ إلى Excel" يقوم بإنشاء ملف Excel وحفظ البيانات الموجودة في الجدول بداخله.
💻 الكود
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QTableWidget, QTableWidgetItem, QMessageBox
from openpyxl import Workbook
class ExcelSaver(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("حفظ البيانات إلى Excel")
self.setGeometry(200, 200, 500, 400)
layout = QVBoxLayout()
# إنشاء الجدول
self.table = QTableWidget(5, 3) # 5 صفوف، 3 أعمدة
self.table.setHorizontalHeaderLabels(["الاسم", "العمر", "المدينة"])
layout.addWidget(self.table)
# زر الحفظ
save_button = QPushButton("💾 حفظ إلى Excel")
save_button.clicked.connect(self.save_to_excel)
layout.addWidget(save_button)
self.setLayout(layout)
def save_to_excel(self):
wb = Workbook()
ws = wb.active
ws.title = "البيانات"
# إضافة العناوين
headers = [self.table.horizontalHeaderItem(i).text() for i in range(self.table.columnCount())]
ws.append(headers)
# إضافة البيانات
for row in range(self.table.rowCount()):
row_data = []
for col in range(self.table.columnCount()):
item = self.table.item(row, col)
row_data.append(item.text() if item else "")
ws.append(row_data)
# حفظ الملف
try:
wb.save("data.xlsx")
QMessageBox.information(self, "نجاح", "تم حفظ البيانات في ملف data.xlsx بنجاح ✅")
except Exception as e:
QMessageBox.warning(self, "خطأ", f"حدث خطأ أثناء الحفظ: {e}")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = ExcelSaver()
window.show()
sys.exit(app.exec_())
📖 الشرح
-
QTableWidget لعرض وإدخال البيانات.
-
openpyxl لحفظ البيانات في ملف Excel.
-
زر يقوم بقراءة محتويات الجدول وإرسالها إلى ملف
data.xlsx
. -
رسالة منبثقة تؤكد نجاح العملية.