PyQt5 学习笔记 (1)鼠标获取坐标/禁止右键功能/QScrollArea添加修改大小

简要说明

在 github 上发现了一个还挺不错的资源:《PyQt 的各种测试和例子》,所以准备在此新开一个坑,逐个研习一下这些例子,把研习过程中的一些重要内容记录在此作为备忘。由于平时工作忙,可能自己研习的时间没有规律,但会坚持不断的更新。

第1个例子——鼠标获取X轴坐标

本例源代码如下:非原创,具体来源见链接,此处仅做研习记录用途

#!/usr/bin/env python
# encoding: utf-8
'''
Created on 2019年5月2日
@author: weike32
@site: https://pyqt5.com ,https://github.com/weike32
@email: 394967319@qq.com
@file: CopyContent
@description: 查阅了很多博客,如果有异,可以联系作者邮箱。本Demo仅作学习参考用,保有后续相关权益。
'''
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import QtCore
import numpy as np
import pyqtgraph as pg


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(726, 595)
        self.graphicsView = pg.PlotWidget(Form)
        self.graphicsView.setGeometry(QtCore.QRect(75, 131, 621, 441))
        self.graphicsView.setObjectName("graphicsView")


class MyWindow(QMainWindow, Ui_Form):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)
        self.setupUi(self)
        x = np.linspace(-100, 100, 1000)
        data = np.sin(x) / x
        self.graphicsView.plot(data, pen=(255, 255, 255, 200))
        self.label = pg.TextItem(text="横坐标:{}".format(0))
        self.graphicsView.addItem(self.label)
        self.setMouseTracking(True)
        self.graphicsView.scene().sigMouseMoved.connect(self.onMouseMoved)
        
    def onMouseMoved(self, evt):
        if self.graphicsView.plotItem.vb.mapSceneToView(evt):
            point =self.graphicsView.plotItem.vb.mapSceneToView(evt)
            self.label.setHtml("<p style='color:white'>横坐标:{0}</p>".format(point.x()))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWin = MyWindow()
    myWin.show()
    sys.exit(app.exec_())

以上代码主窗口为 MyWindow 类,该类继承自 QMainWindowUi_Form
在这个例子中,有以下值得注意的点:

  1. super(MyWindow, self).__init__(parent) 这一行的作用是执行父类的构造函数,以便我们能够使用父类的属性和方法;
  2. Ui_Form 是一个自定义类,加不加 object 其实对于 Python3 来说已经没有区别,因为 Python3 中默认都是新式类,具体可以参考以下链接:python的class(类)中的object是什么意思?
  3. Ui_Form 类其实就是一个构造视图的方法,通过实例化 pyqtgraph.PlotWidget() 来设置一个绘图区域,关于这一个类的具体使用可以参考官方API:PlotWidget
    在这里插入图片描述
  4. MyWindow 的构造函数中,添加setMouseTrack(True),得到监听事件。若是setMouseTrack(False),只有鼠标按下才会有mouseMove监听事件响应。
  5. self.graphicsView.scene().sigMouseMoved.connect(self.onMouseMoved) 中 , self.graphicsView.scene() 是用来获取 pyqtgraph.GraphicsScene 对象,对于 GraphicsScene 来说,有着三个鼠标事件:sigMouseClicked(event), sigMouseMoved(pos)sigMouseHover(items)。分别对应鼠标在视图区域内的单击,移动以及悬停事件。关于这部分的具体内容,可以参考:GraphicsScene and Mouse Events。在此处用到的是第二种,鼠标移动信息,该信号被绑定在了 onMouseMoved(self, evt) 成员函数上,由于这个信号本身是有参数,evt 就是用来接收这个参数的。
  6. sigMouseMoved(pos) 信号中关于 pos 的解释是:The position is given in scene coordinates.也就是说,这个参数是用视图坐标给出的,实际如果要对应到坐标系中,需要进行转换,self.graphicsView.plotItem.vb.mapSceneToView() 方法就是进行转换的。转换前和转换后都是 PyQt5.QtCore.QPointF 类, 可以使用 .x().y() 方法来进行坐标的获取。与mapSceneToView 方法对应的是 mapViewToScene 方法。

第2个例子——禁止右键点击功能、鼠标滚轮,添加滚动条等功能

#!/usr/bin/env python
# encoding: utf-8
'''
Created on 2019年5月21日
@author: weike32
@site: https://pyqt5.com ,https://github.com/weike32
@email: 394967319@qq.com
@file: CopyContent
@description: 禁止右键,添加滑动窗口,点击按钮生成图片,自定义Y轴坐标,背景颜色调整
'''
import sys
from PyQt5.QtWidgets import QDialog, QApplication, QWidget
from qtpy import QtWidgets
import pyqtgraph as pg
from PyQtGraph.Data.graphTest import graph_Form

class CustomViewBox(pg.ViewBox):
    def __init__(self, *args, **kwds):
        pg.ViewBox.__init__(self, *args, **kwds)
        self.RectMode = 3
        self.setMouseMode(self.RectMode)

    def mouseClickEvent(self, ev):
        if ev.button() == pg.QtCore.Qt.RightButton:
            self.autoRange()

    def mouseDragEvent(self, ev):
        pg.ViewBox.mouseDragEvent(self, ev)

    def wheelEvent(self,ev, axis=None):
        # pg.ViewBox.wheelEvent(self, ev, axis)
        ev.ignore()

