الخميس، 21 يونيو 2012

كيفية تغيير ال GUI واجهة المستخدم للبرنامج عن طريق threads

ما تحتاج معرفته قبل القراءة هو : python threading , PyQt 
ان بايثون لا تسمح بتغيير او تحديث او تعديل واجهة المستخدم للبرنامج خارج ال main thread او العملية الأساسية للبرنامج ..


اي لا تستطيع تعديل نص في نافذة برنامجك من عملية خارجية thread عن طريق موديول threading
لذلك نستخدم كلاس QThread القادم مع موديول PyQt4 النستخدمة لتشكيل واجهة المستخدم.....
و نرسل اشارات SIGNAL و نربطها مع الكائن في واجهة المستخدم
مثال :

#! /usr/bin/python
# -*- coding : utf-8 -*-
from PyQt4 import QtGui, QtCore
import time, sys
gui=QtGui.QApplication.processEvents #خاصية تستخدم ﻷمر البرنامج بتحديث واجهة المستخدم حتى لا يتجمد و لا يستجيب للأوامر
class display():#أولا نقوم بتعريف كلاس فيه كائنات واجهة المستخدم
    texttoset="" #متغير
    app=QtGui.QApplication(sys.argv) #نصنع كائن QApplication ضروري لبدء واجهة المستخدم
    dialog=QtGui.QDialog() #نصنع كائن مربع حوار
    dialog.resize(200, 150) #نحدد حجمه
    dialog.setMaximumSize(200, 150) #نحدد أكبر حجم مسموح به لمربع الحوار
    dialog.setMinimumSize(200, 150) #نحدد أصغر حجم مسموح به لمربع الحوار
    dialog.setWindowTitle("new dialog") #نحدد عنوان مربع الحوار
    label=QtGui.QLabel(dialog) #نصنع كائن نص داخل مربع الحوار
    label.setText("am a text label") #نحدد النص
    label.setGeometry(1, 20,200, 50)#نحدد القياسات x,y,width,high
    button=QtGui.QPushButton(dialog)#نصنع كائن زر
    button.setText("click me !")#نحدد النص له
    button.setGeometry(1, 60, 200, 50)#نحدد القياسات
    def changetext(self, value):#نعرف خاصية تغير النص 
        if value==True:
            text=str(self.texttoset)#للتأكد بأنه سيكون نص
            self.label.setText(text)#نحدد النص
ui=display()#نصنع كائن يرث خصائص الكلاس display 
#الان نصنع QThread كلاس
class mythread(QtCore.QThread):#الكلاس يرث خصائصه من كلاس #QtCore.QThread
    #هذه الثريد ستغير النص من  "i have changed by a QThread" الى "back all over again for the x time" و عند الانتهاء الى "QThread has finished" عشر مرات

    def __init__(self):
        QtCore.QThread.__init__(self)#نصنع الكلاس 
    def run(self):#خاصية موروثة من كلاس QtCore.QThread فيها الأوامر التي ستنفذها العملية thread
        x=0
        while x<=10:
            s=str(x)
            display.texttoset="i have changed by a QThread"#نحدد النص الذي سنضعه
            self.emit(QtCore.SIGNAL("anysignalname(bool)"), True) #نرسل اشارة اسمها "anysignalname" تحمل متغير من نوع بوول يحمل قيمتين اما True او False
            time.sleep(1)#توقف البرنامج لمدة 1 ثانية
            gui()#حدث وواجهة المستخدم      
            display.texttoset="back all over again for "+s+" time"#نحدد النص مرة أخرى
            self.emit(QtCore.SIGNAL("anysignalname(bool)"), True) #نرسل الاشارة مرة اخرى
            time.sleep(1)#توقف البرنامج لمدة ثانية واحدة
            gui()#حدث واجهة المستخدم
            x=x+1 #نزيد قيمة اكس
        display.texttoset="QThread has finished!!"#نحدد النص عند الانتهاء
        self.emit(QtCore.SIGNAL("anysignalname(bool)"), True) #نرسل الاشارة مرة أخرى
        time.sleep(1)#توقف البرنامج لمدة ثانية واحدة
        gui()#نحدث واجهة المستخدم      
        
thread1=mythread()#نصنع كائن يرث من كلاس mythread
def start():
    thread1.start()
def connecter():#خاصية ستصل الاشارات بالكائنات
    QtCore.QObject.connect(ui.button, QtCore.SIGNAL("clicked()"), start)#نصل كائن الزر بالخاصية start
    QtCore.QObject.connect(thread1, QtCore.SIGNAL("anysignalname(bool)"), ui.changetext)#نصل الكائن thread1 مع خاصية changetext التي ستغير النص  
ui.dialog.show()#نظهر مربع الحوار
connecter()#نستدعي خاصية وصل الاشارات
ui.app.exec_()#نبدأ بالعملية الأساسية

 هذا البرنامج سيصنع مربع حوار فيه نص و زر اذا ضغطنا الزر سيتغير النص 10 مرات عن طريق عملية خارجية

ليست هناك تعليقات:

إرسال تعليق

لديك شيء لتقوله؟

ملحوظة: يمكن لأعضاء المدونة فقط إرسال تعليق.