01/10/2018, 13:53

Lỗi trôi thời gian khi dùng Timer threading

Chào cả nhà.
Em có tham khảo code ở đây:
https://stackoverflow.com/questions/474528/what-is-the-best-way-to-repeatedly-execute-a-function-every-x-seconds-in-python
Và ứng đây là code của em sử dung nó.
Vấn đề là sau khi click OK, 60 giây sau hàm Timer mới chạy. hichic.
Cả nhà giúp em với. Em cám ơn!

import sys
import os
from PyQt4 import QtCore, QtGui

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import matplotlib.pyplot as plt
import matplotlib.dates as dates
from matplotlib.backends.backend_qt4 import NavigationToolbar2QT as NavigationToolbar    ## for pan in matplotlib
from Tkinter import *
import tkMessageBox
import subprocess
import time
from datetime import datetime
import threading
from threading import Thread
import pyodbc
from multiprocessing import Process, Event
from threading import Timer
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Form(object):
	def setupUi(self, Form):
		Form.setObjectName(_fromUtf8("Form"))
		Form.resize(710, 405)
		self.lable_head = QtGui.QLabel(Form)
		self.lable_head.setGeometry(QtCore.QRect(0, 0, 711, 51))
		self.lable_head.setText(_fromUtf8(""))
		self.lable_head.setPixmap(QtGui.QPixmap(_fromUtf8("doreamon.jpg")))
		self.lable_head.setScaledContents(True)
		self.lable_head.setObjectName(_fromUtf8("lable_head"))
		self.tableWidget = QtGui.QTableWidget(Form)
		self.tableWidget.setGeometry(QtCore.QRect(0, 100, 191, 261))
		self.tableWidget.setObjectName(_fromUtf8("tableWidget"))
		self.tableWidget.setColumnCount(2)
		self.tableWidget.setRowCount(0)
		item = QtGui.QTableWidgetItem()
		self.tableWidget.setHorizontalHeaderItem(0, item)
		item = QtGui.QTableWidgetItem()
		self.tableWidget.setHorizontalHeaderItem(1, item)
		self.label_1 = QtGui.QLabel(Form)
		self.label_1.setGeometry(QtCore.QRect(70, 70, 91, 20))
		self.label_1.setObjectName(_fromUtf8("label_1"))
		self.label_2 = QtGui.QLabel(Form)
		self.label_2.setGeometry(QtCore.QRect(470, 70, 53, 16))
		self.label_2.setObjectName(_fromUtf8("label_2"))
		self.graphicsView = QtGui.QGraphicsView(Form)
		self.graphicsView.setGeometry(QtCore.QRect(210, 100, 491, 261))
		self.graphicsView.setObjectName(_fromUtf8("graphicsView"))
		self.lineEdit = QtGui.QLineEdit(Form)
		self.lineEdit.setGeometry(QtCore.QRect(0, 370, 521, 31))
		self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
		self.pushButton_ok = QtGui.QPushButton(Form)
		self.pushButton_ok.setGeometry(QtCore.QRect(530, 370, 71, 28))
		self.pushButton_ok.setObjectName(_fromUtf8("pushButton_ok"))
		self.pushButton_exit = QtGui.QPushButton(Form)
		self.pushButton_exit.setGeometry(QtCore.QRect(620, 370, 61, 28))
		self.pushButton_exit.setObjectName(_fromUtf8("pushButton_exit"))
		self.retranslateUi(Form)
		QtCore.QMetaObject.connectSlotsByName(Form)




	def retranslateUi(self, Form):
		Form.setWindowTitle(_translate("Form", "Form", None))
		item = self.tableWidget.horizontalHeaderItem(0)
		item.setText(_translate("Form", "x", None))
		item = self.tableWidget.horizontalHeaderItem(1)
		item.setText(_translate("Form", "y", None))
		self.label_1.setText(_translate("Form", "Data table", None))
		self.label_2.setText(_translate("Form", "matplotlib", None))
		self.lineEdit.setText(_translate("Form", "Click Run", None))
		self.pushButton_ok.setText(_translate("Form", "OK", None))
		self.pushButton_exit.setText(_translate("Form", "Exit", None))
		self.pushButton_ok.clicked.connect(self.launch_Thread_run)
		self.pushButton_exit.clicked.connect(self.stop_thread)
	def Runevery5min(self):
		#
        # function cal and update table and plot
        #
		self.lineEdit.setText("Calculate and update data every 5 minutes....")
		t = datetime.now()
		print (t)

	def run(self):
		t = datetime.now()
		print (t)
        # some funct to repare initial data
		self.rt = RepeatedTimer(60, self.Runevery5min)
	def launch_Thread_run(self):
		self.r = threading.Thread(target=self.run())
		self.r.start()

	def stop_thread(self):
		self.rt.stop()
		self.lineEdit.setText("Stoped....")


class RepeatedTimer(object):                                       
    # Here's an update to the code from MestreLion that avoids drifiting over time
    # https://stackoverflow.com/questions/474528/what-is-the-best-way-to-repeatedly-execute-a-function-every-x-seconds-in-python
  def __init__(self, interval, function, *args, **kwargs):
    self._timer = None
    self.interval = interval
    self.function = function
    self.args = args
    self.kwargs = kwargs
    self.is_running = False
    self.next_call = time.time()
    self.start()

  def _run(self):
    self.is_running = False
    self.start()
    self.function(*self.args, **self.kwargs)

  def start(self):
    if not self.is_running:
      self.next_call += self.interval
      self._timer = threading.Timer(self.next_call - time.time(), self._run)
      self._timer.start()
      self.is_running = True

  def stop(self):
    self._timer.cancel()
    self.is_running = False



if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Form = QtGui.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())
Henry viết 16:03 ngày 01/10/2018

Tại vì nó phải chạy xong hàm delayfunc rồi mới excute. Mình không rành lắm về cái này nên không rõ có parameter nào hỗ trợ không. Thế nên bạn cứ run cái đó trước sau đó rồi hẵng dùng timer run.

HK boy viết 15:56 ngày 01/10/2018

self.rt = RepeatedTimer(60, self.Runevery5min)

Do dòng này.

Bạn có thể làm theo cách thô thiển nhất, là chạy chương trình 1 lần trước đã, rồi mới bắt đầu gọi dòng này, hoặc tạo 1 biến là checkFirstTime để kiểm tra có phải lần đầu chạy chương trình hay không, nếu True thì chạy hàm ngay, nếu không thì đợi.

P/s: 5 phút có bằng 60s đâu mà bạn để timer = 60s?

AL viết 16:04 ngày 01/10/2018

Em để 60s để test thử xem nó chạy thế nào trước đã. Vẫn chưa hiểu lắm cách anh chỉ.

Bài liên quan
0