programming - python software download



পাইকিউটি থ্রেডিংয়ের সহজ উপায় (2)

আমার addImage(image_path) একটি জিইউআই রয়েছে যা একটি ফাংশন addImage(image_path) । সহজেই কল্পনা করা যায়, যখন একটি নতুন চিত্রকে QListWidget এ যুক্ত করা উচিত তখনই এটি ডাকা হয়। একটি ফোল্ডারে নতুন চিত্র সনাক্ত করার জন্য, আমি একটি threading.Thread ব্যবহার করি addImage ফোল্ডারে ফাইলের পরিবর্তনগুলি সনাক্ত করতে addImage থ্রেড করুন এবং এই থ্রেডটি পরে addImage সরাসরি কল করে।

থ্রেড সুরক্ষার কারণে QPixmap গুই থ্রেডের বাইরে QPixmap উচিত নয় এমন সতর্কতা পাওয়া যায়।

এই থ্রেডসেফটি তৈরি করার সর্বোত্তম এবং সহজ উপায় কী? QThread? সিগন্যাল / স্লট? QMetaObject.invokeMethod? আমার কেবল থ্রেড থেকে addImage একটি স্ট্রিং পাস করতে হবে।

https://src-bin.com


Answer #1

আপনার কিউটি দ্বারা সরবরাহিত বিল্ট ইন QThread ব্যবহার করা উচিত। আপনি আপনার ফাইল মনিটরিং কোডটি কোনও শ্রমিক শ্রেণীর ভিতরে QObject পারেন যা QObject থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয় যাতে এটি থ্রেডের মধ্যে বার্তা প্রেরণের জন্য কিউটি সিগন্যাল / স্লট সিস্টেমটি ব্যবহার করতে পারে।

class FileMonitor(QObject):

    image_signal = QtCore.pyqtSignal(str)

    @QtCore.pyqtSlot()
    def monitor_images(self):
        # I'm guessing this is an infinite while loop that monitors files
        while True:
            if file_has_changed:
                self.image_signal.emit('/path/to/image/file.jpg')


class MyWidget(QtGui.QWidget):

    def __init__(self, ...)
        ...
        self.file_monitor = FileMonitor()
        self.thread = QtCore.QThread(self)
        self.file_monitor.image_signal.connect(self.image_callback)
        self.file_monitor.moveToThread(self.thread)
        self.thread.started.connect(self.file_monitor.monitor_images)
        self.thread.start()

    @QtCore.pyqtSlot(str)
    def image_callback(self, filepath):
        pixmap = QtGui.QPixmap(filepath)
        ...

Answer #2

আমি বিশ্বাস করি যে সর্বোত্তম পন্থা সিগন্যাল / স্লট প্রক্রিয়াটি ব্যবহার করা। এখানে একটি উদাহরণ। (দ্রষ্টব্য: নীচের EDIT দেখুন যা আমার পদ্ধতির সম্ভাব্য দুর্বলতা দেখায়)।

from PyQt4 import QtGui
from PyQt4 import QtCore

# Create the class 'Communicate'. The instance
# from this class shall be used later on for the
# signal/slot mechanism.

class Communicate(QtCore.QObject):
    myGUI_signal = QtCore.pyqtSignal(str)

''' End class '''


# Define the function 'myThread'. This function is the so-called
# 'target function' when you create and start your new Thread.
# In other words, this is the function that will run in your new thread.
# 'myThread' expects one argument: the callback function name. That should
# be a function inside your GUI.

def myThread(callbackFunc):
    # Setup the signal-slot mechanism.
    mySrc = Communicate()
    mySrc.myGUI_signal.connect(callbackFunc) 

    # Endless loop. You typically want the thread
    # to run forever.
    while(True):
        # Do something useful here.
        msgForGui = 'This is a message to send to the GUI'
        mySrc.myGUI_signal.emit(msgForGui)
        # So now the 'callbackFunc' is called, and is fed with 'msgForGui'
        # as parameter. That is what you want. You just sent a message to
        # your GUI application! - Note: I suppose here that 'callbackFunc'
        # is one of the functions in your GUI.
        # This procedure is thread safe.

    ''' End while '''

''' End myThread '''

আপনার জিইউআই অ্যাপ্লিকেশন কোডটিতে আপনার নতুন থ্রেড তৈরি করা উচিত, এটিকে সঠিক কলব্যাক ফাংশন দেওয়া উচিত এবং এটি চালানো উচিত।

from PyQt4 import QtGui
from PyQt4 import QtCore
import sys
import os

# This is the main window from my GUI

class CustomMainWindow(QtGui.QMainWindow):

    def __init__(self):
        super(CustomMainWindow, self).__init__()
        self.setGeometry(300, 300, 2500, 1500)
        self.setWindowTitle("my first window")
        # ...
        self.startTheThread()

    ''''''

    def theCallbackFunc(self, msg):
        print('the thread has sent this message to the GUI:')
        print(msg)
        print('---------')

    ''''''


    def startTheThread(self):
        # Create the new thread. The target function is 'myThread'. The
        # function we created in the beginning.
        t = threading.Thread(name = 'myThread', target = myThread, args = (self.theCallbackFunc))
        t.start()

    ''''''

''' End CustomMainWindow '''


# This is the startup code.

if __name__== '__main__':
    app = QtGui.QApplication(sys.argv)
    QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique'))
    myGUI = CustomMainWindow()
    sys.exit(app.exec_())

''' End Main '''

সম্পাদনা

মিঃ থ্রি_ আনারস এবং মিঃ ব্রেন্ডন আবেল আমার পদ্ধতির একটি দুর্বলতা নির্দেশ করেছেন। প্রকৃতপক্ষে, দৃষ্টিভঙ্গি এই বিশেষ ক্ষেত্রে ভাল কাজ করে, কারণ আপনি সরাসরি সংকেত উত্পন্ন / নির্গত করেন। আপনি যখন বোতাম এবং উইজেটগুলিতে অন্তর্নির্মিত কিউটি সংকেতগুলি মোকাবেলা করেন, আপনার অন্য একটি পদ্ধতি অবলম্বন করা উচিত (মিঃ ব্রেন্ডন আবেলের উত্তরে বর্ণিত)।

মিঃ থ্রি_ আনারস একটি জিইউআইয়ের সাথে থ্রেড-নিরাপদ যোগাযোগের কয়েকটি পদ্ধতির মধ্যে তুলনা করার জন্য আমাকে স্ট্যাকওভারফ্লোতে একটি নতুন বিষয় শুরু করার পরামর্শ দিয়েছেন। আমি বিষয়টি খতিয়ে দেখব, এবং কাল এটি করব :-)





python-watchdog