PyQt学习Ⅴ(在pyqt中拖放和绘制图形)

在PyQt5中拖放

在计算机图形用户界面中,拖放是单击虚拟对象并将其拖动到其他位置或另一个虚拟对象的动作(或支持其动作)。通常,它可用于调用多种操作,或在两个抽象对象之间创建各种类型的关联。拖放是图形用户界面的一部分。拖放操作使用户能够直观地执行复杂操作。通常,我们可以拖放两件事:数据或一些图形对象。如果我们将图像从一个应用程序拖到另一个应用程序,我们拖放二进制数据。如果我们在Firefox中拖动一个标签并将其移动到另一个位置,我们就会拖放一个图形组件。

QDrag

QDrag提供对基于MIME的拖放数据传输的支持。它处理拖放操作的大部分细节。传输的数据包含在QMimeData对象中。

简单的拖放

在第一个例子中,我们有一个QLineEdit和一个 QPushButton。我们从行编辑小部件拖动纯文本并将其拖放到按钮小部件上。按钮的标签将会改变。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第1张图片

 

该示例提供了简单的拖放操作。

class Button(QPushButton):      

    def __init__(self, title, parent):       

         super().__init__(title, parent)        

In order to drop text on the QPushButton widget, we must reimplement some methods. Therefore, we create our own Button class which will inherit from the QPushButton class.(为了让拖拽过来的文本落在按钮部件上,我们必须重写某些方法,因为,我们创造了我们自己的Button类,它继承于QPushButton类。)

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第2张图片

 

这个parent就理解为按钮是在哪个窗口上的,这个parent输入的就是那个窗口,默认是没有,None,窗口一般都是QWidget类或者子类。我们这里用的是第二种形式,和button = Button("Button", self)是对应的,str="Button",parent=self。

这里稍微扩充一下QMainWindow的知识,以前我们知道它是继承于QWidget的,并且它有自己的布局。像菜单,状态栏,工具栏等在QWidget类里面没有直接定义的方法,而在QMainWindow里面我们是有的,也正是由于QMainWindow有自己的布局,我们以前曾经试过给QMainWindow使用setLayout会给出提示信息,说这个窗口已经有布局了。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第3张图片

 

self.setAcceptDrops(True)

We enable drop events for the widget with setAcceptDrops().(我们用setAcceptDrops()来启动drop事件。)这个后面会实际尝试一下效果。

def dragEnterEvent(self, e):        

    if e.mimeData().hasFormat('text/plain'):       

         e.accept()    

    else:        

        e.ignore()

First, we reimplement the dragEnterEvent() method. We inform about the data type that we accept. In our case it is plain text.(首先,我们重写了dragEnterEvent方法,我们选择我们要接受的数据类型,在上面例子里,我们接受的是纯文本)。

def dropEvent(self, e):    

    self.setText(e.mimeData().text())

By reimplementing the dropEvent() method we define what happes at the drop event. Here we change the text of the button widget.(通过重写dropEvent方法,我们重新定义了drop事件里面的内容,这里我们改变按钮部件上显示的文本。)

关于上面两个事件,参考了https://blog.csdn.net/vvsxr/article/details/49384199。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第4张图片

 

 

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第5张图片

 

 

 

我们先来看一下效果:

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第6张图片

 

当我拖拽文本的时候,按钮出现了一个+号,这个其实是e.accept()的结果,然后松开鼠标按键,文本就出现在了按钮上。

e是QDragEnterEvent的一个实例。关于这个QDragEnterEvent,参考了http://doc.qt.io/qt-5/qdragenterevent.html。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第7张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第8张图片

 

点所有成员的列表。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第9张图片

 

这里面有accept和ignore,我们点进去看看。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第10张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第11张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第12张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第13张图片

 

返回要落下的数据和它相关的MIME信息。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第14张图片

 

看来我们还得学一下QMimeData。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第15张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第16张图片

 

tester是检测函数,getter是得到函数,setter是发送函数。我们上面得例子里,用到了tester和getter。后面得MIME Types是一些数据类型的表示格式。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第17张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第18张图片

 

到此为止和上面例子相关的知识算是学完了,我们来实践一下。

 

看来默认按钮的self.setAcceptDrops()不是true。不过也可以理解,按钮一般也不会设为true,只是我们例子里有这么个特殊要求。还需要说明的是DragEnterEvent必须重写,虽然我不知道QPushButton默认的是什么,但是经过尝试这个例子里面必须要重写。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第19张图片

 

