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

آخر الأخبار

جاري التحميل ...

الدرس 32 — استخدام QSplitter لبناء واجهات قابلة لتغيير الحجم

QSplitter هو ويدجت يضع داخل النافذة مجموعة من الحاويات (widgets) بطريقة أفقية أو عمودية، ويمنح المستخدم مقابض قابلة للسحب لتغيير حجم كل قسم. مفيد لتصميم واجهات مثل: محرر (قائمة ملفات ← محرر نص)، أو لوحة إعدادات ← معاينة، أو أي تخطيط يحتاج أقسامًا قابلة لإعادة التحجيم.

QSplitter

متى نستخدم QSplitter؟

  • عندما تريد أن تسمح للمستخدم بتغيير مساحة كل جزء من الواجهة ديناميكيًا.
  • لتصميم واجهات شبيهة ببيئات التطوير (IDE) أو مستعرضات الملفات.
  • لعمل تخطيطات أفقيّة أو عمودية قابلة للتعديل بسهولة.


المكتبات المطلوبة

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit, QListWidget, QSplitter, QLabel
from PyQt5.QtCore import Qt

مثال عملي بسيط — محرر نص مع شريط جانبي قابل للسحب

الكود التالي يُنشئ نافذة فيها QListWidget على اليسار (قائمة ملفات وهمية) و QTextEdit على اليمين (منطقة التحرير). بينهما QSplitter يمكن سحب المقسم لتغيير العرض.

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit, QListWidget, QSplitter, QLabel
from PyQt5.QtCore import Qt

class SplitterExample(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("مثال QSplitter - محرر بسيط")
        self.resize(800, 500)

        main_layout = QVBoxLayout()

        # عنوان
        header = QLabel("محرر بسيط — جرّ المقبض لتغيير المساحة بين اللوحين")
        header.setStyleSheet("font-weight: bold; padding: 6px;")
        main_layout.addWidget(header)

        # إنشاء الوديجات
        file_list = QListWidget()
        file_list.addItems([f"ملف_{i}.txt" for i in range(1, 11)])

        editor = QTextEdit()
        editor.setPlainText("اكتب هنا...")

        # إنشاء QSplitter أفقي بين القائمتين
        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(file_list)
        splitter.addWidget(editor)

        # إعداد نسبة البداية (اختياري)
        splitter.setSizes([200, 600])  # أجزاء افتراضية: القائمة أصغر من المحرر

        main_layout.addWidget(splitter)
        self.setLayout(main_layout)

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

ملاحظات على الكود

  • QSplitter(Qt.Horizontal) ينشئ تقسيمًا أفقيًا (أعمدة). استخدم Qt.Vertical للحصول على صفوف قابلة للسحب.
  • addWidget() لإضافة كل قسم داخل الـ splitter.
  • setSizes([a, b, ...]) يحدد أحجامًا مبدئية نسبية للأقسام.
  • كل ويدجت داخل الـ splitter يحتفظ بقدرته على التصغير/التكبير تلقائيًا.


أفكار متقدمة وإعدادات مفيدة

  • splitter.handleWidth() لتغيير عرض المقبض.
  • splitter.setChildrenCollapsible(False) لمنع انهيار أحد الأقسام عند سحب المقبض لحدود الصفر.
  • يمكنك وضع splitter داخل splitter (داخل واحد آخر) لبناء تخطيطات معقدة — مثلاً عمود أيمن مقسّم إلى قسمين عموديين داخليًا.
  • حفظ أو استرجاع حجم الأقسام (splitter.sizes()) لتذكر حالة الواجهة بين جلسات المستخدم.


تمرين عملي (مع الحل) — محرر ثنائي مع معاينة HTML

المطلوب: أنشئ نافذة تحتوي على:

  1. محرر نص (QTextEdit) في الجهة اليسرى لإدخال كود HTML.
  2. نافذة معاينة بسيطة على اليمين تعرض نص HTML كـ نص منسّق (نستخدم QTextEdit بوضع read-only وندخل HTML باستخدام setHtml()).
  3. استخدم QSplitter أفقيًا بحيث يمكن سحب المقسم بين المحرر والمعاينة.
  4. عند كل تغير في المحرر (textChanged) يحدث العرض في المعاينة فورًا.

الحل

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit, QSplitter
from PyQt5.QtCore import Qt

class HtmlLivePreview(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("محرر HTML مع معاينة مباشرة")
        self.resize(900, 600)

        layout = QVBoxLayout()

        # محرر HTML
        self.editor = QTextEdit()
        self.editor.setPlainText("<h2>عنوان</h2>\n<p>جرب تحرير هذا النص...</p>")

        # معاينة HTML (وضع للقراءة فقط)
        self.preview = QTextEdit()
        self.preview.setReadOnly(True)
        self.preview.setHtml(self.editor.toPlainText())  # معاينة أولية

        # QSplitter ليجعل المحرر والمعاينة قابلين لتغيير الحجم
        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(self.editor)
        splitter.addWidget(self.preview)
        splitter.setSizes([500, 400])

        # ربط تغيّر المحرر بتحديث المعاينة
        self.editor.textChanged.connect(self.update_preview)

        layout.addWidget(splitter)
        self.setLayout(layout)

    def update_preview(self):
        # تحديث المعاينة بالمحتوى الحالي (كمحتوى HTML)
        html_content = self.editor.toPlainText()
        self.preview.setHtml(html_content)

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

تحدي إضافي (اقتراح)

اجعل التطبيق أعلاه يدعم:

  • حفظ أحجام الأقسام في ملف إعدادات (مثلاً JSON) عند الإغلاق، واستعادتها عند الفتح.
  • إضافة زر إخفاء / إظهار الشريط الجانبي (list) بحيث يستخدم splitter.widget(i).hide() أو show() ويعيد ضبط الأحجام بشكل سلس.
  • استبدال QTextEdit للمعاينة بـ QWebEngineView لعرض HTML حقيقي مع دعم CSS/JS (يتطلب تثبيت PyQtWebEngine).


خاتمة سريعة

QSplitter أداة بسيطة لكنها قوية لبناء واجهات مرنة وسهلة الاستخدام. استخدامها بشكل ذكي (مع حفظ حالة الواجهة وإتاحة إظهار/إخفاء الأقسام) يزيد من احترافية واجهاتك ويعطي تجربة مستخدم ممتازة — وكل هذا دون تكرار الدروس السابقة لأن الفكرة هنا مختلفة: التحكم بالتخطيط الديناميكي وليس بعرض قيمة واحدة أو حفظ بيانات.

عن الكاتب

Tamer Ahmed

التعليقات


اتصل بنا

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

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

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