備忘録
つまづいたところやtipsだけをまとめる
インストールとか
コマンドプロンプトで以下を実行してインストール
py -m pip install pysimplegui
プログラムではsgとしてインポートしておく
import PySimpleGUI as sg
テーマ設定
sg.theme()
で設定できる
sg.theme('ここにテーマの名前')
テーマの一覧を表示する
sg.theme_previewer()
私の環境ではすべては表示されなかったのでscrollable=True
を追加してスクロールできるようにした
sg.theme_previewer(scrollable=True)
windowの設定
keep_on_top=True
で最前面表示、grab_anywhere=True
でどこをつかんでも動かせるようにできる
win = sg.Window("テスト",layout,
size=(300, 150),keep_on_top=True,grab_anywhere=True)
無限ループの実行
問題
連打くんを作るにあたって常にf9キーが押されたかどうかを判断する必要があった
ただしこちらのプログラムではtestは一回しか表示されなかった
while True:
print("test")
event, value = win.read()
if event == sg.WIN_CLOSED:
break
原因と対応
event, value = win.read()
はイベントが発生するまで待つらしい
それを防止するためにtimeoutを使う
while True:#これで0.1秒ごとにtestと表示される
print("test")
event, value = win.read(timeout=100) #イベントが発生しなくても0.1秒で待機を抜ける
if event == sg.WIN_CLOSED:
break
exe化とアイコン
準備
あらかじめフォルダを作りそこにpythonのプログラムとexeのアイコンにしたいicoファイルを移動しておく
icon=でアイコン指定
win = sg.Window("テスト",layout,icon='icon.ico',size=(300, 150))
しかしこのままexe化すると常にexeファイルと同じフォルダにiconファイルをおかないとアイコンが変わらないという事態が発生するため、exeファイルへの取り込みを行うためのプログラムを追加する
importの追加
import sys
import os
関数の追加
def resource_path(relative):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative)
return os.path.join(os.path.abspath('.'), relative)
sg.Window部分の変更
icon_path = resource_path('icon.ico')
win = sg.Window("テスト",layout,icon=icon_path,size=(300, 150))
ファイル全体としてはこんな感じ
import PySimpleGUI as sg
import sys
import os
layout = [
[sg.Text("Hello")]
]
def resource_path(relative):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative)
return os.path.join(os.path.abspath('.'), relative)
icon_path = resource_path('icon.ico')
win = sg.Window("テスト",layout,icon=icon_path,size=(300, 150))
while True:
event, value = win.read()
if event == sg.WIN_CLOSED:
break
win.close()
exe化
exe化にはpyinstallerを使う
コマンドプロンプトでインストール
py -m pip install pyinstaller==5.5
後述の理由でバージョンは5.5にしている
「pythonのプログラムとexeのアイコンにしたいicoファイルを移動したフォルダ」でコマンドプロンプトを実行
--onefileでexeファイルを一つにまとめ、--noconsoleでコンソールを非表示にしている。また、エクスプローラー上のアイコンを変更するために--icon=icon.icoでアイコン指定。
pyinstaller --onefile --noconsole --icon=icon.ico test.py
できたexeファイルが重いときは--excludeを利用したり仮想環境を利用する
アイコンをexeファイルに取り込むために生成されたtest.specを開き、
a.datas += [("icon.ico", "icon.ico", "Data")]
を追加する
できたらコマンドプロンプトでpyinstaller test.spec
を実行する
pyinstaller test.spec
pyinstallerのバージョンが最新だとここでKeyError: 'Data'
というエラーが発生したのでバージョンは5.5にしている
蛇足
作成した連打くんのプログラムを貼っておく
import PySimpleGUI as sg
import pyautogui
import keyboard
import sys
import os
sg.theme('black')
layout = [
[sg.Text("連打くん",size=(30,1), justification='center',
font=(None, 20, 'bold'), text_color='yellow',key='txt')],
[sg.Text("1秒間に"),
sg.Slider(range=(10,1000),default_value =100,resolution=10,
orientation='h',size=(11, 15),key='repeat'),
sg.Text("回")
],
[sg.Text("f9で実行、f10で停止")],
[sg.Checkbox("カーソル移動で停止",default=False,key='stop')]
]
def resource_path(relative):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative)
return os.path.join(os.path.abspath('.'), relative)
icon_path = resource_path('cursor.ico')
win = sg.Window("連打くん",layout,icon=icon_path,size=(300, 185),
keep_on_top=True,grab_anywhere=True)
while True:
event, value = win.read(timeout=100)
if keyboard.is_pressed('f9'):
n = int(value['repeat']/10)
win['txt'].update("実行中",text_color='red')
event, value = win.read(timeout=1)
if(value['stop']):
pos = pyautogui.position()
while keyboard.is_pressed('f10') == False:
pyautogui.click(button='left', clicks=n)
if(pos != pyautogui.position()):
break
else:
while keyboard.is_pressed('f10') == False:
pyautogui.click(button='left', clicks=n)
win['txt'].update("連打くん",text_color='yellow')
if event == sg.WIN_CLOSED:
break
win.close()