我们看到没有设置LineEdit的setAcceptDrops,但是可以直接落下,说明文本框默认的就是true,并且dragEnterEvent,dropEvent默认的设置都是可以直接拖拽过来加入文本内容的。不过这对文本框来说也是正常的设置吧,因为文本框很多时候确实会有这种需求,至少比按钮多。

这个例子结束了总结一下整个过程中的条件。    

 设置按钮可以在鼠标按键松开时文本:self.setAcceptDrops(True)。

重写按钮的dragEnterEvent可以接受文本:def dragEnterEvent(self, e):              if e.mimeData().hasFormat('text/plain'):            e.accept()        else:            e.ignore()

重写按钮的dropEvent,改变按钮的文本:    def dropEvent(self, e):                self.setText(e.mimeData().text())。还必须要把文本设为可以拖拽的:edit.setDragEnabled(True)。

拖放按钮小部件

在下面的示例中,我们将演示如何拖拽按钮小部件。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第20张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第21张图片

 

把show方法写在类定义外面也没什么,只是执行的时间稍稍延后而已。在我们的代码示例中,我们在窗口中有一个QPushButton。如果我们用鼠标左键单击按钮,则会在控制台上打印“按下”消息。通过右键单击并移动按钮,我们对按钮小部件执行拖拽操作。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第22张图片

 

dropAction = drag.exec_(Qt.MoveAction)

拖动对象的exec_()方法开始拖放操作。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第23张图片

 

找到QPushButton的mouseMoveEvent。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第24张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第25张图片

 

下面的不变指的是const,指的是常值。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第26张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第27张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第28张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第29张图片

 

先来试一下,看看是什么效果,经过我之前的尝试,已知的可以删掉的语句我都注释掉了,另外我加了三句print以便更好的理解程序。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第30张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第31张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第32张图片

 

效果:

 

其实下面这一行也可以不要,我们就不去看它什么意思了。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第33张图片

 

dropAction = drag.exec_(Qt.MoveAction)这一行是必须要的,不然按钮移动不了。

 

这个文档里面没加_是因为文档是c++,c++里面,exec应该不是关键字,但是在python里面是,所以就需要加_。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第34张图片

 

找了各种文档居然没找到这个Qt.MoveAction。最后还是在https://blog.csdn.net/q408384053/article/details/8171803找到一点信息。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第35张图片

 

其实这个参数甚至可以不要。来试一下:

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第36张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第37张图片

 

 

 

上面的gif主要是想说明下面这四句对于拖动按钮来说是必须有的,还有注意看这种拖放方式,只有在鼠标按键松时,按钮位置才会变,也就是说按钮运动的轨迹并不能显示,这其实有点不符合我们的习惯或者说预期。

        mimeData = QMimeData()

        drag = QDrag(self)

        drag.setMimeData(mimeData)

        drag.exec_()#类似于app.exec_(),不执行这个,拖放没办法执行;还有show(),没有的话窗口没办法显示。但是其实我可以完全不用QDrag,也能实现,并且更符合我们的习惯,可显示运动轨迹。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第38张图片

 

效果:

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第39张图片

 

实现按住鼠标右键不松开时按钮跟随鼠标移动,松开时按钮固定位置。

在PyQt5中绘画

PyQt5绘画系统能够渲染矢量图形,图像和轮廓基于字体的文本。当我们想要更改或增强现有小部件时,或者如果我们从头开始创建自定义小部件时,在应用程序中需要绘画。为了绘图,我们使用PyQt5工具包提供的绘图API。

QPainter

QPainter在小部件和其他绘图设备上执行低级绘制。它可以绘制从简单线条到复杂形状的所有内容。

paintEvent方法

这幅画是在这个paintEvent()方法中完成的。绘图代码放在QPainter对象的方法begin()和 end()方法之间。它在小部件和其他绘图设备上执行低级绘制。

Drawing Text(绘制文本)

我们首先在窗口的客户区域上绘制一些Unicode文本。

 

在我们的例子中,我们在Cylliric中绘制了一些文本。文本垂直和水平对齐。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第40张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第41张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第42张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第43张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第44张图片

 

翻译:开始在paint device上绘制,如果成功,返回真,否则返回假,注意所有的绘制设置(setPen,setBrush等)都会在begin被调用的时候重置为默认值。可能会有一些比较严重的错误发生,见下图,注意大多数时候,你可以使用一个constructors而不是begin,这样的话,end在结束的时候会被自动调用。警告:一个paint device一次只能被一个painter来使用绘制图形。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第45张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第46张图片

 

QWidget时QPaintDevice的一个子类。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第47张图片

 

        再来看一下这三句的意思:p.setPen(QColor(168, 34, 3))

        qp.setFont(QFont('Decorative', 10))

        qp.drawText(event.rect(), Qt.AlignCenter, self.text)

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第48张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第49张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第50张图片

 

