PyQtGraphでグラフを描く（1）

PyQtGraphでグラフを描くためのメモです。

完成形は、以下のイメージです。実行時のグラフは非表示で、Plotボタンを押すとグラフ表示が行われ、Quitボタンで終了するという単純なものです。


![20210401174519.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/b5c984f4-e0de-f92f-dae9-c5a06fe65fff.png)



## 手順

PyQtGraphでグラフを描く際の手順は、以下のとおりとします。

1. QtDesignerでUIを作成
1. グラフを描くコードを記述
1. 実行


## 結論

本稿の操作で、以下のコードが得られます。
先ずは、QtDesignerで読み込むことができるxmlファイルです。

<details><summary>mainUi.ui</summary><div>

```xml
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <layout class="QVBoxLayout" name="verticalLayout"/>
   </item>
   <item row="1" column="0">
    <layout class="QHBoxLayout" name="horizontalLayout">
     <item>
      <spacer name="horizontalSpacer">
       <property name="orientation">
        <enum>Qt::Horizontal</enum>
       </property>
       <property name="sizeHint" stdset="0">
        <size>
         <width>40</width>
         <height>20</height>
        </size>
       </property>
      </spacer>
     </item>
     <item>
      <widget class="QPushButton" name="pltBtn">
       <property name="text">
        <string>Plot</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QPushButton" name="quitBtn">
       <property name="text">
        <string>Quit</string>
       </property>
      </widget>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>quitBtn</sender>
   <signal>clicked()</signal>
   <receiver>Form</receiver>
   <slot>close()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>359</x>
     <y>215</y>
    </hint>
    <hint type="destinationlabel">
     <x>252</x>
     <y>4</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>
```
</div></details>

続いて、pyuic5でpythonに変換したファイル

<details><summary>mainUi.py</summary><div>

```python
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(800, 600)
        self.gridLayout = QtWidgets.QGridLayout(Form)
        self.gridLayout.setObjectName("gridLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.pltBtn = QtWidgets.QPushButton(Form)
        self.pltBtn.setObjectName("pltBtn")
        self.horizontalLayout.addWidget(self.pltBtn)
        self.quitBtn = QtWidgets.QPushButton(Form)
        self.quitBtn.setObjectName("quitBtn")
        self.horizontalLayout.addWidget(self.quitBtn)
        self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1)

        self.retranslateUi(Form)
        self.quitBtn.clicked.connect(Form.close)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pltBtn.setText(_translate("Form", "Plot"))
        self.quitBtn.setText(_translate("Form", "Quit"))
```

</div></details>


グラフ描画用のコードは、以下のとおりです。ファイル名はmain.pyとしました。

<details><summary>main.py</summary><div>

```python
import sys
from PyQt5 import QtWidgets
import numpy as np
import pyqtgraph as pg

from PyQt5 import uic
class GraphWindow(QtWidgets.QWidget):   
    def __init__(self, *args, **kwargs):
        super(GraphWindow, self).__init__(*args, **kwargs)
        uic.loadUi('mainUi.ui', self)


        # ここからは共通
        self.p1, self.p2 = self.set_graph_ui()
        self.pltBtn.clicked.connect(self.plot)

    def set_graph_ui(self):
        pg.setConfigOptions(antialias=True)
        win = pg.GraphicsLayoutWidget()
        self.verticalLayout.addWidget(win)
        
        p1 = win.addPlot()
        p1.setAutoVisible(y=True)

        win.nextRow()
        p2 = win.addPlot()
        p2.setAutoVisible(y=True)

        return p1, p2


    def plot(self):
        self.p1.clear()
        self.p2.clear()
        t = np.linspace(0, 20, 200)
        y_cos = np.cos(t)
        data1 = 10000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)
        data2 = 15000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)

        self.p1.plot(data1, pen="r")
        self.p1.plot(data2, pen="g")
        self.p2.plot(data1, pen="w")


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


```

</div></details>


