في هذا الدرس سنتعرف على QTabWidget، وهو عنصر واجهة رسومية يسمح بعرض محتويات في شكل تبويبات (Tabs)، بحيث يمكن للمستخدم التنقل بين الصفحات بسهولة مثل متصفح الإنترنت أو إعدادات البرامج.
أهم خصائص QTabWidget
-
إضافة تبويب جديد:
tab_widget.addTab(عنصر, "عنوان التبويب")
-
تغيير عنوان التبويب:
tab_widget.setTabText(رقم_التبويب, "عنوان جديد")
-
الوصول للتبويب الحالي:
index = tab_widget.currentIndex()
-
تغيير التبويب الحالي:
tab_widget.setCurrentIndex(رقم_التبويب)
مثال عملي
هذا المثال يحتوي على 3 تبويبات: الصفحة الرئيسية، الإعدادات، حول البرنامج.
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QTabWidget
class TabExample(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("مثال QTabWidget")
self.resize(400, 300)
layout = QVBoxLayout()
# إنشاء التبويبات
tabs = QTabWidget()
# التبويب الأول
tab1 = QWidget()
tab1_layout = QVBoxLayout()
tab1_layout.addWidget(QLabel("مرحبًا بك في الصفحة الرئيسية"))
tab1.setLayout(tab1_layout)
# التبويب الثاني
tab2 = QWidget()
tab2_layout = QVBoxLayout()
tab2_layout.addWidget(QLabel("هنا الإعدادات"))
tab2.setLayout(tab2_layout)
# التبويب الثالث
tab3 = QWidget()
tab3_layout = QVBoxLayout()
tab3_layout.addWidget(QLabel("حول البرنامج: إصدار 1.0"))
tab3.setLayout(tab3_layout)
# إضافة التبويبات
tabs.addTab(tab1, "الرئيسية")
tabs.addTab(tab2, "الإعدادات")
tabs.addTab(tab3, "حول")
layout.addWidget(tabs)
self.setLayout(layout)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TabExample()
window.show()
sys.exit(app.exec_())
شرح الكود
-
أنشأنا عنصر QTabWidget لاحتواء التبويبات.
-
أضفنا 3 صفحات (
QWidget
) مع تخطيطات خاصة بها. -
وضعنا كل صفحة داخل التبويب المناسب.
-
أضفنا النصوص لشرح محتوى كل تبويب.
📌 معلومة إضافية:
يمكنك إضافة أي عنصر داخل التبويب، مثل أزرار، جداول، أو حتى تبويبات داخل تبويبات.
تمرين شامل على QTabWidget بحيث:
-
التبويب الأول: إدخال بيانات (الاسم – العمر – الدرجة) مع زر إضافة للجدول.
-
التبويب الثاني: عرض البيانات في QTableWidget.
-
التبويب الثالث: زر لحفظ الجدول في ملف Excel.
الكود
import sys
import os
import pandas as pd
from PyQt5.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QTabWidget,
QLabel, QLineEdit, QPushButton, QHBoxLayout,
QTableWidget, QTableWidgetItem, QMessageBox
)
class TabApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("تمرين شامل على QTabWidget")
self.resize(600, 400)
self.excel_file = "students_data.xlsx"
layout = QVBoxLayout()
# إنشاء QTabWidget
self.tabs = QTabWidget()
# التبويب الأول - إدخال البيانات
self.tab1 = QWidget()
tab1_layout = QVBoxLayout()
form_layout = QHBoxLayout()
self.name_input = QLineEdit()
self.name_input.setPlaceholderText("ادخل الاسم")
self.age_input = QLineEdit()
self.age_input.setPlaceholderText("ادخل العمر")
self.grade_input = QLineEdit()
self.grade_input.setPlaceholderText("ادخل الدرجة")
form_layout.addWidget(self.name_input)
form_layout.addWidget(self.age_input)
form_layout.addWidget(self.grade_input)
btn_add = QPushButton("إضافة إلى الجدول")
btn_add.clicked.connect(self.add_to_table)
tab1_layout.addLayout(form_layout)
tab1_layout.addWidget(btn_add)
self.tab1.setLayout(tab1_layout)
# التبويب الثاني - عرض الجدول
self.tab2 = QWidget()
tab2_layout = QVBoxLayout()
self.table = QTableWidget()
self.table.setColumnCount(3)
self.table.setHorizontalHeaderLabels(["الاسم", "العمر", "الدرجة"])
tab2_layout.addWidget(self.table)
self.tab2.setLayout(tab2_layout)
# تحميل البيانات من Excel إذا موجود
self.load_from_excel()
# التبويب الثالث - حفظ البيانات
self.tab3 = QWidget()
tab3_layout = QVBoxLayout()
btn_save = QPushButton("حفظ البيانات في Excel")
btn_save.clicked.connect(self.save_to_excel)
tab3_layout.addWidget(QLabel("اضغط الزر لحفظ جميع البيانات في ملف Excel"))
tab3_layout.addWidget(btn_save)
self.tab3.setLayout(tab3_layout)
# إضافة التبويبات
self.tabs.addTab(self.tab1, "إدخال البيانات")
self.tabs.addTab(self.tab2, "عرض البيانات")
self.tabs.addTab(self.tab3, "حفظ البيانات")
layout.addWidget(self.tabs)
self.setLayout(layout)
def add_to_table(self):
name = self.name_input.text()
age = self.age_input.text()
grade = self.grade_input.text()
if not name or not age or not grade:
QMessageBox.warning(self, "خطأ", "يرجى إدخال جميع البيانات")
return
row_position = self.table.rowCount()
self.table.insertRow(row_position)
self.table.setItem(row_position, 0, QTableWidgetItem(name))
self.table.setItem(row_position, 1, QTableWidgetItem(age))
self.table.setItem(row_position, 2, QTableWidgetItem(grade))
self.name_input.clear()
self.age_input.clear()
self.grade_input.clear()
def save_to_excel(self):
rows = self.table.rowCount()
cols = self.table.columnCount()
data = []
for row in range(rows):
row_data = []
for col in range(cols):
item = self.table.item(row, col)
row_data.append(item.text() if item else "")
data.append(row_data)
df = pd.DataFrame(data, columns=["الاسم", "العمر", "الدرجة"])
df.to_excel(self.excel_file, index=False)
QMessageBox.information(self, "تم الحفظ", f"تم حفظ البيانات في {self.excel_file}")
def load_from_excel(self):
if os.path.exists(self.excel_file):
df = pd.read_excel(self.excel_file)
self.table.setRowCount(len(df))
for row in range(len(df)):
for col in range(len(df.columns)):
self.table.setItem(row, col, QTableWidgetItem(str(df.iat[row, col])))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TabApp()
window.show()
sys.exit(app.exec_())
شرح الفكرة
-
التبويب الأول: إدخال بيانات الطالب.
-
التبويب الثاني: عرض جميع البيانات في جدول.
-
التبويب الثالث: حفظ البيانات في ملف Excel.
-
عند فتح البرنامج يتم تحميل البيانات من الملف إذا كان موجود.
سأطور لك التمرين بحيث:
-
عند إضافة أي صف جديد أو تعديل أي خلية أو حذف صف يتم حفظ الجدول مباشرة في ملف Excel.
-
عند تشغيل البرنامج يتم تحميل البيانات من الملف تلقائيًا إذا كان موجودًا.
الكود المطور – الحفظ التلقائي
import sys
import os
import pandas as pd
from PyQt5.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QTabWidget,
QLabel, QLineEdit, QPushButton, QHBoxLayout,
QTableWidget, QTableWidgetItem, QMessageBox
)
class TabApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("QTabWidget - حفظ تلقائي في Excel")
self.resize(600, 400)
self.excel_file = "students_data.xlsx"
layout = QVBoxLayout()
# إنشاء QTabWidget
self.tabs = QTabWidget()
# التبويب الأول - إدخال البيانات
self.tab1 = QWidget()
tab1_layout = QVBoxLayout()
form_layout = QHBoxLayout()
self.name_input = QLineEdit()
self.name_input.setPlaceholderText("ادخل الاسم")
self.age_input = QLineEdit()
self.age_input.setPlaceholderText("ادخل العمر")
self.grade_input = QLineEdit()
self.grade_input.setPlaceholderText("ادخل الدرجة")
form_layout.addWidget(self.name_input)
form_layout.addWidget(self.age_input)
form_layout.addWidget(self.grade_input)
btn_add = QPushButton("إضافة إلى الجدول")
btn_add.clicked.connect(self.add_to_table)
tab1_layout.addLayout(form_layout)
tab1_layout.addWidget(btn_add)
self.tab1.setLayout(tab1_layout)
# التبويب الثاني - عرض الجدول
self.tab2 = QWidget()
tab2_layout = QVBoxLayout()
self.table = QTableWidget()
self.table.setColumnCount(3)
self.table.setHorizontalHeaderLabels(["الاسم", "العمر", "الدرجة"])
tab2_layout.addWidget(self.table)
self.tab2.setLayout(tab2_layout)
# التبويب الثالث - معلومات الحفظ
self.tab3 = QWidget()
tab3_layout = QVBoxLayout()
tab3_layout.addWidget(QLabel("📌 يتم حفظ البيانات تلقائيًا عند أي تعديل أو إضافة"))
self.tab3.setLayout(tab3_layout)
# إضافة التبويبات
self.tabs.addTab(self.tab1, "إدخال البيانات")
self.tabs.addTab(self.tab2, "عرض البيانات")
self.tabs.addTab(self.tab3, "معلومات")
layout.addWidget(self.tabs)
self.setLayout(layout)
# تحميل البيانات من Excel إذا موجود
self.load_from_excel()
# حفظ تلقائي عند تعديل أي خلية
self.table.itemChanged.connect(self.save_to_excel)
def add_to_table(self):
name = self.name_input.text()
age = self.age_input.text()
grade = self.grade_input.text()
if not name or not age or not grade:
QMessageBox.warning(self, "خطأ", "يرجى إدخال جميع البيانات")
return
row_position = self.table.rowCount()
self.table.insertRow(row_position)
self.table.setItem(row_position, 0, QTableWidgetItem(name))
self.table.setItem(row_position, 1, QTableWidgetItem(age))
self.table.setItem(row_position, 2, QTableWidgetItem(grade))
# مسح الحقول
self.name_input.clear()
self.age_input.clear()
self.grade_input.clear()
# حفظ تلقائي بعد الإضافة
self.save_to_excel()
def save_to_excel(self):
rows = self.table.rowCount()
cols = self.table.columnCount()
data = []
for row in range(rows):
row_data = []
for col in range(cols):
item = self.table.item(row, col)
row_data.append(item.text() if item else "")
data.append(row_data)
df = pd.DataFrame(data, columns=["الاسم", "العمر", "الدرجة"])
df.to_excel(self.excel_file, index=False)
def load_from_excel(self):
if os.path.exists(self.excel_file):
df = pd.read_excel(self.excel_file)
self.table.setRowCount(len(df))
for row in range(len(df)):
for col in range(len(df.columns)):
self.table.setItem(row, col, QTableWidgetItem(str(df.iat[row, col])))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = TabApp()
window.show()
sys.exit(app.exec_())
التطويرات المضافة
-
الحفظ التلقائي يتم عند:
-
إضافة صف جديد.
-
تعديل أي خلية في الجدول.
-
-
تحميل البيانات يتم مباشرة عند بدء البرنامج.
-
التبويب الثالث يوضح للمستخدم أن البيانات تحفظ تلقائيًا.