翻译:把painter的颜色设置为给定的颜色。后续的drawText()函数使用此字体。文字颜色与前面的setPen颜色相同。如果你设置了一个不可用的字体,Qt会使用最相近的。font()函数会返回setFont里的字体,fnotinfo()返回真正使用的字体,这两个字体可能一样,但也可能不一样,因为你可能在setFont里给的字体不存在。drawTextw其实有很多格式,例子中用了这种格式。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第51张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第52张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第53张图片

 

    qp.drawText(event.rect(), Qt.AlignCenter, self.text)的第一个参数event.rect就代表一个矩形框,第二个参数时是上面显示的那些对齐方式,第三个self.text是我们事先准备的文本。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第54张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第55张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第56张图片

 

QRec就是创造一个左上角在x,y,宽是wifth,高是height的矩形。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第57张图片

 

event.rec()就是QWidget窗口不带窗口框架的一个矩形,我们的self.text就要在这个矩形里面绘制出来,因为drawText的参数格式是这么要求的,所以需要这么搞。那么到此为止我们基本上已经看懂了。我们来演示一下:

 

字体和颜色设置应该放在begin之后,上面其实也有提到,因为begin会把这些重置为默认值。其实end可以不要的,这个上面也有提到。QFont('Decorative', 10)这个10是字体的大小,单位是磅。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第58张图片

 

 

 

这个例子怎么说呢,只是显示个文本文字而已,我们用QLable不就可以实现吗,这样用QPainter还有点麻烦。

画点

点是可以绘制的最简单的图形对象。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第59张图片

 

在我们的示例中,我们在窗口的客户区域上随机绘制了1000个红点。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第60张图片

 

最后一句的原文:We draw the point with the drawPoint() method.

应该译为:我们用drawPoint方法绘制了这一点,draw谷歌翻译错了。

Qt.red参考http://doc.qt.io/qt-5/qt.html#GlobalColor-enum。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第61张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第62张图片

 

size()返回的是一个QSize对象,

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第63张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第64张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第65张图片

 

x,y都是以窗口左上角为坐标原点。

有了上面例子的解释,这个例子其实不难理解了,里面就是用到了一个随机数而已。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第66张图片

 

每次扩大窗口size都不一样

颜色

颜色是表示红色,绿色和蓝色(RGB)强度值的组合的对象。有效的RGB值范围为0到255.我们可以通过各种方式定义颜色。最常见的是RGB十进制值或十六进制值。我们还可以使用RGBA值,代表红色,绿色,蓝色和Alpha。这里我们添加一些关于透明度的额外信息 Alpha值255定义完全不透明度,0表示完全透明度,例如颜色不可见。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第67张图片

 

在我们的例子中,我们绘制了三个彩色矩形。QBrush其实在这里面完全没有用到。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第68张图片

 

来学习一下例子里面的新东西。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第69张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第70张图片

 

这个虽然是五的文档,但可能也不是最新的。setBrush后面的第二个参数可以是QColor。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第71张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第72张图片

 

 

        qp.setBrush(QColor(200, 0, 0))

        qp.drawRect(10, 15, 90, 60)

        qp.setBrush(QColor(255, 80, 0, 160))

        qp.drawRect(130, 15, 90, 60)

        qp.setBrush(QColor(25, 0, 90, 200))

        qp.drawRect(250, 15, 90, 60)

有的QColor有三个参数,有的四个,大概是因为最后一个int a是有默认值的,虽然不知道是多少。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第73张图片

 

x,y是矩阵左上角的坐标。看一下效果:

 

setPen里面的颜色在这个例子里面是矩形边框的颜色。

QPen

QPen是一个基本的图形对象。它用于绘制矩形,椭圆,多边形或其他形状的线条,曲线和轮廓。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第74张图片

 

在我们的例子中,我们画了六行。线条以六种不同的笔样式绘制。有五种预定义的笔样式。我们还可以创建自定义笔样式。最后一行使用自定义笔样式绘制。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第75张图片

 

我们自定义的样式是1个破折号,4个空格,5个破折号,4个空格,索引为偶数的是破折号,为奇数的位置是空格,注意列表的第一个元素索引是0,不是1。其实setPen还有这种格式

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第76张图片

 

这个例子用的就是这个。

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第77张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第78张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第79张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第80张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第81张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第82张图片

 

 

PyQt学习Ⅴ(在pyqt中拖放和绘制图形)_第83张图片

 

setDashPattern后面的参数不一定是列表,但必须是iterable类型的,例如元组。

效果:

 

未完待续。

你可能感兴趣的:(python)