wxPython 绘图演示——模拟雷达信号图(2)
参考此前 wxpython 实现简易画板(1),wxPython 实现绘图有直接法和缓冲法。推荐使用缓冲法来避免屏闪。
1.1. 基本框架
下面以“雷达信号图”为例,回顾 wxPython 的绘图的基本框架:
class RadarGraph(wx.Window):
def __init__(self, *args, **kw):
super().__init__(*args, **kw)
# 自定义的数据
# Add your codes
# 设置并重绘缓冲区
self.buffer = None # 缓冲区
self.InitBuffer()
# 绑定事件
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_PAINT, self.OnPaint)
# add other events you need
def InitBuffer(self):
'''设置并重绘缓冲区'''
w, h = self.GetClientSize()
self.buffer = wx.Bitmap(w, h)
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
# 你的绘制内容
self.DrawGraph(dc)
def DrawGraph(self, dc:wx.BufferedPaintDC):
pass
# ----- 事件响应函数 -----
def OnSize(self, event):
"""响应窗口大小改变"""
# 每次窗口大小变换,都需要重新设置缓冲区大小,重绘窗口
self.InitBuffer()
def OnPaint(self, event):
"""响应Paint Event"""
wx.BufferedPaintDC(self, self.buffer)
1.2. 运行结果
设置了一个定时器 wx.Timer
,让数据随着时间而变化,形成一个动图效果。
1.3. 完整代码
点击查看代码
# -*- encoding: utf-8 -*-
# Python 3.9.6 64bit
'''
@File : a_sample_radar_graph.py
@Time : 2022/01/04 11:02
@Author : Wreng
@Description : 雷达信号图,参考 Python in action / Chapter 12 / example 12.2
@Other : version - Python 3.9.6 64bit, wxPython 4.1.1
'''
import wx
import math
import random
class RadarGraph(wx.Window):
def __init__(self, parent, title, labels):
super().__init__(parent)
# 窗口标题
self.title = title
self.titleFont = wx.Font(14, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
# 图中的标签
self.labels = labels
self.labelFont = wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
self.data = [0.0] * len(labels)
self.xy = None
self.buffer = None # 缓冲区
# 设置并重绘缓冲区
self.InitBuffer()
# 绑定事件
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_PAINT, self.OnPaint)
def InitBuffer(self):
'''创建缓冲区'''
w, h = self.GetClientSize()
self.buffer = wx.Bitmap(w, h)
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
# 你的绘制内容
self.DrawGraph(dc)
def DrawGraph(self, dc:wx.BufferedPaintDC):
'''绘制图形'''
spacer = 10
scaledmax = 150.0
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
dc.Clear()
dw, dh = dc.GetSize()
# 绘制标题
dc.SetFont(self.titleFont)
tw, th = dc.GetTextExtent(self.title)
dc.DrawText(self.title, (dw-tw)/2, spacer)
# 找到中心点
th = th + 2*spacer
cx = dw / 2
cy = (dh - th)/2 + th
# 计算比率
mindim = min(cx, (dh - th)/2)
scale = mindim / scaledmax
# 绘制轴线,以25为刻度
dc.SetPen(wx.Pen("black", 1))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawCircle(cx, cy, 25*scale)
dc.DrawCircle(cx, cy, 50*scale)
dc.DrawCircle(cx, cy, 75*scale)
dc.DrawCircle(cx, cy, 100*scale)
dc.SetPen(wx.Pen("black", 2))
dc.DrawLine(cx-110*scale, cy, cx+110*scale, cy)
dc.DrawLine(cx, cy-110*scale, cx, cy+110*scale)
# 寻找了每个点的坐标,绘制标签以及最大的数据点
dc.SetFont(self.labelFont)
maxval = 0
angle = 0
polypoints = []
for i, label in enumerate(self.labels):
val = self.data[i]
point = self.PolarToCartesian(val*scale, angle, cx, cy) # 将极坐标转化为直角坐标
polypoints.append(point)
x, y = self.PolarToCartesian(125*scale, angle, cx, cy)
dc.DrawText(label, x, y) # 绘制标签
if val > maxval:
maxval = val
angle = angle + 360 / len(self.labels)
# 根据最大值确定brush的颜色, green is good; red is bad
c = "forest green"
if maxval > 70:
c = "yellow"
if maxval > 95:
c = "red"
dc.SetBrush(wx.Brush(c)) # 设置画刷的颜色
dc.SetPen(wx.Pen("navy", 3))
dc.DrawPolygon(polypoints) # 绘制采集的形状
def PolarToCartesian(self, radius, angle, cx,cy):
'''将极坐标转化为直角坐标'''
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
return (int(cx+x+0.5), int(cy+y+0.5)) # 四舍五入转化为整数
def GetData(self):
return self.data
def SetData(self, newData):
assert len(newData) == len(self.data)
self.data = newData[:]
# 数据改变了,因此更新缓冲和窗口
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
self.DrawGraph(dc)
# ====================================================================
# 事件响应函数
# ====================================================================
def OnSize(self, event):
"""响应窗口大小改变"""
# 每次窗口大小变换,都需要重新设置缓冲区大小,重绘窗口
self.InitBuffer()
def OnPaint(self, event):
"""响应Paint Event"""
wx.BufferedPaintDC(self, self.buffer)
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Double Buffered Drawing", size=(480, 480))
self.plot = RadarGraph(self, "Sample Radar Plot", ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'])
data = []
for d in self.plot.GetData():
data.append(random.randint(0, 75))
self.plot.SetData(data)
# 设置一个定时器,使数据随时间随机变化
self.timer = wx.Timer(self)
self.timer.Start(500) # 每 500ms 触发一次 EVT_TIMER
self.Bind(wx.EVT_TIMER, self.OnTimeout)
def OnTimeout(self, event):
data = []
for d in self.plot.GetData():
val = d + random.uniform(-5, 5)
if val < 0:
val = 0
if val > 110:
val = 110
data.append(val)
self.plot.SetData(data)
if __name__ == '__main__':
app = wx.App()
frm = TestFrame()
frm.Show()
app.MainLoop()
1.4. 相关参考
- https://docs.wxpython.org/
- wxpython 实现简易画板(1)
- wxPython in Action by Noel Rappin, Robin Dunn, Chapter 12
- 蓝奏云下载:https://wwe.lanzoup.com/b01oz824f,密码:g7np
- 书中的代码可以在这找到:https://github.com/freephys/wxPython-In-Action
推荐这些文章:
RT
A. 序列
考虑如果直接算,很容易算重,于是正难则反,算有不多彩的序列包含的 \(a\) 的个数。
于是对序列 \(a\) 进行分类讨论。
(1)若 \(a\) 已经是多彩的序列,那么其他位置选什么都不重要,不存在不多彩的序列包含 \(a\),答案就是 \((n - m + 1) * k^{n - m}\) 。
(2)若 \(a\) 中含有重复的元素,则一定不存在跨过 \(a\) 的多彩子序列,于是从 \(a\) 的左右两边分别进行 \(dp\) 。
左右两边的 \(dp\) 基本一样,这里只介绍从 \(a\) 的右边开始 \(dp\)。
设 \(f_{i, j}\) 表示在 \(a\...
这里主要是有两种情况:
1.一个信号连接多个槽函数
2.多个信号连接一个槽函数
"""
信号槽N对N连接与断开连接
"""
from PyQt5.QtCore import *
class NNSignal(QObject):
signal1 = pyqtSignal()
signal2 = pyqtSignal(int)
signal3 = pyqtSignal()
def __init__(self):
super(NNSignal, self).__init__()
# 一个信号连接多个槽函数
sel...
【题目描述】设计三维图形类体系,要求如下:设计三维图形功能接口,接口包含周长、面积、体积计算方法;基于以上接口,首先定义点类,应包含x,y坐标数据成员,坐标获取及设置方法、显示方法等;以点类为基类派生圆类,增加表示半径的数据成员,半径获取及设置方法,重载显示函数,并可计算周长和面积等;以圆类为基础派生球类、圆柱类、圆锥类;要求派生类球、圆柱、圆锥中都含有输入和输出显示方法;并可计算面积、周长。程序中定义各种类的对象,并完成测试。【练习要求】请给出源代码程序和运行测试结果,源代码程序要求添加必要的注释。
代码:
import math
class Shape:
def ...
pyQt5基础学习-重载多种输入的槽函数 1.pyqtSignal([int, str], [str])(构造两种输出参数的信号)
当槽函数会有多种类型的函数输入时,需要进行重载,这里对信号构成进行重载,在绑定槽函数时,做指定操作
MultiSignal.py
"""
为类添加多个信号
"""
from PyQt5.QtCore import *
class MultiSignal(QObject):
signal1 = pyqtSignal()
signal2 = pyqtSignal(int)
signal3 = pyqtSignal(int, str)
signal4 = pyqtSignal(list)
signal5 = pyqtSignal(dict)
...
PyQt5基础学习-QPushButton().clicked.connect(信号和槽) 1.QPushButton().setStyleSheet("设置风格的执行函数")
通过对按钮绑定函数来生成信号和槽,即信号是按钮点击时发送的信号, 槽为对应绑定的函数
SignalSlotDemo.py
"""
信号(Signal) 与槽(Slot)
"""
from PyQt5.QtWidgets import *
import sys
class SigalSlotDemo(QWidget):
def __init__(self):
super(SigalSlotDemo, self).__init__()
self.initUI()
def onClick(self):
self.bt...
构造线程的信息函数,定时发送信号, 将时间信息器绑定函数,实现定时执行的操作
Counter.py
"""
使用线程类(QThread)编写计数器
QThread
def run(self):
while True:
self.sleep(1)
if sec == 5:
break;
QLCDNumber
WorkThread(QThread)
用到自定义信号
"""
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QTimer, QDateTim...
通过鼠标的点击,来获得直线的初始化位置, 通过鼠标的移动事件,获得当前的位置,获得完位置后进行绘图,同时再更新初始化的位置
Drawing.py
"""
项目实战: 实现绘图应用
需要解决3个核心内容
1.如何绘图
2.在哪里绘图
3.如果通过鼠标进行绘图
"""
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QPixmap
from PyQt5.QtCore import Qt, QPoint
class Drawing(QWi...
PyQt5基础学习-信号和槽的自动连接 1.@QtCore.pyqtSlot(定义为槽函数) 2.QpushButton().setObjectName("设置需要绑定的函数名")
@QtCore.pyqtSlot 定义为需要自动连接的槽函数, on_对象名_信号名字
AutoSignalSlot.py
"""
信号与槽自动连接
on_对象名_signalname
"""
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton
import sys
class AutoSignalSlot(QWidget):
def __init__(self):
super(AutoSignalS...
class A:
def __init__(self):
self.n = 2
def add(self, m):
# 第四步
# 来自 D.add 中的 super
# self == d, self.n == d.n == 5
print('self is {0} @A.add'.format(self))
self.n += m
# d.n == 7
class B(A):
def __init__(self):
self.n = 3...
错误实例:
def init(self):
self.w1 = torch.nn.Parameter(torch.FloatTensor(1),requires_grad=True).cuda()
self.w2 = torch.nn.Parameter(torch.FloatTensor(1),requires_grad=True).cuda()
self.w1.data.fill_(0.3)
self.w2.data.fill_(0.3)
def forward(self, x):
out = self.w1 * out1 + self.w2 * out2
out = sel...
文章链接:https://www.dianjilingqu.com/4694.html
本文章来源于网络,版权归原作者所有,如果本站文章侵犯了您的权益,请联系我们删除,联系邮箱:saisai#email.cn,感谢支持理解。