fc2ブログ

PyQtを使う

 RにGUIがないので、R.NET(C#)でGUIを作成してみたのが前回のお話でした。最近よく使うPythonでも似たような内容に直面しています。ただ、Pythonの方はRに比べ、いろいろとGUIの作り方(アプローチ)があるようですね。今回は、PyQtを使って簡単なGUIを作ってみました。
 PyQtはフリーウェアでセットアップは「pip install pyqt5」でOK。GUIの作成ツールは、Anacondaをインストールした際に、一緒にセットアップされている「Qt Designer」を使います。designer.exeは、私の環境では以下のフォルダ内に入っていたので実行します。
C:\Anaconda3\Library\bin
 起動画面は以下の通りです。➀Main Window、➁画面サイズの順に選択し、➂作成ボタンを押します。Qt_designer1_180225.png Visual Studioのような画面が表示されますので、同じ要領でFormを作成します。Qt_designer2_180225.png 各オブジェクトのプロパティもVSと同じような操作です。オブジェクトを配置した後には「シグナル/スロットエディタ」で動作を設定します。この部分はVSと違った感があり、いまいち理解できていません・・。とりあえず、ボタンをクリックしたときにイベントが上がるような暫定設定をしました。作成時に「Ctrl + R」を押すと、プレビュー画面を確認できます。Qt_designer3_180225.png Formとシグナル/スロットエディタによる動作を含め、保存すると、uiファイルが作成されます。中身はxmlファイルです。
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>480</height>
</rect>
</property>
・・・・
 次に、uiファイルをpyファイルに変換します。作成したTestWindow.uiからTestWindow.pyを作成する場合は以下のコマンドをコマンドプロンプトから実行します。
python -m PyQt5.uic.pyuic -x TestWindow.ui -o TestWindow.py
ui_to_py変換_180225 変換されたTestWindow.pyをVisual Studio Code上で実行してみると、いい感じに表示できました。VScode確認_180225 そのまま、VSCodeでイベント/アクション関連を手直ししました。ソフトの仕様は、以下の通りです。
  ➀  スピンボタンを動かすと、LCDにその値が表示される。
  ➁  Input1ボタンを押すと、Outputに既定の文字が表示され、LCDにボタンの番号(1)が表示される。
  ➂  Input2ボタンを押すと、Inputボックス内の文字列がOutputボックスに表示され、LCDにボタンの番号(2)が表示される。
  ④ Clearボタンを押すと、Inputボックス、Outputボックスの文字がクリアされ、スピンボタンとLCDが初期値(0)に戻る。
 完成版のプログラムは以下の通りです。
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'TestWindow.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(640, 480)
MainWindow.setLocale(QtCore.QLocale(QtCore.QLocale.Japanese, QtCore.QLocale.Japan))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.Input1_btn = QtWidgets.QPushButton(self.centralwidget)
self.Input1_btn.setGeometry(QtCore.QRect(440, 140, 112, 34))
self.Input1_btn.setObjectName("Input1_btn")
self.Input2_btn = QtWidgets.QPushButton(self.centralwidget)
self.Input2_btn.setGeometry(QtCore.QRect(440, 200, 112, 34))
self.Input2_btn.setObjectName("Input2_btn")
self.Clear_btn = QtWidgets.QPushButton(self.centralwidget)
self.Clear_btn.setGeometry(QtCore.QRect(440, 320, 112, 34))
self.Clear_btn.setObjectName("Clear_btn")
self.InputTextBox = QtWidgets.QTextEdit(self.centralwidget)
self.InputTextBox.setGeometry(QtCore.QRect(70, 90, 291, 101))
self.InputTextBox.setObjectName("InputTextBox")
self.InputLabel = QtWidgets.QLabel(self.centralwidget)
self.InputLabel.setGeometry(QtCore.QRect(30, 60, 75, 18))
self.InputLabel.setObjectName("InputLabel")
self.lcdNumber = QtWidgets.QLCDNumber(self.centralwidget)
self.lcdNumber.setGeometry(QtCore.QRect(516, 40, 41, 51))
font = QtGui.QFont()
font.setPointSize(20)
self.lcdNumber.setFont(font)
self.lcdNumber.setLayoutDirection(QtCore.Qt.RightToLeft)
self.lcdNumber.setAutoFillBackground(False)
self.lcdNumber.setStyleSheet("QLCDNumber{\n"
" color: rgb(255, 255, 0);\n"
" background-color: rgb(128, 128, 128);\n"
" font: 20pt \"MS UI Gothic\";\n"
"}")
self.lcdNumber.setSmallDecimalPoint(False)
self.lcdNumber.setDigitCount(1)
self.lcdNumber.setSegmentStyle(QtWidgets.QLCDNumber.Flat)
self.lcdNumber.setObjectName("lcdNumber")
self.OutputTextBox = QtWidgets.QTextBrowser(self.centralwidget)
self.OutputTextBox.setGeometry(QtCore.QRect(70, 240, 291, 101))
self.OutputTextBox.setObjectName("OutputTextBox")
self.OutputLabel = QtWidgets.QLabel(self.centralwidget)
self.OutputLabel.setGeometry(QtCore.QRect(30, 210, 75, 18))
self.OutputLabel.setObjectName("OutputLabel")
self.spinBox = QtWidgets.QSpinBox(self.centralwidget)
self.spinBox.setGeometry(QtCore.QRect(430, 40, 61, 51))
font = QtGui.QFont()
font.setPointSize(20)
self.spinBox.setFont(font)
self.spinBox.setObjectName("spinBox")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 640, 31))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)

