??QPainter.drawRect(QRectF)绘制图形传入的是世界坐标,而后经过变换矩形变为窗口坐标,最后经过窗口-视口变换变为设备坐标。其中世界坐标系和窗口坐标系都属于逻辑坐标系,设备坐标系属于物理坐标。
??综上,三个坐标系中,世界坐标系和窗口坐标系是逻辑坐标系,与具体的设备大小没有关系,两者之间相差的是坐标变换,而设备坐标系也就是物理坐标系,第二象限是绘图的有效果区域,没有负坐标轴。
关于绘图设备
??绘图设备常常有QWidget、QPixmap、QImage等。(另外感觉QGraphicsItem也可以作为绘图设备,使用paint函数绘图。)关于QGraphicsView和QGraphicsScene
??使用QWidget::paintEvent只能绘制简单的图形,Qt提供了可与用户交互的QGraphics绘图体系,图形项可移动、选中。view类似于绘图设备,但是view不能设置视口,scene的坐标系类似于逻辑坐标系,可以通过view.setSceneRect(QRectF)来选定scene中的部分区域显示在view中。
`X'=aX + b``Y'=cY + d`其中,XY为窗口坐标,X'Y'为视口坐标。
??在QWidget::paintEvet()中绘图,QWidget是绘图设备,左上角为物理坐标系的坐标原点。通过设置窗口setWindow()和设置视口setViewPort()来分别设置逻辑坐标系的绘制区域和物理坐标系的显示区域,超出物理坐标系的内容不予显示。在逻辑坐标系中通过坐标系变换实现绘制。
??在QGraphicsItem::paint()中可以绘制,Item的左上角默认是逻辑坐标系的原点,可通过painter的坐标系变换(如translate、scale、shear、rotate)实现与QWidget体系中相同的绘制。与QWidget不同的是,超出Item仍然能够显示。
??QGraphicsView间接继承于QWidget,因此可作为控件摆放在QWidget中,直接继承于QAbstractScrollArea,因此作为显示的窗口时,可以出现滚动条。View与QGraphicsScene搭配使用,Scene用于存放QGraphicsItem,默认逻辑坐标系的原点位于其中心,Item通过item::setPos()设置其在(场景)逻辑坐标系中的位置,通过item::setRect()设置其在自身局部坐标系中的位置,因此Scene场景的不同位置皆可放置Item。而View类似于视口,用于显示场景中的内容,通过view::setSceneRect()可设置显示哪部分场景区域,类似于设置窗口。但是View并不能设置显示在哪部分区域。
painter.save();
painter.setPen(Qt::red);
painter.drawRect(0,0, 200, 200);//可视化视口(红色)
painter.setViewport(0,0, 200, 200);
QPen pen=painter.pen();
pen.setStyle(Qt::DashLine);
pen.setWidth(3);
pen.setColor(Qt::blue);
painter.setPen(pen);
painter.setWindow(-100, -100, 200, 200);
painter.drawRect(-100, -100, 200, 200);//可视化窗口(蓝色)
painter.translate(50, 50);//平移(50,50)
painter.setPen(Qt::black);//绘制两个图形
painter.drawRect(-100, -100, 100, 100);
painter.drawRect(50, 50, 100, 100);
painter.restore();
总结:
文章转自博客园(YueLiGo):https://www.cnblogs.com/wsw2022/p/16983853.html
一篇文章用VBA下载一部完整小说,VBA除了可以轻松下载一部《水浒传》小说,还有什么用途?VBA获取网页信息(即爬虫技术)其用处可多了。今天介绍各位小伙用来监控的自选股票的主力资金变动的情况,愿大伙在2022年股票市场长红!也是把上期一个网友评论的内容(有些数据藏得很深,怎么找真正的地址……)回应一下。
东富的主力资金流入图
有一个理论我们会经常听到,A股的票涨涨跌跌主要是因为有大资金在活动、在操作,一些股票不断上涨是因为有主力资金不断买入,反而不断下跌是因为主力资金不断流出。喜欢做短线的,我们实时观察这些主力资金就变得很有意义,很多网站都有主力资金的数据,但是要对多支股票进行观察,则需要一个个打开网页、APP或者电脑程序查看数据,这样耗时也不能多支股票同框对比。还有一些小伙正上班,打开股票软件给老板或同事看到,总觉得怪怪的,当然这不是鼓励一些小伙上班玩股票,纯属用项目和大家一起交流学习。
用VBA就可以很轻松解决上述两个问题。大伙先看看效果吧!
点击按钮更新数据:2022年12月21日数据
完整代码如下:
Sub maincapital()
Application.DisplayAlerts=False
'循环A列数据,解析出相应股票代码
For Each cl In Range("a2:a" & Range("a2").End(xlDown).Row)
stock_code=Right(cl, 6) '取右边6位字符
Dim strText, stcok_code As String
'拼接构造网址
URL="https://push2.eastmoney.com/api/qt/ulist.np/get?cb=fltt=2&secids=1." + stock_code + "&fields=f62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf64%2Cf65%2Cf70%2Cf71%2Cf76%2Cf77%2Cf82%2Cf83%2Cf164%2Cf166%2Cf168%2Cf170%2Cf172%2Cf252%2Cf253%2Cf254%2Cf255%2Cf256%2Cf124%2Cf6%2Cf278%2Cf279%2Cf280%2Cf281%2Cf282&ut=b2884a393a59ad64002292a3e90d46a5&_=1641268581776"
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", URL, False
.send
strText=.responseText
End With
'判断是有null,解决深A股和上A股网址不同拼接问题,secids=0.是深A;secids=1.是上A。
Dim regStrTest As Object
With CreateObject("VBScript.Regexp")
.Pattern="null"
Set regStrTest=.Execute(strText)
End With
If regStrTest.Count > 0 Then
'如果出现null则拼接构造一个新网址
URL="https://push2.eastmoney.com/api/qt/ulist.np/get?cb=fltt=2&secids=0." + stock_code + "&fields=f62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf64%2Cf65%2Cf70%2Cf71%2Cf76%2Cf77%2Cf82%2Cf83%2Cf164%2Cf166%2Cf168%2Cf170%2Cf172%2Cf252%2Cf253%2Cf254%2Cf255%2Cf256%2Cf124%2Cf6%2Cf278%2Cf279%2Cf280%2Cf281%2Cf282&ut=b2884a393a59ad64002292a3e90d46a5&_=1641268581776"
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", URL, False
.send
strText=.responseText
End With
End If
Rnum=cl.Row '股票名称所在行号
'利用正则表达式得到我们想要的内容,并写相应的表格
With CreateObject("VBScript.Regexp")
.Pattern="""f62"":(.*?),"
Cells(Rnum, 2)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '主力净流进
.Pattern="""f184"":(.*?),"
Cells(Rnum, 3)=Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '主力净比
.Pattern="""f66"":(.*?),"
Cells(Rnum, 4)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '超大单净流进
.Pattern="""f69"":(.*?),"
Cells(Rnum, 5)=Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '超大单净比
.Pattern="""f72"":(.*?),"
Cells(Rnum, 6)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '大单净流进
.Pattern="""f75"":(.*?),"
Cells(Rnum, 7)=Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '大单净比
.Pattern="""f78"":(.*?),"
Cells(Rnum, 8)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '中单净流进
.Pattern="""f81"":(.*?),"
Cells(Rnum, 9)=Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '中单净比
.Pattern="""f84"":(.*?),"
Cells(Rnum, 10)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '小单净流进
.Pattern="""f87"":(.*?),"
Cells(Rnum, 11)=Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '小单净比
.Pattern="""f64"":(.*?),"
Cells(Rnum, 12)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '超大单流入
.Pattern="""f65"":(.*?),"
Cells(Rnum, 13)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '超大流出
.Pattern="""f70"":(.*?),"
Cells(Rnum, 14)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '大单流入
.Pattern="""f71"":(.*?),"
Cells(Rnum, 14)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '大单流出
End With
Next
Application.DisplayAlerts=True
End Sub
这个项目用到的几个重要知识:
获取动态网页加载数据的真正网址
我们在目标网页点击右键,并点击“查看网页源代码”后,当使用cttl+f键查看我们想要获取的信息进行查看(这里我输入主力净比数据-42.76),发现并没有相关的数据。
在源代码网页同时按cttl+f键查看
通过这个方法基本可以判断目标网页的部分数据是使用动态加载的方式。简单的动态加载数据,可以通过以下两步获取真正的网址:
第一步:打开浏览器控制台。演示使用的浏览器是chrome,按下F12键打开浏览器控制台,再次刷新网页,在控制台找到并点击扩大镜小按钮,打开search对话框,这里输入想找的数据(这里我输入主力净比数据42.76)后,按下回车键或输入框旁边的刷新按键,就会弹出一个“get”字符及一些类似网址的内容,点击弹出的内容,右下面对话框会弹出相应的内容(对话框的菜单有Headers,Preview,Response……)
图中主力净比数据为-42.73和在输入框的数据不一致,是因为资金数据动态变化了
第二步:找到加载数据的网址。点击Headers可以看到Resquest URl字符,后面网址就是加载数据真正的网址,复制网址在浏览器打开,我们可以看到相应的数据内容。获得这网址后,就可以通过VBA访问这个网址获取相应的数据,按下来的工作就好办了。
目标数据的网址
使用CreateObject("MSXML2.XMLHTTP")对象获取网页信息
stock_code=Right(cl, 6) '取右边6位字符
Dim strText, stcok_code As String '
'拼接构造网址
URL="https://push2.eastmoney.com/api/qt/ulist.np/get?cb=fltt=2&secids=1." + stock_code + "&fields=f62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf64%2Cf65%2Cf70%2Cf71%2Cf76%2Cf77%2Cf82%2Cf83%2Cf164%2Cf166%2Cf168%2Cf170%2Cf172%2Cf252%2Cf253%2Cf254%2Cf255%2Cf256%2Cf124%2Cf6%2Cf278%2Cf279%2Cf280%2Cf281%2Cf282&ut=b2884a393a59ad64002292a3e90d46a5&_=1641268581776"
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", URL, False
.send
strText=.responseText
End With
'判断是有null,解决深A股和上A股网址不同拼接问题,secids=0.是深A;secids=1.是上A。
Dim regStrTest As Object
With CreateObject("VBScript.Regexp")
.Pattern="null"
Set regStrTest=.Execute(strText)
End With
If regStrTest.Count > 0 Then
'如果出现null则拼接构造一个新网址
URL="https://push2.eastmoney.com/api/qt/ulist.np/get?cb=fltt=2&secids=0." + stock_code + "&fields=f62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf64%2Cf65%2Cf70%2Cf71%2Cf76%2Cf77%2Cf82%2Cf83%2Cf164%2Cf166%2Cf168%2Cf170%2Cf172%2Cf252%2Cf253%2Cf254%2Cf255%2Cf256%2Cf124%2Cf6%2Cf278%2Cf279%2Cf280%2Cf281%2Cf282&ut=b2884a393a59ad64002292a3e90d46a5&_=1641268581776"
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", URL, False
.send
strText=.responseText
End With
End If
上面代码的说明:
1、使用right(目标字符串,字符个数)函数获取目标字符串从右边数起第几个字符。
2、做两次网址请求是因为深A股和上A股的数据网址是有区别,网址的参数“secids=0.+ 股票代码”是深A;“secids=1.+股票代码”是上A。如果人为对每支股票判断是上A还深A会很复杂,所以使用正则表达式,对请求数据内容出现“null”字样的网址,则更换网址参数。如下图:
上A网址请求结果
深A网址请求结果
使用CreateObject("VBScript.Regexp")正则表达式对象获取数据
For Each cl In Range("a2:a" & Range("a2").End(xlDown).Row)
……
Rnum=cl.Row '股票名称所在行号
'利用正则表达式得到我们想要的内容,并写相应的表格
With CreateObject("VBScript.Regexp")
.Pattern="""f62"":(.*?)," 'VBA的英文的双引号
Cells(Rnum, 2)=Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '主力净流入
.Pattern="""f184"":(.*?),"
Cells(Rnum, 3)=Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '主力净比
.Pattern="""f66"":(.*?),"
……
上面代码的说明:
1、Range("a2").End(xlDown)是表示定位从A2单元往下最后一个不空值的单元格。
2、cl.Row是表示单元格的行数,Range("A1").Row,Cells(1, 1).Row都可以获取单元格行数,列值则是Range("A1").Column和Cells(1, 1).Column。
3、.Pattern="""f62"":(.*?)," 是正则表达式(网页的内容是:"f62":-15043563520.0),VBA的英文的双引号用正则表式表示则是两个双引号,即是""。"f62":后面数据就是主力净流入的数据,用(.*?)表示。再用.submatches.Item(0)得到目标数据,这个数据是以元为单位,网页显示的是亿,所以要/100000000。
4、Round(目标数据,小数点位数)是取多少位小数的方法。
点击按钮调用函数
Private Sub CommandButton1_Click()
Call maincapital '调用函数
End Sub
在这总结一下VBA抓取数据主要步骤:
分析网站->>分析网页数据->>处理网页数据->>储存网页数据
欢迎大家评论及提意见,相互学习,提高效率,创造价值。
Chart的显示需要用到QChartView,创建QChartView的步骤如下:
(1)在.pro文件中添加:QT +=charts。
(2)用到QChart的文件中添加:QT_CHARTS_USE_NAMESPACE,或者:using namespace QtCharts;
(3)在ui界面中拖入一个graphicsView(或)控件,然后右击提升为QChartView类,如下图,点击添加,点击提升;QChart的显示容器创建完成。
Qt资料领取→「链接」
QChart的两种显示方法:(本质上就是同一种方法)
(1)QChart必须显示在widget上,更确切地说,是必须把它显示在QGraphicView控件中,众所周知,QT的ui控件都可以作为独立窗口直接显示,所以这就是方法1。
(2)把QChart显示在ui界面的QGraphicView控件中。
PS:把QChart显示在QGraphicView控件中,程序略显繁琐,QT早就为我们封装好了一个ui控件类QtCharts::QChartView,它继承了QGraphicView。这就是上文提到的把QGraphicView提升成了QChartView。用QChartView来显示QChart还是很方便的。
用QGraphicView来显示QChart较为繁琐,下面来对比一下,分别用QGraphicView和QChartView来显示QChart,代码量的区别:
(1)用QGraphicView来显示,需要借助QGraphicsScene类。具体地说就是,QGraphicView在最底层,QGraphicsScene在中间,QChart在最外层。
QGraphicsScene scene;//场景(中间层)
QGraphicsView view(&scene);//视图(最底层)
view.setRenderHint(QPainter::Antialiasing);//设置视图抗锯齿
view.setSceneRect(0, 0, 630, 280);//设置视图大小
QLineSeries *lineseries=new QLineSeries();//图表的数据集
lineseries->append(0, 5);//append和<<功能差不多
*lineseries << QPointF(13, 5) << QPointF(17, 6) << QPointF(20, 2);
QChart *lineChart=new QChart();//图表(最顶层)
lineChart->addSeries(lineseries); // 将 数据集 添加至图表中
scene.addItem(lineChart);//把图标添加到场景中(一个场景中允许添加多个图表)
view.show();//视图显示
(2)用QChartView来显示QChart较为方便
QLineSeries *lineseries=new QLineSeries();//图表的数据集
lineseries->append(0, 5);//append和<<功能差不多
*lineseries << QPointF(13, 5) << QPointF(17, 6) << QPointF(20, 2);
QChart *lineChart=new QChart();//图表(最顶层)
lineChart->addSeries(lineseries); // 将 数据集 添加至图表中
QChartView *chartView=new QChartView(chart);//QChartView 可以一步到位直接显示QChart
chartView->setRenderHint(QPainter::Antialiasing);//继承来的抗锯齿方法
chartView->resize(400, 300);
chartView->show();//本示例代码,把该控件作为窗口直接显示出来。
//其实,也可以把QChartView的父控件设置为主UI,这样就能把QChartView显示在主窗体中了
如果ui中已添加了QChartView,则可以直接在ui中显示:
......
ui->histogramView->setChart(chart); //histogramView--ui中已添加的QChartView
ui->histogramView->setRenderHint(QPainter::Antialiasing);
ui->histogramView->setVisible(true);
最后再来捋一下各个类之间的层次关系。下图中,大括号“{”代表左边实体包含右边实体,下箭头↓↓↓↓代表继承关系
文章转自博客园(手磨咖啡):https://www.cnblogs.com/zzzsj/p/14760234.html
Qt资料领取(视频教程+文档+代码+项目实战)
*请认真填写需求信息,我们会在24小时内与您取得联系。