整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Qt窗口和視口解析

          Qt窗口和視口解析

          標變換流程

          ??QPainter.drawRect(QRectF)繪制圖形傳入的是世界坐標,而后經過變換矩形變為窗口坐標,最后經過窗口-視口變換變為設備坐標。其中世界坐標系和窗口坐標系都屬于邏輯坐標系,設備坐標系屬于物理坐標。

          世界坐標、窗口坐標和設備坐標

          • 世界坐標
            ??世界坐標也叫邏輯坐標,使用的單位叫做邏輯單位,在世界坐標系中的大小與顯示設備大小無關,類似于數學中的單位長度。
          • 窗口坐標
            ??窗口坐標與世界坐標差在坐標變換上,如translate、rotate、scale、shear等。
          • 設備坐標
            ??設備坐標是物理坐標,設備的左上角為原點(QGraphicsView同),向右為x正方向,向下為y軸正方向。物理坐標系的第二象限為有效繪圖區域,沒有負坐標軸。顯示器中,坐標單位通常為像素,打印機中,坐標單位通常為點。

          ??綜上,三個坐標系中,世界坐標系和窗口坐標系是邏輯坐標系,與具體的設備大小沒有關系,兩者之間相差的是坐標變換,而設備坐標系也就是物理坐標系,第二象限是繪圖的有效果區域,沒有負坐標軸。

          窗口和視口

          • 窗口
            ??窗口是窗口坐標系中的矩形框,
            窗口存在的意義是為了確定顯示窗口坐標系中的哪部分區域。
            ??使用
            painter.setWindow(x,y,w,h)即可設置窗口的大小以及坐標系原點在窗口中的位置。默認情況下窗口與視口大小相同,并且原點都位于左上角。
          • 視口
            ??視口是設備環境中的一個矩形框,使用物理坐標,和設備大小密切相關,超出設備外的視口區域不予顯示。
            視口存在的意義是為了將顯示的內容顯示在物理坐標系中的哪個矩形區域。
            ??使用
            painter.setViewPort(x,y,w,h)即可設置視口的大小以及視口在物理坐標系中的位置。

          關于繪圖設備
          ??繪圖設備常常有QWidget、QPixmap、QImage等。(另外感覺QGraphicsItem也可以作為繪圖設備,使用paint函數繪圖。)關于QGraphicsView和QGraphicsScene
          ??使用QWidget::paintEvent只能繪制簡單的圖形,Qt提供了可與用戶交互的QGraphics繪圖體系,圖形項可移動、選中。view類似于繪圖設備,但是view不能設置視口,scene的坐標系類似于邏輯坐標系,可以通過view.setSceneRect(QRectF)來選定scene中的部分區域顯示在view中。

          世界變換和窗口視口變換

          • 世界變換
            ??世界變換的目的是直接對邏輯坐標進行矩陣變換,常見的有translate、scale、rotate、shear。
          • 窗口視口變換
            ??用戶輸入的坐標一定是邏輯坐標,最終用來繪制的一定是經過窗口-視口變換后的視口坐標,也就是設備坐標(物理坐標)。
            ??如果不顯示使用
            setViewPortsetWindow指定視口和窗口大小,默認的窗口和視口坐標原點都是(0,0),窗口和視口大小都是設備的長和寬。若設置了一個,那么未設置的仍然使用默認設置。
            ??窗口和視口變換關系實際上就是一對線性函數:

          `X'=aX + b``Y'=cY + d`其中,XY為窗口坐標,X'Y'為視口坐標。

          QWidget、QGraphicsItem、QGraphicsView繪圖

          ??在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();
          

          總結:

          1. 視口setViewport(QRectF)傳入的是QWidget的物理坐標,窗口setWindow(QRectF)傳入的是邏輯坐標。視口和窗口是線性映射關系,因此藍框和紅色框會重合。
          2. 平移translate(50,50)操作,移動的是邏輯坐標系,原來的坐標系原點在藍色窗口中央,平移后位于圖示的紅色坐標系。
          3. save和restore用于保存和恢復QPainter的變換。

          文章轉自博客園(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

          這個項目用到的幾個重要知識:

          1. 獲取動態網頁加載數據的真正網址;
          2. 使用CreateObject("MSXML2.XMLHTTP")對象獲取網頁信息,基本框架可以參考用VBA下載一部完整小說;
          3. 使用CreateObject("VBScript.Regexp")正則表達式對象,處理網頁信息并寫入表格;
          4. 點擊按鈕調用函數

          獲取動態網頁加載數據的真正網址

          我們在目標網頁點擊右鍵,并點擊“查看網頁源代碼”后,當使用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資料領取(視頻教程+文檔+代碼+項目實戰)


          主站蜘蛛池模板: 国产成人高清视频一区二区| 久久精品道一区二区三区| 亚洲一区二区三区乱码A| 视频一区在线播放| 日本一区视频在线播放| 亚洲永久无码3D动漫一区| 无码人妻AⅤ一区二区三区| 亚洲一区二区三区四区视频| 精品一区二区高清在线观看| 一区二区国产在线播放| 日韩电影一区二区| 四虎在线观看一区二区| 一区二区不卡久久精品| 一区二区三区在线|欧| 精品91一区二区三区| 农村人乱弄一区二区| 亚洲一本一道一区二区三区| 波多野结衣中文一区二区免费| 无码精品人妻一区二区三区免费看| 精品日韩亚洲AV无码一区二区三区| 麻豆果冻传媒2021精品传媒一区下载 | 精品国产一区二区三区免费| 91国偷自产一区二区三区| 人妻av无码一区二区三区| 亚洲熟女乱色一区二区三区| 婷婷国产成人精品一区二| 国产精品一级香蕉一区| 亚洲AV本道一区二区三区四区| 国产麻豆精品一区二区三区v视界| 精品一区二区三区在线视频观看| 国产精品日韩欧美一区二区三区| 乱码人妻一区二区三区| 日韩AV无码一区二区三区不卡 | 男插女高潮一区二区| 中文精品一区二区三区四区| 国模精品视频一区二区三区| 国产精品福利一区| 国产凸凹视频一区二区| 天堂不卡一区二区视频在线观看 | 无码国产精成人午夜视频一区二区| 日韩精品一区二区三区大桥未久 |