self.retranslateUi(MainWindow)
#self.Clear_btn.clicked.connect(self.Clear_btn.click)
#self.Input1_btn.clicked.connect(self.Input1_btn.click)
#self.Input2_btn.clicked.connect(self.Input2_btn.click)
#self.spinBox.valueChanged['int'].connect(self.spinBox.setValue)
self.Input1_btn.clicked.connect(self.func1)
self.Input2_btn.clicked.connect(self.func2)
self.Clear_btn.clicked.connect(self.clear)
self.spinBox.valueChanged['int'].connect(self.lcdout)
QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.Input1_btn.setText(_translate("MainWindow", "Input 1"))
self.Input2_btn.setText(_translate("MainWindow", "Input 2"))
self.Clear_btn.setText(_translate("MainWindow", "Clear"))
self.InputLabel.setText(_translate("MainWindow", "Input"))
self.OutputLabel.setText(_translate("MainWindow", "Output"))

def lcdout(self):
self.lcdNumber.display(self.spinBox.text())

def func1(self):
self.OutputTextBox.setText("Input 1 Button has clicked!")
self.lcdNumber.display(1)

def func2(self):
self.OutputTextBox.setText(self.InputTextBox.toPlainText())
self.lcdNumber.display(2)

def clear(self):
self.InputTextBox.clear()
self.OutputTextBox.clear()
self.spinBox.setValue(0)
self.lcdNumber.display(0)

if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
70~73行目(修正前)から74~77行目(修正後)に手直ししました。また、89~104行目にアクション用の関数を追加しました。

➀の実行結果です。PyQt実行結果Win1_180225➁の実行結果です。PyQt実行結果Win2_180225➂の実行結果です。PyQt実行結果Win3_180225すべて、問題なく仕様通り動作しました。

 Python(PyQt)の良い所は、プラットフォームを選ばない所でしょう。同じ上記プログラム(TestWindow.py)をMacBook Airにコピーし、VS Code上で実行しました。PyQt実行結果Mac1_180225PyQt実行結果Mac2_180225PyQt実行結果Mac3_180225 これも問題なしです。同じプログラムでプラットフォームを選ばない魅力、大変素晴らしいですね。.NET Frameworkがはるかに霞んで見えます・・。
スポンサーサイト



コメント

非公開コメント

ご訪問者数

(Since 24 July, 2016)

タグクラウド


プロフィール

Dr.BobT

Author: Dr.BobT
興味のおもむくままに生涯考え続けるエンジニアでありたい。

月別アーカイブ

メールフォーム

名前:
メール:
件名:
本文: