如何解决PyQt5 将 QImage 放在小部件中
我创建了一个允许我绘制数字的小图形用户界面。这个数字应该用 CNN 分类。 CNN 尚未连接到此 GUI。以后会这样做。我对 PyQt5 仍然很陌生,并使用了我在网上找到的一些代码来使用 QImage 进行绘图。它有效,但目前我可以在整个 GUI 上绘制。是否可以将其放在小部件中?这样我只能在特定的框架内绘制,而不能在整个 GUI 中绘制?
所以基本上我怎样才能在小部件或我之前在我的 GUI 上创建的东西旁边获得 self.image = QImage(...) ?这是否可能以某种方式或您甚至建议以完全不同的方式解决它?
import sys
from PyQt5 import QtWidgets
from PyQt5.QtGui import QIcon,QImage,QPainter,QPen,QBrush
from PyQt5.QtCore import Qt,QPoint
from UI.mainwindow_2 import Ui_MainWindow
import matplotlib.pyplot as plt
import numpy as np
class MainWindow(QtWidgets.QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.image = QImage(self.size(),QImage.Format_RGB32)
self.image.fill(Qt.white)
self.drawing = False
self.brushSize = 28
self.brushColor = Qt.black
self.lastPoint = QPoint()
self.ui.Clear.clicked.connect(self.clear)
def mousepressEvent(self,event):
if event.button() == Qt.LeftButton:
self.drawing = True
self.lastPoint = event.pos()
def mouseMoveEvent(self,event):
if(event.buttons() & Qt.LeftButton) & self.drawing:
painter = QPainter(self.image)
painter.setPen(QPen(self.brushColor,self.brushSize,Qt.solidLine,Qt.RoundCap,Qt.RoundJoin))
painter.drawLine(self.lastPoint,event.pos())
self.lastPoint = event.pos()
self.update()
def mouseReleaseEvent(self,event):
if event.button() == Qt.LeftButton:
self.drawing = False
def paintEvent(self,event):
canvasPainter = QPainter(self)
canvasPainter.drawImage(self.rect(),self.image,self.image.rect())
def clear(self):
self.image.fill(Qt.white)
self.update()
def main():
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
解决方法
首先要考虑以下几个方面:
- 任何(可见的)QWidget 子类都会接收到绘制事件
- 绘画总是受限于小部件的几何形状
- 绘制总是从底部到顶部进行,因此每当小部件有一些子部件时,在该父部件上绘制的任何内容都可能被这些子部件覆盖
因此,首先要做的是仅在要为其绘制的实际小部件上实现paintEvent。由于您使用的是 Designer,这会使事情变得更加复杂,因为无法对 ui 中已存在的小部件进行子类化。
幸运的是,Qt 有一个名为“promoted widgets”的概念:它允许通过指定在程序中最终生成 ui 时实际使用的自定义子类来“扩展”某个小部件。
- 选择用户界面中的哪个小部件将用于绘画;我建议你从一个基本的 QWidget 开始,我稍后会详细解释;
- 右键单击它,然后从上下文菜单中选择“升级到...”;
- 在“Promoted class name”中输入您要使用的确切类名(比如“Canvas”);
- 在“头文件”字段中,输入将包含该类的文件名,因为它将出现在
import
语句中(意味着它应该不具有 {{ 1}} 扩展名!);假设您想在单个脚本中完成所有操作,并且您的脚本名为“mycanvas.py”,请在该字段中输入“mycanvas”; - 确保“基类名称”组合设置为您选择的小部件的确切类类型(QWidget,在这种情况下,通常会自动选择)
- 点击“添加”,然后点击“推广”;
- 保存ui并用pyuic生成文件;
现在,您的 py
文件的实现很简单:
mycanvas.py
两个注意事项:
- QFrame 通常有一些边框,并且由于绘制总是在整个 小部件大小内进行,因此您最终也可能在边框上进行绘制。如果你想要一个 QFrame 并在里面绘制那个小部件,那么将一个 QWidget 作为那个框架的子元素添加并确保为该框架设置了布局;
- 在 init 中设置 QImage 大小不是一个好方法,因为小部件可能会改变它的大小,或者它可能会被初始化为小于它最终拥有的大小;您可以在创建 QImage 之前在
class Canvas(QtWidgets.QWidget): def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) self.image = QImage(self.size(),QImage.Format_RGB32) self.image.fill(Qt.white) self.drawing = False self.brushSize = 28 self.brushColor = Qt.black self.lastPoint = QPoint() # ... all the painting related methods,as you did in your code class MainWindow(QtWidgets.QMainWindow): def __init__(self,parent=None): super().__init__(parent) self.ui.Clear.clicked.connect(self.ui.canvas.clear) def main(): # ...
中设置固定大小,或者跟踪内部容器中的点/线并在paintEvent 中连续绘制内容;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。