管理两个主要 window MainWindow 和线程

Managing two main window MainWindow and threading

我更新了一些东西,比如从线程 class 调用 on_event 方法,现在我有了这段代码:

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys, pyodbc, serial
import os
import time
import thread
from PyQt4.QtCore import pyqtSignal
from PyQt4.QtCore import QObject, pyqtSignal

#Variables
Code_Zone = "d"

class MainWindow(QtGui.QWidget):
    def __init__(self, main):
        super(MainWindow, self).__init__()
        self.main = main
        self.grid = QtGui.QGridLayout(self)
        self.welcome = QtGui.QLabel("Bienvenue sur www.developpez.net", self)
        self.grid.addWidget(self.welcome, 2, 2, 1, 5)

class AccessWindow(QtGui.QWidget):
    def __init__(self):
        super(AccessWindow, self).__init__()
        self.setMinimumSize(150, 50)
        self.grid = QtGui.QGridLayout(self)
        self.label = QtGui.QLabel(self)
        self.grid.addWidget(self.label, 1, 1, 1, 1)

class Main(object):
    global EPC_Code
    def __init__(self):
        self.accueil = MainWindow(self)
        self.accueil.show()
        self.access = AccessWindow()

    def on_event(self, data):
        def refresh():
            self.toggle_widget(False)
            #c = AThread()
            c.run()
            #self.wait()
        # vérification des données 
        EPC_Code = data
        cnxn = """DRIVER={SQL Server};SERVER=Aziz-PC\SQLEXPRESS;PORT=1433;UID=poleindus;PWD=poleindus;DATABASE=indusdb"""
        db_connection = pyodbc.connect(cnxn)
        db_cursor = db_connection.cursor()
        print ('Connected TO DB & READY')
        sql_command = "EXECUTE [Get_Access_RFID] @Code_RFID = '"+EPC_Code+"', @Code_Zone = '"+Code_Zone+"'"
        db_cursor.execute("EXECUTE [Get_Access_RFID] @Code_RFID = '"+EPC_Code+"', @Code_Zone = '"+Code_Zone+"'")
        rows = db_cursor.fetchone()
        result= str(rows[0])
        print ("result = " + str(result))
        if result == "True":
            # si OK
            self.access.label.setText('ACCESS GRANTED')
        else:
            # si pas OK
            self.access.label.setText('ACCESS DENIED')
        self.toggle_widget(True)
        QtCore.QTimer.singleShot(2000, refresh)

    def toggle_widget(self, b):
        self.accueil.setVisible(not b)
        self.access.setVisible(b)


class AThread(QtCore.QThread):
    rfid_event = pyqtSignal(str, name='rfid_event')

    def run(self):
        while 1:
            ser = serial.Serial(port='COM6', baudrate=115200)
            a = ser.read(19).encode('hex')
            ser.close()

            if len(a) == 38:
                EPC_Code = a[14:]
                print ('EPC is : ' + EPC_Code)
                self.rfid_event.emit(EPC_Code)

if __name__=='__main__':
    #cnxn = """DRIVER={SQL Server};SERVER=Aziz-PC\SQLEXPRESS;PORT=1433;UID=poleindus;PWD=poleindus;DATABASE=indusdb"""
    #db_connection = pyodbc.connect(cnxn)
    #db_cursor = db_connection.cursor()
    #print ('Connected TO DB & READY')
    app = QtGui.QApplication(sys.argv)
    main = Main()
    thread = AThread()
    thread.rfid_event.connect(Main().on_event)
    thread.start()
    #main = Main()
    sys.exit(app.exec_())

我已经在代码的顶部添加了这一行,现在,我有另一个错误:要执行的第一个参数必须是字符串或 unicode query.when 我检查了 sql 命令,我发现它等于: PyQt4.QtCore.QString(u"EXECUTE [Get_Access_RFID] @Code_RFID = 'e20010712904019411709bdd', @Code_Zone = 'd'")

您在 AThread 中创建了一个新的 Main。这意味着您现在有两个(更糟糕的是,您每次处理 RFID 事件时都会创建一个)。

此外,您不能从线程内部调用 Main 的方法。想象一下,如果线程在第一次调用之前再次调用它们会发生什么情况return:数据会被破坏。

相反,您必须在 AThread 中声明一个信号并调用 emit() 来发送它。最后一段代码中的 Main 可以连接到此信号。

class AThread(QtCore.QThread):
    rfid_event = pyqtSignal(str, name='rfid_event')

    def run(self):
        while 1:
            ser = serial.Serial(port='COM6', baudrate=115200)
            a = ser.read(19).encode('hex')
            ser.close()

            if len(a) == 38:
                EPC_Code = a[14:]
                print ('EPC is : ' + EPC_Code)
                self.rfid_event.emit(EPC_Code)

及稍后在 __main__ 代码中:

main = Main()
thread = AThread()
thread.rfid_event.coonect(Main.on_event)
thread.start()
#main = Main()
sys.exit(app.exec_())

另请注意,thread.finished.connect(app.exit) 将不起作用:该线程包含无限循环并且永远不会结束。相反,您应该在主 window 关闭时终止线程。

我也修复了串口的访问;每次都必须关闭它。