我正在windows10上使用python3.7并使用PyQt5作为GUI。在我的应用程序中,我得到了一个QScrollArea()
,里面有一组按钮。单击时,按钮必须移动到区域之外。我使用QPropertyAnimation()
来显示移动。你知道吗
我创建了一个用于测试的小应用程序。这个应用程序显示了一个小的QScrollArea()
,里面有一堆按钮。单击按钮时,它将向右移动:
代码如下:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class MyButton(QPushButton):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setFixedWidth(300)
self.setFixedHeight(30)
self.clicked.connect(self.animate)
return
def animate(self):
self.anim = QPropertyAnimation(self, b'position')
self.anim.setDuration(3000)
self.anim.setStartValue(QPointF(self.pos().x(), self.pos().y()))
self.anim.setEndValue(QPointF(self.pos().x() + 200, self.pos().y() - 20))
self.anim.start()
return
def _set_pos_(self, pos):
self.move(pos.x(), pos.y())
return
position = pyqtProperty(QPointF, fset=_set_pos_)
class CustomMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 600, 300)
self.setWindowTitle("ANIMATION TEST")
# OUTER FRAME
# ============
self.frm = QFrame()
self.frm.setStyleSheet("""
QFrame {
background: #d3d7cf;
border: none;
}
""")
self.lyt = QHBoxLayout()
self.frm.setLayout(self.lyt)
self.setCentralWidget(self.frm)
# BUTTON FRAME
# =============
self.btn_frm = QFrame()
self.btn_frm.setStyleSheet("""
QFrame {
background: #ffffff;
border: none;
}
""")
self.btn_frm.setFixedWidth(400)
self.btn_frm.setFixedHeight(200)
self.btn_lyt = QVBoxLayout()
self.btn_lyt.setAlignment(Qt.AlignTop)
self.btn_lyt.setSpacing(5)
self.btn_frm.setLayout(self.btn_lyt)
# SCROLL AREA
# ============
self.scrollArea = QScrollArea()
self.scrollArea.setStyleSheet("""
QScrollArea {
border-style: solid;
border-width: 1px;
}
""")
self.scrollArea.setWidget(self.btn_frm)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setFixedWidth(400)
self.scrollArea.setFixedHeight(150)
self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.lyt.addWidget(self.scrollArea)
# ADD BUTTONS TO BTN_LAYOUT
# ==========================
self.btn_lyt.addWidget(MyButton("Foo"))
self.btn_lyt.addWidget(MyButton("Bar"))
self.btn_lyt.addWidget(MyButton("Baz"))
self.btn_lyt.addWidget(MyButton("Qux"))
self.show()
return
if __name__== '__main__':
app = QApplication(sys.argv)
QApplication.setStyle(QStyleFactory.create('Plastique'))
myGUI = CustomMainWindow()
sys.exit(app.exec_())
当按钮移动时,它停留在QScrollArea()
。我需要把它放在一切之上:
谢谢你@magrif为我指明了正确的方向。多亏了你的建议,我才有了工作。你知道吗
所以我将animate()
函数改为:
def animate(self):
self.anim = QPropertyAnimation(self, b'position')
self.anim.setDuration(3000)
startpoint = self.mapToGlobal(self.pos())
endpoint = self.mapToGlobal(QPoint(self.pos().x() + 200, self.pos().y() - 20))
self.setWindowFlags(Qt.Popup)
self.show()
self.anim.setStartValue(QPointF(startpoint.x(), startpoint.y()))
self.anim.setEndValue(QPointF(endpoint.x(), endpoint.y()))
self.anim.start()
QTimer.singleShot(1000, self.hide)
return
请注意,我在按钮上安装了一个单次触发计时器。这是因为只要这个按钮表现为“弹出窗口”(因为self.setWindowFlags(Qt.Popup)
),Qt eventloop就会被阻塞。不管怎样,一次性计时器对我来说已经足够好了。你知道吗
不幸的是我还有一个问题。当我单击第一个按钮Foo时,它从最初的位置开始(几乎)动画。如果我点击另一个按钮,比如Baz,它会突然跳下大约100个像素并从那里开始动画。你知道吗
我认为这与startpoint = self.mapToGlobal(self.pos())
函数以及这些按钮位于QScrollArea()
中的事实有关。但我不知道怎么解决这个问题。你知道吗
我的目的是建立一个鼠标右键菜单,如下所示:
当用户单击“抓取并移动”时,按钮应该从QScrollArea()
中消失,并快速移向鼠标。当它到达鼠标指针时,按钮应该淡出,并且可以开始拖放操作。你知道吗
注:以下与本主题相关的问题是这个问题:
Qt: How to perform a drag-and-drop without holding down the mouse button?
小部件的位置是相对于其父部件的,因此不应使用
startpoint = self.mapToGlobal(self.pos())
,而应使用startpoint = self.mapToGlobal(QPoint())
,因为对于小部件,左上角的位置是QPoint(0, 0)
。你知道吗因此,如果要使用@magrif解决方案,应该将其更改为:
但缺点是,当动画运行时,不能与窗口交互。你知道吗
另一种解决方案是将QFrame的父级更改为窗口本身:
注意:不需要创建qproperty位置,因为qpropertypos已经存在。你知道吗
< C++中的P>作品::使用
mapToGlobal()
计算按钮的全局坐标。使用
setWindowFlags()
和show()
设置标志Qt.Popup
Init start和end值关联(1)中的全局坐标,并开始动画
相关问题 更多 >
编程相关推荐