Issue
I'm trying to make a turntable player that would flip through image sequences when holding left mouse button and drag left or right. It almost works and is printing out the correct image names. But the image itself does not update/repaint.
If I remove the return True
from last line of eventFilter method, it works. It will also produce lots of complain about eventFilter wanting a boolean return however.
3 questions. How would I fix this? Is there a better approach to do this than what I did? Also is there to get the image sequences to load in advance so it wouldn't slow down mid way?
Thank you.
Sample image sequence used in __name__ == '__main__'
: https://drive.google.com/open?id=1_kMf0bVZ5jMKdCQXzmOk_34nwwHOyXqz
# -*- coding: utf-8 -*-
import sys
from os.path import dirname, realpath, join
from PySide.QtGui import (QApplication, QVBoxLayout, QLabel, QPixmap,
QWidget)
from PySide import QtCore
class PlayTurntable(QWidget):
def __init__(self, images, mouse_threshold=50, parent=None):
super(PlayTurntable, self).__init__(parent)
self.label = QLabel()
self.label.setFixedWidth(300)
self.label.setFixedHeight(200)
layout = QVBoxLayout()
layout.addWidget(self.label)
self.setLayout(layout)
# init variables
self.tracking = False
self.mouse_start = 0
self.mouse_threshold = mouse_threshold
self.images = images
self.image_index = 0
self.pic = QPixmap(self.images[self.image_index])
self.label.setPixmap(self.pic.scaled(300, 200, QtCore.Qt.KeepAspectRatio))
self.installEventFilter(self)
def eventFilter(self, obj, event):
if event.type() == event.MouseButtonPress:
if event.button() == QtCore.Qt.LeftButton:
self.mouse_start = event.x()
self.tracking = True
event.accept()
if event.type() == event.MouseButtonRelease:
if event.button() == QtCore.Qt.LeftButton:
self.tracking = False
event.accept()
if event.type() == event.MouseMove:
if self.tracking:
mouse_x = event.x()
distance = self.mouse_start - mouse_x
if abs(distance) >= self.mouse_threshold:
self.mouse_start = mouse_x
if distance > 0:
self.frame_step(1)
else:
self.frame_step(-1)
event.accept()
return True
def frame_step(self, amount):
self.image_index += amount
if self.image_index >= len(self.images):
self.image_index = 0
elif self.image_index < 0:
self.image_index = len(self.images) - 1
print 'switching to: %s' % self.images[self.image_index]
self.pic.load(self.images[self.image_index])
self.label.setPixmap(
self.pic.scaled(300, 200, QtCore.Qt.KeepAspectRatio))
self.label.repaint()
if __name__=='__main__':
current_path = dirname(realpath(__file__))
images = ['turn1.jpg', 'turn2.jpg', 'turn3.jpg', 'turn4.jpg']
for index, value in enumerate(images):
images[index] = join(current_path, value)
app = QApplication(sys.argv)
PT = PlayTurntable(images)
PT.show()
sys.exit(app.exec_())
Solution
Only the events that you want not to be propagated to your children must return True, and there are others that you should not. In your particular case there are particular events that force you to update the GUI, and one of them is the mouseevent, and when you return True you are preventing them from being updated. Your goal is not to filter elements, just listen to those events so it is advisable to return what the parent returns.
# -*- coding: utf-8 -*-
import sys
from os.path import dirname, realpath, join
from PySide.QtGui import (QApplication, QVBoxLayout, QLabel, QPixmap,
QWidget)
from PySide.QtCore import Qt
class PlayTurntable(QWidget):
def __init__(self, images, mouse_threshold=50, parent=None):
super(PlayTurntable, self).__init__(parent)
self.label = QLabel()
self.label.setFixedSize(300, 200)
layout = QVBoxLayout(self)
layout.addWidget(self.label)
# init variables
self.tracking = False
self.mouse_start = 0
self.mouse_threshold = mouse_threshold
self.images = images
self.image_index = 0
self.pic = QPixmap(self.images[self.image_index])
self.label.setPixmap(self.pic.scaled(300, 200, Qt.KeepAspectRatio))
self.installEventFilter(self)
def eventFilter(self, obj, event):
if event.type() == event.MouseButtonPress:
if event.button() == Qt.LeftButton:
self.mouse_start = event.x()
self.tracking = True
elif event.type() == event.MouseButtonRelease:
if event.button() == Qt.LeftButton:
self.tracking = False
elif event.type() == event.MouseMove:
if self.tracking:
mouse_x = event.x()
distance = self.mouse_start - mouse_x
if abs(distance) >= self.mouse_threshold:
self.mouse_start = mouse_x
if distance > 0:
self.frame_step(1)
else:
self.frame_step(-1)
return QWidget.eventFilter(self, obj, event)
def frame_step(self, amount):
self.image_index += amount
self.image_indes = (self.image_index + amount) % len(self.images)
print('switching to: %s' % self.images[self.image_index])
self.pic.load(self.images[self.image_index])
self.label.setPixmap(self.pic.scaled(300, 200, Qt.KeepAspectRatio))
if __name__=='__main__':
current_path = dirname(realpath(__file__))
images = ['turn1.jpg', 'turn2.jpg', 'turn3.jpg', 'turn4.jpg']
for index, value in enumerate(images):
images[index] = join(current_path, value)
app = QApplication(sys.argv)
PT = PlayTurntable(images)
PT.show()
sys.exit(app.exec_())
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.