QLabel 不重绘像素图
QLabel doesn't repaint pixmap
我正在尝试制作一个转盘播放器,它可以在按住鼠标左键并向左或向右拖动时翻阅图像序列。它几乎可以工作并且正在打印出正确的图像名称。但是图片本身没有update/repaint.
如果我从 eventFilter 方法的最后一行中删除 return True
,它就会起作用。然而,它也会产生很多关于 eventFilter 想要布尔值 return 的抱怨。
3 个问题。我将如何解决这个问题?有没有比我做的更好的方法来做到这一点?也有没有让图像序列提前加载,这样它就不会在中途变慢?
谢谢。
__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_())
只有您不想传播到您的 children 的事件必须 return 为真,还有一些您不应该传播的事件。在您的特定情况下,有一些特定事件会迫使您更新 GUI,其中之一是鼠标事件,当您 return True 时,您正在阻止它们被更新。您的目标不是过滤元素,只是监听那些事件,因此建议 return 什么 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_())
我正在尝试制作一个转盘播放器,它可以在按住鼠标左键并向左或向右拖动时翻阅图像序列。它几乎可以工作并且正在打印出正确的图像名称。但是图片本身没有update/repaint.
如果我从 eventFilter 方法的最后一行中删除 return True
,它就会起作用。然而,它也会产生很多关于 eventFilter 想要布尔值 return 的抱怨。
3 个问题。我将如何解决这个问题?有没有比我做的更好的方法来做到这一点?也有没有让图像序列提前加载,这样它就不会在中途变慢?
谢谢。
__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_())
只有您不想传播到您的 children 的事件必须 return 为真,还有一些您不应该传播的事件。在您的特定情况下,有一些特定事件会迫使您更新 GUI,其中之一是鼠标事件,当您 return True 时,您正在阻止它们被更新。您的目标不是过滤元素,只是监听那些事件,因此建议 return 什么 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_())