【发布时间】:2018-02-13 04:21:34
【问题描述】:
因此,我目前在 QListView 中显示了一个视频剪辑列表,并创建了一个自定义委托来使用来自 QStandardItemModel 的数据为它们绘制预览缩略图。
最终,我希望能够在您将鼠标悬停在缩略图上时为其设置动画,以便它们播放剪辑的预览(仅显示几帧)。我想要这个的两个版本。一个只是播放,另一个根据您的鼠标位置显示帧(进一步向左是剪辑的开头,当您向右移动时,它会擦过)。
现在我正试图弄清楚如何实现动画片段。我是否应该使用委托来绘制框架并更新模型上的自定义框架数据,委托将使用该数据来了解使用重新实现的绘制函数绘制哪些帧(那里已经有了绘制函数的框架)?或者这会不会太耗费资源?那么最好的方法是什么?我查看了编辑器小部件,但那些似乎不是实时编辑模型数据/更新委托,而是仅在完成编辑后。此外,我希望它在鼠标悬停时初始化,这似乎不是内置编辑触发器中的选项。
class AnimatedThumbDelegate(QItemDelegate):
def __init__(self,parent=None):
super().__init__(parent)
self.height=200
self.width=self.height*1.77
self.frames=10
def paint(self,painter,option,index):
painter.save()
image=index.data(FootageItem.FILMSTRIP)
if not image.isNull():
painter.drawPixmap(QRect(option.rect),image,QRect(image.width()/self.frames*index.data(FootageItem.FRAME),0,image.width()/self.frames,image.height()))
painter.restore()
def sizeHint(self,option,index):
return QSize(self.width,self.height)
此委托绘制我用于预览帧的条形图像的一部分,并通过引用帧数据来实现。 FootageItem 只是一个 QStandardItem 类,它帮助构建我想要为这些剪辑存储的数据,我只是在这里使用它的索引。它从我的模型中获取 QPixmap。我使用的幻灯片图像如下所示:
我可以使用编辑器小部件来更新值并根据 mouseMoveEvents 在委托对象上强制重绘吗?然后我可以让编辑器出现在鼠标悬停上吗?或者我应该看看重新实现 QListView 以使用鼠标事件更新委托?还是有其他我没发现的方法?
我制作了一个小部件,它的行为大致与我希望更新框架部分的工作方式相同,但希望将其移植到委托类而不是 QWidget,以便我可以让它显示表格中的数据并利用QT 必须提供的模型/视图编程。
class ScrollingThumbnail(QWidget):
def __init__(self,parent,image,rect):
super().__init__(parent)
self.image=image
self.paused=False
self.frame=5
self.frames=10
self.bar=False
self.vis=True
self.thumbRect=rect
self.setMouseTracking(True)
def leaveEvent(self):
self.stop()
def mouseMoveEvent(self,e):
if(e.pos().y()>self.height*0.6):
self.bar=True
self.pause()
self.frame=int(e.pos().x()/(self.width/self.frames))
self.repaint()
elif self.paused:
self.paused=False
self.bar=False
self.play()
def paintEvent(self,e):
qP=QPainter()
qP.begin(self)
if self.vis:
self.drawWidget(qP)
qP.end()
def drawWidget(self,qP):
if not self.image.isNull():
qP.drawPixmap(self.thumbRect,self.image,QRect(self.image.width()/self.frames*self.frame,0,self.image.width()/self.frames,self.image.height()))
if self.bar:
pen=QPen(QColor(255,255,255,50),self.height/60,cap=Qt.RoundCap)
qP.setPen(pen)
off=self.height/20
inc=((self.width-(off*2))/(self.frames-1))
qP.drawLine(off,self.height-off-20,off+(inc)*(self.frame),self.height-off-20)
def play(self):
if not self.paused:
self.frame=(self.frame+1)%self.frames
self.repaint()
self.timer=threading.Timer(0.1,self.play)
self.timer.start()
def pause(self):
try:
self.timer.cancel()
except:
pass
self.paused=True
def stop(self):
try:
self.timer.cancel()
except:
pass
self.frame=5
self.repaint()
它使用线程计时器作为循环播放帧的廉价黑客方式。可能会更多地寻找更好的方法来实现这一点(可能使用 QThread?)还有一个它的 gif 效果,就所需的行为而言:i.imgur.com/aKoKs3m.gifv
干杯, 亚历克斯
【问题讨论】:
-
据我所见,您有一个图像,根据情况,需要一个片段并且必须在委托中显示。你想使用什么鼠标事件:mousePressEvent、mouseMoveEvent、mouseReleaseEvent?行为应该是什么,请提供更多详细信息?如果它正在使用它显示的图像,那就太好了。
-
这是一个我希望它如何操作的示例(我在走代理路线之前制作的小部件版本的屏幕截图)。 i.imgur.com/aKoKs3m.gifv 当您将鼠标移到图像上时,这一切都会发生。根据您的光标是在顶部还是底部滚动条式部分上切换播放“模式”。所以可能是mouseMoveEvent。
-
从我通常看到的图像序列显示,并且通过鼠标可以控制序列,您可以显示该代码。
-
更新了原来的帖子。这是一个小部件的代码,这是我最初的方法,虽然我假设使用委托是要走的路?特别是在有很多条目的情况下,并且希望以后能够过滤/排序它们。
-
图片是QPixmap还是QImage?
标签: python pyqt real-time-updates qitemdelegate