python - pyqt中的QTimer会丢失时间吗?
问题描述
我做了一个小定时器应用程序。它似乎工作正常,但是当我在后台运行它时,计时器(使用 QTimer)不能正确运行。它失去了时间:经过 30 分钟后,有时计时器只减少了 10 分钟。
看着它,它似乎运行得并不慢。当我(在我的 Mac 上)切换桌面时会出现问题(尽管在其他一些情况下它也可能很慢)。我怎样才能防止这种情况?
具体来说:应用程序上有 TimerPanes。他们应该从设定的时间(如 3600 秒)开始倒计时。例如,当我在后台运行它并切换到观看视频时,可能会经过 10 分钟(我检查了我的系统时钟),但倒计时只会进行 5 分钟。
这是完整的代码,TimerPane 类是使用 QTimer 的类。您可以运行它,看看它是否也发生在您身上:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
Base = declarative_base()
class Task(Base):
__tablename__ = 'task'
id = Column(Integer, primary_key=True)
name = Column(String(1000), nullable=False)
time = Column(Integer, nullable=False, default=0)
color = Column(String(1000), nullable=False, default=0)
engine = create_engine('sqlite:///tasks.db')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
def Convert(t):
return "{}:{:0>2d}:{:0>2d}".format(t//3600,(t%3600)//60,t%60)
class MainWindow(QMainWindow):
def __init__(self, tasks, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setWindowTitle("Timer")
layout1 = QHBoxLayout()
layout1.addWidget(Frame(tasks))
layout1.setContentsMargins(0,0,0,0)
layout1.setSpacing(0)
self.widget = QWidget()
self.widget.setLayout(layout1)
self.scroll = QScrollArea()
self.scroll.setWidget(self.widget)
self.setCentralWidget(self.scroll)
self.scroll.setWidgetResizable(True)
self.setMinimumSize(100,200)
class Frame(QWidget):
def __init__(self, tasks, *args, **kwargs):
super(Frame, self).__init__(*args, **kwargs)
self.vbox = QVBoxLayout()
self.create = QPushButton("Create new task")
self.vbox.addWidget(self.create)
self.create.clicked.connect(self.showDialog)
self.setLayout(self.vbox)
for task in tasks:
self.vbox.addWidget(TimerPane(task))
def showDialog(self):
t=InputDialog()
if t.exec()==1:
name, time, color = t.getInputs()
obj = Task()
obj.name = name
obj.time = time
obj.color= color
session.add(obj)
session.commit()
self.vbox.addWidget(TimerPane(obj))
class TimerPane(QWidget):
def __init__(self, obj=None, *args, **kwargs):
super(TimerPane, self).__init__(*args, **kwargs)
self.setAutoFillBackground(True)
self.layout=QVBoxLayout()
BFont=QFont()
BFont.setBold(True)
IFont=QFont()
IFont.setItalic(True)
self.namelabel=QLabel()
self.namelabel.setFont(BFont)
self.layout.addWidget(self.namelabel)
self.timelabel=QLabel()
self.timelabel.setFont(IFont)
self.layout.addWidget(self.timelabel)
self.timeleftlabel=QLabel()
self.layout.addWidget(self.timeleftlabel)
self.setLayout(self.layout)
self.timeleft=0
self.time=0
self.name=''
if obj:
self.obj=obj
self.load()
self.active=False
self.deleteButton = QPushButton("Delete")
self.deleteButton.setSizePolicy(QSizePolicy.Fixed,
QSizePolicy.Fixed)
self.layout.addWidget(self.deleteButton)
self.deleteButton.clicked.connect(self.delete_widget)
def mousePressEvent(self, event):
if self.active:
self.timer_stop()
else:
self.timer_start()
def timer_timeout(self):
self.timeleft -= 1
if self.timeleft == 0:
self.timer_stop()
self.timeleft = self.obj.time
self.update_gui()
def timer_start(self):
self.my_qtimer = QTimer(self)
self.my_qtimer.timeout.connect(self.timer_timeout)
self.my_qtimer.start(1000)
self.active=True
self.update_gui()
def timer_stop(self):
self.my_qtimer.stop()
self.active=False
def update_gui(self,*args):
self.timeleftlabel.setText(Convert(self.timeleft))
def load(self):
p = self.palette()
p.setColor(self.backgroundRole(), QColor(self.obj.color))
self.setPalette(p)
self.name=self.obj.name
self.time=self.obj.time
self.timeleft=self.obj.time
try:
self.namelabel.setText(self.name)
self.timelabel.setText(Convert(self.time))
self.timeleftlabel.setText(Convert(self.timeleft))
self.active=False
except:
print("Error, invalid values, delting object")
self.delete_widget()
def delete_widget(self):
session.delete(self.obj)
session.commit()
self.deleteLater()
class InputDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.name = QLineEdit(self)
self.time = QLineEdit(self)
self.color= QColor(0, 0, 0).name()
layout = QFormLayout(self)
layout.addRow("Name", self.name)
layout.addRow("Time", self.time)
self.btn = QPushButton('Color', self)
layout.addWidget(self.btn)
self.btn.clicked.connect(self.showColor)
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, self);
layout.addWidget(buttonBox)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
def showColor(self):
col = QColorDialog.getColor()
if col.isValid():
self.color=col.name()
def getInputs(self):
return (self.name.text(), self.time.text(), self.color)
if __name__ == '__main__':
app = QApplication([])
app.setApplicationName("Timer")
existing_tasks = session.query(Task).all()
window=MainWindow(existing_tasks)
window.show()
app.exec_()
解决方案
推荐阅读
- r - 编写函数以将行添加到数据框中
- vba - 如果 IsNumeric(num) And Len(num) > 1 计算一个数字的 false ?
- python - Pandas,将元组列表转换为 DataFrame 尴尬的列标题。
- smalltalk - Smalltalk 的 message to:do: 是如何在幕后实现的?
- data-structures - 用于树的孩子的适当数据结构
- arrays - VBA循环将行添加到被错误覆盖的数组?
- html - 如何更改角度材料表单字段中所需生成的asterick css?
- android - 如何在新活动中正确打开 pdf?
- css - 将阴影添加到 svg 多边形
- unity3d - Unity 2018.2.7 100+ 项目创建错误