我正在学习 python 和 PySide2 并跟进 learnpytq 的一些教程,特别是 https://www.learnpyqt.com/courses/custom-widgets/bitmap-graphics/我被困在了一个点上。
在创建像素图 Canvas 之后,我们在小部件上移动 mouseMoveEvent 以确保鼠标的坐标始终相对于 Canvas 。我已经复制了提供的源代码,但仍在我正在运行的应用程序中,鼠标位置是相对于窗口(或父小部件,我不确定),导致绘制的线偏移到鼠标位置。
代码如下:
import sys
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import Qt
class Canvas(QtWidgets.QLabel):
def __init__(self):
super().__init__()
pixmap = QtGui.QPixmap(600, 300)
self.setPixmap(pixmap)
self.last_x, self.last_y = None, None
self.pen_color = QtGui.QColor('#000000')
def set_pen_color(self, c):
self.pen_color = QtGui.QColor(c)
def mouseMoveEvent(self, e):
if self.last_x is None: # First event.
self.last_x = e.x()
self.last_y = e.y()
return # Ignore the first time.
painter = QtGui.QPainter(self.pixmap())
p = painter.pen()
p.setWidth(4)
p.setColor(self.pen_color)
painter.setPen(p)
painter.drawLine(self.last_x, self.last_y, e.x(), e.y())
painter.end()
self.update()
# Update the origin for next time.
self.last_x = e.x()
self.last_y = e.y()
def mouseReleaseEvent(self, e):
self.last_x = None
self.last_y = None
COLORS = [
# 17 undertones https://lospec.com/palette-list/17undertones
'#000000', '#141923', '#414168', '#3a7fa7', '#35e3e3', '#8fd970', '#5ebb49',
'#458352', '#dcd37b', '#fffee5', '#ffd035', '#cc9245', '#a15c3e', '#a42f3b',
'#f45b7a', '#c24998', '#81588d', '#bcb0c2', '#ffffff',
]
class QPaletteButton(QtWidgets.QPushButton):
def __init__(self, color):
super().__init__()
self.setFixedSize(QtCore.QSize(24,24))
self.color = color
self.setStyleSheet("background-color: %s;" % color)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.canvas = Canvas()
w = QtWidgets.QWidget()
l = QtWidgets.QVBoxLayout()
w.setLayout(l)
l.addWidget(self.canvas)
palette = QtWidgets.QHBoxLayout()
self.add_palette_buttons(palette)
l.addLayout(palette)
self.setCentralWidget(w)
def add_palette_buttons(self, layout):
for c in COLORS:
b = QPaletteButton(c)
b.pressed.connect(lambda c=c: self.canvas.set_pen_color(c))
layout.addWidget(b)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
谁能发现我做错了什么?
最佳答案
问题在于您是根据 widget 坐标绘制的,而不是实际“ Canvas ”(“嵌入式”像素图)的坐标,如果QLabel 的可用空间大于 QPixmap 的大小。
例如,如果图像垂直居中,您调整窗口大小并且标签高度变为 400(大于像素图高度),每当您单击位置 100, 100
时,该位置实际上将垂直平移 50 像素(标签的高度减去图像的高度,除以 2)。
要根据像素图实际获得位置,您必须自己计算,然后相应地平移鼠标点:
def mouseMoveEvent(self, e):
if self.last_x is None: # First event.
self.last_x = e.x()
self.last_y = e.y()
return # Ignore the first time.
rect = self.contentsRect()
pmRect = self.pixmap().rect()
if rect != pmRect:
# the pixmap rect is different from that available to the label
align = self.alignment()
if align & QtCore.Qt.AlignHCenter:
# horizontally align the rectangle
pmRect.moveLeft((rect.width() - pmRect.width()) / 2)
elif align & QtCore.Qt.AlignRight:
# align to bottom
pmRect.moveRight(rect.right())
if align & QtCore.Qt.AlignVCenter:
# vertically align the rectangle
pmRect.moveTop((rect.height() - pmRect.height()) / 2)
elif align & QtCore.Qt.AlignBottom:
# align right
pmRect.moveBottom(rect.bottom())
painter = QtGui.QPainter(self.pixmap())
p = painter.pen()
p.setWidth(4)
p.setColor(self.pen_color)
painter.setPen(p)
# translate the painter by the pmRect offset; note the negative sign
painter.translate(-pmRect.topLeft())
painter.drawLine(self.last_x, self.last_y, e.x(), e.y())
painter.end()
self.update()
# Update the origin for next time.
self.last_x = e.x()
self.last_y = e.y()
关于python - 鼠标移动事件上的鼠标位置设置在父项而不是子项上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59047167/