Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
??QPainter.drawRect(QRectF)繪制圖形傳入的是世界坐標(biāo),而后經(jīng)過變換矩形變?yōu)榇翱谧鴺?biāo),最后經(jīng)過窗口-視口變換變?yōu)樵O(shè)備坐標(biāo)。其中世界坐標(biāo)系和窗口坐標(biāo)系都屬于邏輯坐標(biāo)系,設(shè)備坐標(biāo)系屬于物理坐標(biāo)。
??綜上,三個坐標(biāo)系中,世界坐標(biāo)系和窗口坐標(biāo)系是邏輯坐標(biāo)系,與具體的設(shè)備大小沒有關(guān)系,兩者之間相差的是坐標(biāo)變換,而設(shè)備坐標(biāo)系也就是物理坐標(biāo)系,第二象限是繪圖的有效果區(qū)域,沒有負坐標(biāo)軸。
關(guān)于繪圖設(shè)備
??繪圖設(shè)備常常有QWidget、QPixmap、QImage等。(另外感覺QGraphicsItem也可以作為繪圖設(shè)備,使用paint函數(shù)繪圖。)關(guān)于QGraphicsView和QGraphicsScene
??使用QWidget::paintEvent只能繪制簡單的圖形,Qt提供了可與用戶交互的QGraphics繪圖體系,圖形項可移動、選中。view類似于繪圖設(shè)備,但是view不能設(shè)置視口,scene的坐標(biāo)系類似于邏輯坐標(biāo)系,可以通過view.setSceneRect(QRectF)來選定scene中的部分區(qū)域顯示在view中。
`X'=aX + b``Y'=cY + d`其中,XY為窗口坐標(biāo),X'Y'為視口坐標(biāo)。
??在QWidget::paintEvet()中繪圖,QWidget是繪圖設(shè)備,左上角為物理坐標(biāo)系的坐標(biāo)原點。通過設(shè)置窗口setWindow()和設(shè)置視口setViewPort()來分別設(shè)置邏輯坐標(biāo)系的繪制區(qū)域和物理坐標(biāo)系的顯示區(qū)域,超出物理坐標(biāo)系的內(nèi)容不予顯示。在邏輯坐標(biāo)系中通過坐標(biāo)系變換實現(xiàn)繪制。
??在QGraphicsItem::paint()中可以繪制,Item的左上角默認是邏輯坐標(biāo)系的原點,可通過painter的坐標(biāo)系變換(如translate、scale、shear、rotate)實現(xiàn)與QWidget體系中相同的繪制。與QWidget不同的是,超出Item仍然能夠顯示。
??QGraphicsView間接繼承于QWidget,因此可作為控件擺放在QWidget中,直接繼承于QAbstractScrollArea,因此作為顯示的窗口時,可以出現(xiàn)滾動條。View與QGraphicsScene搭配使用,Scene用于存放QGraphicsItem,默認邏輯坐標(biāo)系的原點位于其中心,Item通過item::setPos()設(shè)置其在(場景)邏輯坐標(biāo)系中的位置,通過item::setRect()設(shè)置其在自身局部坐標(biāo)系中的位置,因此Scene場景的不同位置皆可放置Item。而View類似于視口,用于顯示場景中的內(nèi)容,通過view::setSceneRect()可設(shè)置顯示哪部分場景區(qū)域,類似于設(shè)置窗口。但是View并不能設(shè)置顯示在哪部分區(qū)域。
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();
總結(jié):
文章轉(zhuǎn)自博客園(YueLiGo):https://www.cnblogs.com/wsw2022/p/16983853.html
一篇文章用VBA下載一部完整小說,VBA除了可以輕松下載一部《水滸傳》小說,還有什么用途?VBA獲取網(wǎng)頁信息(即爬蟲技術(shù))其用處可多了。今天介紹各位小伙用來監(jiān)控的自選股票的主力資金變動的情況,愿大伙在2022年股票市場長紅!也是把上期一個網(wǎng)友評論的內(nèi)容(有些數(shù)據(jù)藏得很深,怎么找真正的地址……)回應(yīng)一下。
東富的主力資金流入圖
有一個理論我們會經(jīng)常聽到,A股的票漲漲跌跌主要是因為有大資金在活動、在操作,一些股票不斷上漲是因為有主力資金不斷買入,反而不斷下跌是因為主力資金不斷流出。喜歡做短線的,我們實時觀察這些主力資金就變得很有意義,很多網(wǎng)站都有主力資金的數(shù)據(jù),但是要對多支股票進行觀察,則需要一個個打開網(wǎng)頁、APP或者電腦程序查看數(shù)據(jù),這樣耗時也不能多支股票同框?qū)Ρ取_€有一些小伙正上班,打開股票軟件給老板或同事看到,總覺得怪怪的,當(dāng)然這不是鼓勵一些小伙上班玩股票,純屬用項目和大家一起交流學(xué)習(xí)。
用VBA就可以很輕松解決上述兩個問題。大伙先看看效果吧!
點擊按鈕更新數(shù)據(jù):2022年12月21日數(shù)據(jù)
完整代碼如下:
Sub maincapital()
Application.DisplayAlerts=False
'循環(huán)A列數(shù)據(jù),解析出相應(yīng)股票代碼
For Each cl In Range("a2:a" & Range("a2").End(xlDown).Row)
stock_code=Right(cl, 6) '取右邊6位字符
Dim strText, stcok_code As String
'拼接構(gòu)造網(wǎng)址
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(yù)股和上A股網(wǎng)址不同拼接問題,secids=0.是深A(yù);secids=1.是上A。
Dim regStrTest As Object
With CreateObject("VBScript.Regexp")
.Pattern="null"
Set regStrTest=.Execute(strText)
End With
If regStrTest.Count > 0 Then
'如果出現(xiàn)null則拼接構(gòu)造一個新網(wǎng)址
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 '股票名稱所在行號
'利用正則表達式得到我們想要的內(nèi)容,并寫相應(yīng)的表格
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
這個項目用到的幾個重要知識:
獲取動態(tài)網(wǎng)頁加載數(shù)據(jù)的真正網(wǎng)址
我們在目標(biāo)網(wǎng)頁點擊右鍵,并點擊“查看網(wǎng)頁源代碼”后,當(dāng)使用cttl+f鍵查看我們想要獲取的信息進行查看(這里我輸入主力凈比數(shù)據(jù)-42.76),發(fā)現(xiàn)并沒有相關(guān)的數(shù)據(jù)。
在源代碼網(wǎng)頁同時按cttl+f鍵查看
通過這個方法基本可以判斷目標(biāo)網(wǎng)頁的部分數(shù)據(jù)是使用動態(tài)加載的方式。簡單的動態(tài)加載數(shù)據(jù),可以通過以下兩步獲取真正的網(wǎng)址:
第一步:打開瀏覽器控制臺。演示使用的瀏覽器是chrome,按下F12鍵打開瀏覽器控制臺,再次刷新網(wǎng)頁,在控制臺找到并點擊擴大鏡小按鈕,打開search對話框,這里輸入想找的數(shù)據(jù)(這里我輸入主力凈比數(shù)據(jù)42.76)后,按下回車鍵或輸入框旁邊的刷新按鍵,就會彈出一個“get”字符及一些類似網(wǎng)址的內(nèi)容,點擊彈出的內(nèi)容,右下面對話框會彈出相應(yīng)的內(nèi)容(對話框的菜單有Headers,Preview,Response……)
圖中主力凈比數(shù)據(jù)為-42.73和在輸入框的數(shù)據(jù)不一致,是因為資金數(shù)據(jù)動態(tài)變化了
第二步:找到加載數(shù)據(jù)的網(wǎng)址。點擊Headers可以看到Resquest URl字符,后面網(wǎng)址就是加載數(shù)據(jù)真正的網(wǎng)址,復(fù)制網(wǎng)址在瀏覽器打開,我們可以看到相應(yīng)的數(shù)據(jù)內(nèi)容。獲得這網(wǎng)址后,就可以通過VBA訪問這個網(wǎng)址獲取相應(yīng)的數(shù)據(jù),按下來的工作就好辦了。
目標(biāo)數(shù)據(jù)的網(wǎng)址
使用CreateObject("MSXML2.XMLHTTP")對象獲取網(wǎng)頁信息
stock_code=Right(cl, 6) '取右邊6位字符
Dim strText, stcok_code As String '
'拼接構(gòu)造網(wǎng)址
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(yù)股和上A股網(wǎng)址不同拼接問題,secids=0.是深A(yù);secids=1.是上A。
Dim regStrTest As Object
With CreateObject("VBScript.Regexp")
.Pattern="null"
Set regStrTest=.Execute(strText)
End With
If regStrTest.Count > 0 Then
'如果出現(xiàn)null則拼接構(gòu)造一個新網(wǎng)址
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(目標(biāo)字符串,字符個數(shù))函數(shù)獲取目標(biāo)字符串從右邊數(shù)起第幾個字符。
2、做兩次網(wǎng)址請求是因為深A(yù)股和上A股的數(shù)據(jù)網(wǎng)址是有區(qū)別,網(wǎng)址的參數(shù)“secids=0.+ 股票代碼”是深A(yù);“secids=1.+股票代碼”是上A。如果人為對每支股票判斷是上A還深A(yù)會很復(fù)雜,所以使用正則表達式,對請求數(shù)據(jù)內(nèi)容出現(xiàn)“null”字樣的網(wǎng)址,則更換網(wǎng)址參數(shù)。如下圖:
上A網(wǎng)址請求結(jié)果
深A(yù)網(wǎng)址請求結(jié)果
使用CreateObject("VBScript.Regexp")正則表達式對象獲取數(shù)據(jù)
For Each cl In Range("a2:a" & Range("a2").End(xlDown).Row)
……
Rnum=cl.Row '股票名稱所在行號
'利用正則表達式得到我們想要的內(nèi)容,并寫相應(yīng)的表格
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是表示單元格的行數(shù),Range("A1").Row,Cells(1, 1).Row都可以獲取單元格行數(shù),列值則是Range("A1").Column和Cells(1, 1).Column。
3、.Pattern="""f62"":(.*?)," 是正則表達式(網(wǎng)頁的內(nèi)容是:"f62":-15043563520.0),VBA的英文的雙引號用正則表式表示則是兩個雙引號,即是""。"f62":后面數(shù)據(jù)就是主力凈流入的數(shù)據(jù),用(.*?)表示。再用.submatches.Item(0)得到目標(biāo)數(shù)據(jù),這個數(shù)據(jù)是以元為單位,網(wǎng)頁顯示的是億,所以要/100000000。
4、Round(目標(biāo)數(shù)據(jù),小數(shù)點位數(shù))是取多少位小數(shù)的方法。
點擊按鈕調(diào)用函數(shù)
Private Sub CommandButton1_Click()
Call maincapital '調(diào)用函數(shù)
End Sub
在這總結(jié)一下VBA抓取數(shù)據(jù)主要步驟:
分析網(wǎng)站->>分析網(wǎng)頁數(shù)據(jù)->>處理網(wǎng)頁數(shù)據(jù)->>儲存網(wǎng)頁數(shù)據(jù)
歡迎大家評論及提意見,相互學(xué)習(xí),提高效率,創(chuàng)造價值。
Chart的顯示需要用到QChartView,創(chuàng)建QChartView的步驟如下:
(1)在.pro文件中添加:QT +=charts。
(2)用到QChart的文件中添加:QT_CHARTS_USE_NAMESPACE,或者:using namespace QtCharts;
(3)在ui界面中拖入一個graphicsView(或)控件,然后右擊提升為QChartView類,如下圖,點擊添加,點擊提升;QChart的顯示容器創(chuàng)建完成。
Qt資料領(lǐng)取→「鏈接」
QChart的兩種顯示方法:(本質(zhì)上就是同一種方法)
(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,代碼量的區(qū)別:
(1)用QGraphicView來顯示,需要借助QGraphicsScene類。具體地說就是,QGraphicView在最底層,QGraphicsScene在中間,QChart在最外層。
QGraphicsScene scene;//場景(中間層)
QGraphicsView view(&scene);//視圖(最底層)
view.setRenderHint(QPainter::Antialiasing);//設(shè)置視圖抗鋸齒
view.setSceneRect(0, 0, 630, 280);//設(shè)置視圖大小
QLineSeries *lineseries=new QLineSeries();//圖表的數(shù)據(jù)集
lineseries->append(0, 5);//append和<<功能差不多
*lineseries << QPointF(13, 5) << QPointF(17, 6) << QPointF(20, 2);
QChart *lineChart=new QChart();//圖表(最頂層)
lineChart->addSeries(lineseries); // 將 數(shù)據(jù)集 添加至圖表中
scene.addItem(lineChart);//把圖標(biāo)添加到場景中(一個場景中允許添加多個圖表)
view.show();//視圖顯示
(2)用QChartView來顯示QChart較為方便
QLineSeries *lineseries=new QLineSeries();//圖表的數(shù)據(jù)集
lineseries->append(0, 5);//append和<<功能差不多
*lineseries << QPointF(13, 5) << QPointF(17, 6) << QPointF(20, 2);
QChart *lineChart=new QChart();//圖表(最頂層)
lineChart->addSeries(lineseries); // 將 數(shù)據(jù)集 添加至圖表中
QChartView *chartView=new QChartView(chart);//QChartView 可以一步到位直接顯示QChart
chartView->setRenderHint(QPainter::Antialiasing);//繼承來的抗鋸齒方法
chartView->resize(400, 300);
chartView->show();//本示例代碼,把該控件作為窗口直接顯示出來。
//其實,也可以把QChartView的父控件設(shè)置為主UI,這樣就能把QChartView顯示在主窗體中了
如果ui中已添加了QChartView,則可以直接在ui中顯示:
......
ui->histogramView->setChart(chart); //histogramView--ui中已添加的QChartView
ui->histogramView->setRenderHint(QPainter::Antialiasing);
ui->histogramView->setVisible(true);
最后再來捋一下各個類之間的層次關(guān)系。下圖中,大括號“{”代表左邊實體包含右邊實體,下箭頭↓↓↓↓代表繼承關(guān)系
文章轉(zhuǎn)自博客園(手磨咖啡):https://www.cnblogs.com/zzzsj/p/14760234.html
Qt資料領(lǐng)取(視頻教程+文檔+代碼+項目實戰(zhàn))
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。