上記のコードは、uiファイルをロードする場合のコードです。pyファイルをロードする場合は、以下のコードとなります。

```python
from mainUiMW import Ui_MainWindow
class GraphWindow(QtWidgets.QMainWindow, Ui_MainWindow):   
    def __init__(self):
        super(GraphWindow, self).__init__()
        self.setupUi(self)   
```

を以下のように変更すればOKです。


```python
from PyQt5 import uic
class GraphWindow(QtWidgets.QWidget):   
    def __init__(self, *args, **kwargs):
        super(GraphWindow, self).__init__(*args, **kwargs)
        uic.loadUi('mainUi.ui', self)
```



## QtDesignerでUIを作成

上記のUIは以下の手順で作成します。


QtDesignerを起動すると、以下の画面が表示されます。

![20210401105527.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/8aa7331d-5100-aab8-3626-849b9b60c18a.png)

Main WindowもしくはWidgetが選択できます。
ステータスバーやメニューを使用したい場合は、Main Windowを選択してください。
簡易なWindowのみの場合は、Widgetで良いでしょう。


## Widgetを選択する場合

Widgetで作成する手順は以下のとおりです。
まずは、Widgetを選択します。

![20210401111144.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/b0c03010-bdc7-5428-7d47-5fcd07d518fb.png)



Widget BoxからPush Buttonを２つ並べて、それぞれプロパティと値を変更
Plot用はobjectNameを「Plot」に、textを「pltBtn」に、Quit用は「Quit」「quitBtn」に変更
Horizontal Spacerを並べる


![20210401141500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/4f259418-79ab-a67c-9441-34ad8cdc53c4.png)
次に、先ほどのウィジェット（ボタン、スペーサー）を全て選択し
上にあるHrizontal layoutボタンを押すと、図のようになります。

![20210401142716.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/cfa68fac-caaa-7c5c-78ea-9cc7849b876d.png)
![20210401142959.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/7b249a05-179d-ac95-b07c-a7dc703a7e36.png)


Widget boxから、Vertical Layoutをドラッグして配置

![20210401143259.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/ca0f33e6-162a-0904-7e9a-978ee8542795.png)
![20210401143339.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/9f9b9087-d244-5550-a36f-b6f59b7a05e1.png)

ウィジェットを選択していない状態で、上のLay Out in Gridを選択すると以下のようになります。


![20210401143355.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/7181cb36-6f8b-f29a-d2ae-2a7246d1c4f0.png)


続いて、Quitボタンの動作設定をします。

![20210401143541.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/5abdb802-4772-dd60-4836-285d6db262f9.png)

上にあるEdit Signals/Slotsボタンを押すと、次の画面になります。

![20210401143654.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/37274570-3cbd-bfa9-5fd3-8b43d8636ef6.png)



Quitボタンをクリックし、赤線が以下の図のようになる位置でリリースします。
フォームをクローズするので、フォームをクローズしたいのでフォーム上でリリースする必要があります。メニューバー付近でリリースすると良いかと思います。

![20210401144059.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/ed9b8f89-324e-ae44-2248-f7eb60f149e9.png)

リリースすると以下の画面となります

![20210401144130.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/95eaf771-3bd0-a805-969e-89572778737e.png)



OKを選択すると、以下のようになります。


![20210401144223.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/97ed3161-e2a3-f4d8-7341-759320629fb3.png)



動作確認を行います。
MacではCommand-Rを実行すると、以下のようなWindowが開きますので、Quitボタンを押下してみてください。
Windowが閉じればOKです。

最後にウィンドウサイズを800x600に変更します。

![20210401145756.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191337/357063e4-d820-0f43-c9c1-688e61c0bf5e.png)

適当な名前で保存します。ここでは「mainUi.ui」とします。


Main Windowを使用する場合も同じように染ます。
名前は、mainUiMW.uiとします。

次にpythonのコードに変換します。

```sh
% pyuic5 mainUi.ui -o mainUi.py
% pyuic5 mainUiMW.ui -o mainUiMW.py
```