class graphAnalysis(QDialog,graph_Form):
    def __init__(self):
        super(graphAnalysis, self).__init__()
        self.setupUi(self)
        self.pushButton_7.clicked.connect(self.test)
        self.tabWidget.clear()

    def test(self):
        tab1 = QtWidgets.QWidget()
        scrollArea = QtWidgets.QScrollArea(tab1)
        scrollArea.setMinimumSize(984,550)
        scrollArea.setWidgetResizable(True)
        labelsContainer = QWidget()
        labelsContainer.setMinimumSize(0,1500)
        scrollArea.setWidget(labelsContainer)
        layout = QtWidgets.QVBoxLayout(labelsContainer)
        time = ['2019-04-20 08:09:00', '2019-04-20 08:09:00', '2019-04-20 08:09:00', '2019-04-20 08:09:00']
        value = [1.2, 2, 1, 4]
        xdict = dict(enumerate(time))
        ticks = [list(zip(range(4), tuple(time)))]
        vb = CustomViewBox()
        plt = pg.PlotWidget(title="标题这里填写",viewBox=vb)
        plt.setBackground(background=None)
        plt.plot(list(xdict.keys()), value)
        plt.getPlotItem().getAxis("bottom").setTicks(ticks)
        temp = QtWidgets.QWidget()
        temp.setMinimumSize(900,300)
        temp.setMaximumSize(900,300)
        layout1 = QtWidgets.QVBoxLayout(temp)
        layout1.addWidget(plt)
        layout.addWidget(temp)
        spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        layout.addItem(spacerItem)
        self.tabWidget.addTab(tab1, '这里tabWidget修改标签')

if __name__ =="__main__":
    app = QApplication(sys.argv)
    w = graphAnalysis()
    w.show()
    sys.exit(app.exec_())

from PyQtGraph.Data.graphTest import graph_Form 运行可能报错,目录结构的问题
测试时可以将Data目录下的 graphTest .py 和 graphTest.ui 拷贝到和 graph1.py 同级的目录里,并将 from PyQtGraph.Data.graphTest import graph_Form 改成 from graphTest import graph_Form

禁止右键点击功能,鼠标滚轮

默认的绘图,在绘图区域单击右键,可以得到很多的操作菜单。
本例中通过 改写 ViewBox 来实现禁用右键点击功能

  • ViewBox.RectModeViewBox.PanMode:对于viewbox来说,鼠标模式只支持两种,一种是 rect 模式,一种是 pan 模式;两种模式的区别在于鼠标左边的拖拽功能不一样:Rect 模式拖拽鼠标左键时会产生一个矩形方框,松开鼠标会放大方框内的图形;而 Pan 模式拖拽鼠标左键时平移作用。值得注意的是,两种模式下,鼠标中键和右键的作用均相同,鼠标中键等同于左键,单击鼠标右键作用默认为唤出交互菜单。经测试,PanMode对应的值为3,而RectMode对应的值为1,self.RectMode = 3; self.setMouseMode(self.RectMode); 两行代码实际上是将鼠标模式设置为了 PanMode,直接使用一句 self.setMouseMode(self.PanMode) 即可
  • ev.ignore() 一行,禁用了鼠标滚轮的滚动效果(原本可以用来缩放图形),这样鼠标滚轮滚动可以只触发滚动条滚动而不影响图形。
  • mouseClickEvent 中,通过判断鼠标单击事件单击的是右键,来重新定义单击右键的功能,从而改变原来的右键单击功能(唤出菜单),改变以后的右键功能为:单击右键显示全部图形(autoRange)按住右键左右拖拽为缩放X轴,上下拖拽为缩放Y轴

添加滚动条

graphAnalysis 中的布局写的有点难以阅读,逻辑是这样的:

  1. __init__(self) 中,通过继承 graph_Form,得到父类的布局,一个 tabWidget 和 一个 pushButton_7,并且通过 self.tabWidget.clear() 函数将原有的 tab 里的内容情空掉了,新的内容通过按钮的回调函数 test() 来添加;
  2. test 函数中添加的视图结构如下,个人认为嵌套得过于复杂,实际自己写代码时,如果这样写,会给后期维护带来很大的麻烦;

tabWidget布局

addTab
包含
setWidget
竖向布局
竖向布局
tabWidget
tab1
scrollArea
labelsContainer
laout
temp
spacerItem
layout1
plt
  1. 通过上面的梳理可以看到,所有可见的控件都包含在 scrollArea 里,也就是 QtWidgets.QScrollArea 实例,实际上,只要是QWidget,都可以装载进这个容器里,以达到滚动条滚动显示的目的

一些其他的图形操作

        temp = QtWidgets.QWidget()
        temp.setMinimumSize(900,300)
        temp.setMaximumSize(900,300)

通过设置 最大 和 最小 尺寸 一致,来禁止图形内容被放大或缩小,当父级控件被缩放的时候,该控件只会显示局部或者留白

plt = pg.PlotWidget(title="标题这里填写",viewBox=vb)

通过重载 ViewBox,来实现前述的禁用右键和滚动等功能

time = ['2019-04-20 08:09:00', '2019-04-20 08:09:00', '2019-04-20 08:09:00', '2019-04-20 08:09:00']
xdict = dict(enumerate(time))
ticks = [list(zip(range(4), tuple(time)))]
value = [1.2, 2, 1, 4]
plt.plot(list(xdict.keys()), value)
plt.getPlotItem().getAxis("bottom").setTicks(ticks)

通过 setTicks 来实现时间轴的显示,注意 ticks 的格式问题

第3个例子——QScrollArea添加和修改大小

等待研习。。。


最后插一条私人恩怨
山东中天物联网(另一个名字,威海天乐物联网有限公司)是个不诚信商家,需要采购传感器和采集仪的朋友们千万注意避坑。我为公司采购,事前明确确认过的参数,收货后发现无法满足,但对方耍无赖拒绝退货退款。吃了个闷亏。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值