تقنيات نور التعليمية تقنيات نور التعليمية
في الوقت الحالي

جاري صيانة و تحديث للمدونة

في الوقت الحالي
جاري التحميل ...

الدرس 26 – QTableWidget

 في هذا الدرس سنتعرف على QTableWidget، وهو عنصر واجهة رسومية في PyQt يسمح لنا بعرض البيانات في شكل جدول يحتوي على صفوف وأعمدة.

يمكنك من خلاله إضافة، تعديل، أو حذف البيانات، وتنسيق الخلايا بسهولة.

QTableWidget

أهم خصائص QTableWidget

  • تحديد عدد الصفوف والأعمدة باستخدام:
    table.setRowCount(عدد_الصفوف)
    table.setColumnCount(عدد_الأعمدة)
    
  • تحديد عناوين الأعمدة باستخدام:
    table.setHorizontalHeaderLabels(["العمود 1", "العمود 2", ...])
    
  • إضافة بيانات إلى خلية:
    table.setItem(صف, عمود, QTableWidgetItem("النص"))
    
  • قراءة البيانات من خلية:
    value = table.item(صف, عمود).text()
    

مثال عملي

هذا المثال يعرض جدول بيانات بسيط يحتوي على معلومات طلاب (الاسم، العمر، الدرجة).

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTableWidget, QTableWidgetItem

class TableApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("مثال QTableWidget")
        self.resize(400, 300)

        layout = QVBoxLayout()

        # إنشاء الجدول
        self.table = QTableWidget()
        self.table.setRowCount(3)  # عدد الصفوف
        self.table.setColumnCount(3)  # عدد الأعمدة
        self.table.setHorizontalHeaderLabels(["الاسم", "العمر", "الدرجة"])

        # إضافة البيانات
        data = [
            ["أحمد", "20", "90"],
            ["منى", "22", "85"],
            ["خالد", "19", "88"]
        ]

        for row, row_data in enumerate(data):
            for col, value in enumerate(row_data):
                self.table.setItem(row, col, QTableWidgetItem(value))

        layout.addWidget(self.table)
        self.setLayout(layout)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TableApp()
    window.show()
    sys.exit(app.exec_())

شرح الكود

  1. أنشأنا جدول باستخدام QTableWidget.
  2. حددنا عدد الصفوف والأعمدة.
  3. وضعنا عناوين للأعمدة.
  4. أضفنا بيانات في كل خلية باستخدام setItem().

📌 معلومة مهمة:
QTableWidget مناسب للجداول الصغيرة والمتوسطة. أما الجداول الكبيرة جدًا أو التي تحتاج ربطها بقاعدة بيانات، يفضل استخدام QTableView مع نموذج بيانات.


 تمرين على QTableWidget بحيث:

  • يمكن إضافة صفوف ديناميكيًا من خلال إدخال البيانات في خانات نصية.
  • يمكن حذف الصف المحدد بزر واحد.

التمرين مع الحل

import sys
from PyQt5.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QTableWidget, QTableWidgetItem,
    QLineEdit, QPushButton, QHBoxLayout, QMessageBox
)

class TableApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("تمرين QTableWidget - إضافة وحذف صفوف")
        self.resize(500, 400)

        # تصميم الواجهة
        main_layout = QVBoxLayout()

        # إنشاء الجدول
        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels(["الاسم", "العمر", "الدرجة"])
        main_layout.addWidget(self.table)

        # حقول إدخال البيانات
        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)
        main_layout.addLayout(form_layout)

        # أزرار الإضافة والحذف
        btn_layout = QHBoxLayout()
        btn_add = QPushButton("إضافة صف")
        btn_delete = QPushButton("حذف الصف المحدد")

        btn_add.clicked.connect(self.add_row)
        btn_delete.clicked.connect(self.delete_row)

        btn_layout.addWidget(btn_add)
        btn_layout.addWidget(btn_delete)
        main_layout.addLayout(btn_layout)

        self.setLayout(main_layout)

    def add_row(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 delete_row(self):
        selected_row = self.table.currentRow()
        if selected_row >= 0:
            self.table.removeRow(selected_row)
        else:
            QMessageBox.warning(self, "خطأ", "يرجى تحديد صف لحذفه")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TableApp()
    window.show()
    sys.exit(app.exec_())

شرح الفكرة

  1. الجدول يبدأ فارغًا بعدد أعمدة محدد.
  2. إضافة صف:
    • ندخل البيانات في QLineEdit.
    • عند الضغط على "إضافة صف"، يتم إنشاء صف جديد في الجدول ووضع القيم فيه.
  3. حذف صف:
    • نحدد الصف بالماوس.
    • عند الضغط على "حذف الصف المحدد"، يتم حذفه مباشرة.

التمرين المطور بحيث:

  • الجدول يحفظ البيانات تلقائيًا في ملف Excel عند الإضافة أو الحذف.
  • عند فتح البرنامج، يتم تحميل البيانات من ملف Excel إذا كان موجودًا.

الكود المطور

import sys
import os
import pandas as pd
from PyQt5.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QTableWidget, QTableWidgetItem,
    QLineEdit, QPushButton, QHBoxLayout, QMessageBox
)

class TableExcelApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QTableWidget - حفظ واسترجاع من Excel")
        self.resize(500, 400)

        self.excel_file = "table_data.xlsx"

        # تصميم الواجهة
        main_layout = QVBoxLayout()

        # إنشاء الجدول
        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels(["الاسم", "العمر", "الدرجة"])
        main_layout.addWidget(self.table)

        # تحميل البيانات من Excel إذا موجود
        self.load_from_excel()

        # حقول إدخال البيانات
        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)
        main_layout.addLayout(form_layout)

        # أزرار الإضافة والحذف
        btn_layout = QHBoxLayout()
        btn_add = QPushButton("إضافة صف")
        btn_delete = QPushButton("حذف الصف المحدد")

        btn_add.clicked.connect(self.add_row)
        btn_delete.clicked.connect(self.delete_row)

        btn_layout.addWidget(btn_add)
        btn_layout.addWidget(btn_delete)
        main_layout.addLayout(btn_layout)

        self.setLayout(main_layout)

    def add_row(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))

        # حفظ إلى Excel
        self.save_to_excel()

        # مسح الحقول
        self.name_input.clear()
        self.age_input.clear()
        self.grade_input.clear()

    def delete_row(self):
        selected_row = self.table.currentRow()
        if selected_row >= 0:
            self.table.removeRow(selected_row)
            self.save_to_excel()
        else:
            QMessageBox.warning(self, "خطأ", "يرجى تحديد صف لحذفه")

    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 = TableExcelApp()
    window.show()
    sys.exit(app.exec_())

مميزات النسخة المطورة

  • عند الإضافة أو الحذف، يتم حفظ الجدول مباشرة في ملف table_data.xlsx.
  • عند إعادة تشغيل البرنامج، يتم استرجاع البيانات من الملف.
  • لا تحتاج لحفظ يدوي، كل شيء يتم أوتوماتيكيًا.

عن الكاتب

Tamer Ahmed

التعليقات


اتصل بنا

إذا أعجبك محتوى مدونتنا نتمنى البقاء على تواصل دائم ، فقط قم بإدخال بريدك الإلكتروني للإشتراك في بريد المدونة السريع ليصلك جديد المدونة أولاً بأول ، كما يمكنك إرسال رساله بالضغط على الزر المجاور ...

جميع الحقوق محفوظة

تقنيات نور التعليمية