gpt4 book ai didi

multithreading - 从线程修改QGraphicsItem的正确方法?

转载 作者:行者123 更新时间:2023-12-03 13:12:45 27 4
gpt4 key购买 nike

我正在制作吉他谱软件,开始播放时,图形会每16个音符更新一次(例如,通过将光标移到右边的一个空格)。我在弄清楚如何从没有问题的线程中更新QGraphicsItems时遇到麻烦。在下面的示例中(从原始程序简化),我使用QThread进行回放,并每0.02秒在右侧重新绘制一个QGraphicsRectItem。问题在于,即使停止播放,矩形也经常冻结并保持冻结状态。

谁能让我知道从线程更新QGraphicsView的更好方法是什么?

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import random
import sys
import threading

from PyQt4 import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()

# add TablatureWindow
self.tabWidget = QtGui.QTabWidget()
self.setCentralWidget(self.tabWidget)
self.setWindowTitle('Tablature Editor')

self.tablatureWindow = TablatureWindow(self)
self.tabWidget.removeTab(0)
self.tabWidget.addTab(self.tablatureWindow, 'Untitled')
self.tablatureWindow.setFocus()

self.positionWindow() # center and enlargen window

self.show()

def positionWindow(self):
qr = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
width = QtGui.QDesktopWidget().availableGeometry().width() - 100
height = QtGui.QDesktopWidget().availableGeometry().height() - 100
self.resize(width, height)
qr = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())


class TablatureWindow(QtGui.QGraphicsView):
def __init__(*args, **kwargs):
start_time = time.time()

self = args[0]
self._parent = args[1]

QtGui.QGraphicsView.__init__(self)
self.scene = QtGui.QGraphicsScene(self)
self.setScene(self.scene)

self.scene.setSceneRect(QtCore.QRectF(0, 0, 20000, 2000))

self.cursorItem = QtGui.QGraphicsRectItem(100, 100, 20, 20)
self.cursorItem.setBrush(QtCore.Qt.black)
self.scene.addItem(self.cursorItem)
self.centerOn(0,0)

self.isPlaying = False


def keyPressEvent(self, e):
key = e.key()

# "p" starts or stops playback
if key == QtCore.Qt.Key_P:
if self.isPlaying == False:
self.beginPlayback()
else:
self.stopPlayback()

def beginPlayback(self):
print('begin')
self.isPlaying = True

self.playbackThread = PlaybackThread(self)
self.playbackThread.start()

def stopPlayback(self):
print('stop')
self.isPlaying = False

self.playbackThread.stopPlayback()


class PlaybackThread(QtCore.QThread):
def __init__(self, parent):
QtCore.QThread.__init__(self)
self._parent = parent

self.doStopThread = False

def run(self):
self.startTime = time.time()

dt = 0.02 # move every dt seconds

for i in range(0, 2000): # keep going right for 1000 spaces
if not self.doStopThread:

x = self._parent.cursorItem.rect().x()
y = self._parent.cursorItem.rect().y()
w = self._parent.cursorItem.rect().width()
h = self._parent.cursorItem.rect().height()

self._parent.cursorItem.setRect(x+10, y, w, h)

ideal_dt = (i+1) * dt + self.startTime
dt2 = ideal_dt-time.time()
time.sleep(dt2) # sleep for remaining time


def stopPlayback(self):
self.doStopThread = True

def __del__(self):
self.wait()


def main():

app = QtGui.QApplication(sys.argv)
ex = MainWindow()
sys.exit(app.exec_())


if __name__ == '__main__':
main()

最佳答案

我想通过用QTimer替换线程找到了部分答案:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import random
import sys
import threading

from PyQt4 import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()

# add TablatureWindow
self.tabWidget = QtGui.QTabWidget()
self.setCentralWidget(self.tabWidget)
self.setWindowTitle('Tablature Editor')

self.tablatureWindow = TablatureWindow(self)
self.tabWidget.removeTab(0)
self.tabWidget.addTab(self.tablatureWindow, 'Untitled')
self.tablatureWindow.setFocus()

self.positionWindow() # center and enlargen window

self.show()

def positionWindow(self):
qr = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
width = QtGui.QDesktopWidget().availableGeometry().width() - 100
height = QtGui.QDesktopWidget().availableGeometry().height() - 100
self.resize(width, height)
qr = self.frameGeometry()
cp = QtGui.QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())


class TablatureWindow(QtGui.QGraphicsView):
def __init__(*args, **kwargs):
start_time = time.time()

self = args[0]
self._parent = args[1]

QtGui.QGraphicsView.__init__(self)
self.scene = QtGui.QGraphicsScene(self)
self.setScene(self.scene)

self.scene.setSceneRect(QtCore.QRectF(0, 0, 20000, 2000))

self.cursorItem = QtGui.QGraphicsRectItem(100, 100, 20, 20)
self.cursorItem.setBrush(QtCore.Qt.black)
self.scene.addItem(self.cursorItem)
self.centerOn(0,0)

self.isPlaying = False


def keyPressEvent(self, e):
key = e.key()

# "p" starts or stops playback
if key == QtCore.Qt.Key_P:
if self.isPlaying == False:
self.beginPlayback()
else:
self.stopPlayback()

def beginPlayback(self):
print('begin')
self.isPlaying = True

self.playback = Playback(self)

def stopPlayback(self):
print('stop')
self.isPlaying = False

self.playback.stopPlayback()


class Playback:
def __init__(self, parent):
self._parent = parent

self.timer = QtCore.QTimer()
QtCore.QObject.connect(
self.timer,
QtCore.SIGNAL("timeout()"),
self.doStuff)

self.timer.start(20) # 20 ms

def doStuff(self):
x = self._parent.cursorItem.rect().x()
y = self._parent.cursorItem.rect().y()
w = self._parent.cursorItem.rect().width()
h = self._parent.cursorItem.rect().height()

self._parent.cursorItem.setRect(x+10, y, w, h)

self._parent.update()

def stopPlayback(self):
self.timer.stop()

def main():

app = QtGui.QApplication(sys.argv)
ex = MainWindow()
sys.exit(app.exec_())


if __name__ == '__main__':
main()

尽管我确实看到了一些图形故障,例如在滚动窗口时从移动的矩形中留下了一些小矩形,但我再也看不到冻结了(无论如何)。

关于multithreading - 从线程修改QGraphicsItem的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21513824/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com