はじめに
PySimpleGUIは、Python用のGUIライブラリです
これを使用して、16ビットの基底(2進数、8進数、10進数、16進数)を変換するアプリを作成しました。
インストールと実行方法
ダウンロード
ソースは、https://github.com/tostos5963/PySimpleGUI-BaseConverter で公開していますので以下のどちらかの手順でダウンロードしてください。
git clone
git clone https://github.com/tostos5963/PySimpleGUI-BaseConverter.git
URL部は github のサイトで、①[Code]押下 → ②URL コピー を押下したらクリップボードにコピーできます。
ZIPファイル
①[Code]押下 → ② [Download ZIP]押下で、ZIPファイルをダウンロードできます。ダウンロードしたら任意のフォルダに展開してください。
Windowsの場合
pip install pysimplegui
python BaseConverter.py
Linux (ubuntu)の場合
pip3 install pysimplegui
python3 Sliding15Puzzle.py
以下のエラーが出た場合
ModuleNotFoundError: No module named 'tkinter'
python3-tk をインストールしてください
sudo apt-get install python3-tk
Macの場合
すみません。動作すると思いますがMacを所持していないため確認できていません。
使用方法
- 10進数を入力できます。[+]押下で+1、[-]押下で-1 します。
- 2進数を表示します。
- 8進数を表示します。
- 16進数を表示します。
- 2進数を変更できます。押下すると[0]~[1]が順に変化します。
- 8進数を変更できます。押下すると[0]~[7]が順に変化します。
- 16進数を変更できます。押下すると[0]~[F]が順に変化します。
ソースコード
主な処理の説明です。
初期処理
def __init__(self):
self.dec_value = 0
# 正規表現 (Regular expression):[+][-] button KEY
self.sign_btn_pattern = re.compile(r'dec-(?P<SIGN>plus|minus)')
# 正規表現 (Regular expression):numeric button KEY
self.value_btn_pattern = re.compile(r'^(btn|inp)-(?P<BASE>bin|oct|hex|dec)-(?P<POS>\d+)')
bit_frame_list = []
bit_frame_list.append(sg.Frame("BIT", [
[sg.Text("BIN:")],
[sg.Text("OCT:")],
[sg.Text("HEX:")]], title_location=sg.TITLE_LOCATION_TOP))
# 数値 button を作成
oct_idx = 5 # OCT 6桁 = 5 4 3 2 1 0
hex_idx = 3 # HEX 4桁 = 3 2 1 0
for bit in reversed(range(16)):
# BIN button : 1 bit
btn_bit = sg.Button('0', size=(1,1), key="btn-bin-{:d}".format(bit), enable_events=True, button_color=('#000000','#ffffff'))
if (bit % 3) == 0:
# OCT button : 3 bits 毎に作成
btn_oct = sg.Button('0', size=(1,1), key="btn-oct-{:d}".format(oct_idx), button_color=('#000000','#ffffff'))
oct_idx = oct_idx - 1
else:
# OCT button が不要なビット位置にも無効 button を作成(無いとFrame()内の button 位置がビット毎にずれる)
btn_oct = sg.Button(' ', size=(1,1), key="oct{:d}".format(bit), disabled=True, button_color="#64778d")
if (bit % 4) == 0:
# HEX button : 4 bits 毎に作成
btn_hex = sg.Button('0', size=(1,1), key="btn-hex-{:d}".format(hex_idx), button_color=('#000000','#ffffff'))
hex_idx = hex_idx - 1
else:
# HEX button が不要なビット位置にも無効 button を作成(無いとフレーム()内の button 位置がビット毎にずれる)
btn_hex = sg.Button(' ', size=(1,1), key="hex{:d}".format(bit), disabled=True, button_color="#64778d")
# Frame(1bit : BIN, OCT, HEX) を作成
bit_frame_list.append(sg.Frame("{:>2d}".format(bit), [[btn_bit], [btn_oct], [btn_hex]],
title_location=sg.TITLE_LOCATION_TOP, element_justification='center'))
# DEC: テキストフィールドの変更イベントが必要なので Spin ではなく Input を使用
# Spin → (Input, [+], [-]) (need to fire the text field change event)
self.layout = [[sg.Text("DEC:"), sg.Input('', size=(7, 1), key="inp-dec-0", enable_events=True),
sg.Button('+', key="dec-plus"), sg.Button('-', key="dec-minus")],
[sg.Text("BIN:"), sg.Text('', key="disp-bin")],
[sg.Text("OCT:"), sg.Text('', key="disp-oct")],
[sg.Text("HEX:"), sg.Text('', key="disp-hex")],
bit_frame_list,
[sg.Button('Exit')] ]
self.window = sg.Window('BaseConverter', self.layout)
dec_value は入力された数値を保持する変数です。
sign_btn_pattern は10進数の[+][-]のどちらを押下されたか判断するための正規表現です。
value_btn_pattern は、2進数、8進数、16進数のどのボタンを押下されたか、または10進数の数値が変更されたかを判断するための正規表現です。
layout はウィンドウに表示する エレメント(ウィジェット)のリストです。
window は、PySimpleGUIのWindow です。タイトル名とlayoutを設定しています。
値更新とボタン表示更新(2進数)
# BIN: Text と button を更新
def update_bin(self):
# BIN Text 更新
self.window['disp-bin'].Update("{:>b}".format(self.dec_value))
# BIN の各 button 更新
mask = 0x0001
for bit in range(16):
key = "btn-bin-{:d}".format(bit)
if (self.dec_value & mask) == 0:
bit_str = "0"
else:
bit_str = "1"
if self.window[key].ButtonText != bit_str:
self.window[key].Update(bit_str)
mask = mask << 1
保持している値 (dec_value)を2進数(テキスト/ボタン)に反映します。
同様に、update_oct()は8進数、update_hex()は16進数、update_dec()は10進数のテキスト/ボタンに反映します。
2進数のボタンを押下したときの処理
def onclick_bin(self, pos):
# BIN button (0 → 1)(1 → 0)
key = "btn-bin-{:d}".format(pos)
if self.window[key].ButtonText == '0':
self.window[key].Update("1")
else:
self.window[key].Update("0")
# BIN buttons → number (ボタンの0/1 を並べて BIN 文字列を作成)
num_str = ""
for bit in reversed(range(16)):
key = "btn-bin-{:d}".format(bit)
num_str = num_str + self.window[key].ButtonText
self.dec_value = int(num_str, 2)
self.window['disp-bin'].Update("{:>b}".format(self.dec_value))
self.update_oct()
self.update_dec()
self.update_hex()
引数の pos は何番目のボタンを押下されたかを表します。一番右が0で一番左が15です。
押下されたボタンの数字が[0]であれば[1]に、[1]であれば[0]にします。
2進数のボタンから2進数の文字列を作成しint()で数値変換したものを dec_value に設定します。
2進数(テキスト)を更新し、他の基底(8進数、10進数、16進数)の更新処理(update_oct(), update_dec(), update_hex() )を呼び出します。
同様に、onclik_oct()は8進数、onclik_hex()は16進数のボタンが押下された時の処理、onchange_dec()は 10進数の値が変更されたときの処理です。
10進数の [+] または [-] が押下された時の処理
# DEC [+] or [-]
def onchange_plus_minus(self, dec_num_str, sign):
try:
d_val = int(dec_num_str)
if sign == 'plus':
# [+] button = 10進数を + 1
d_val = d_val + 1
if (d_val > 0xFFFF):
d_val = 0xFFFF
else:
# [-] button = 10進数を - 1
d_val = d_val - 1
if (d_val < 0):
d_val = 0
except:
d_val = self.dec_value
# DEC 表示
if (dec_num_str != str(d_val)):
self.window["inp-dec-0"].Update(str(d_val))
if self.dec_value != d_val:
self.dec_value = d_val
self.update_bin()
self.update_oct()
self.update_hex()
引数 dec_num_str は10進数テキスト、sign は符号([+]=’plus’, [-]=’minus’)です。
dec_num_str を数値変換し、sign が ‘plus’ の場合は +1、’minus’ の場合は -1 します。+1したときに 0xFFFFを超えた場合は 0xFFFF に、-1したときに0未満になった場合は 0 にします。
値が変更されたら10進数のテキスト部更新、変更後の値を dec_value に保持し、 他の基底(8進数、10進数、16進数)の更新処理(update_oct(), update_dec(), update_hex() )を呼び出します。
メインループ
def main_loop(self):
while True:
event, values = self.window.read()
if event in (sg.WIN_CLOSED, 'Exit'):
break
# [+][-] button ?
m = self.sign_btn_pattern.match(event)
if m:
self.onchange_plus_minus(values["inp-dec-0"], m.group('SIGN'))
continue
# numeric button ?
m = self.value_btn_pattern.match(event)
if m:
base_type = m.group('BASE') # 基底
pos = int(m.group('POS')) # button 位置
if base_type == 'dec':
self.onchange_dec(values[event])
elif base_type == 'bin':
self.onclick_bin(pos)
elif base_type == 'oct':
self.onclick_oct(pos)
elif base_type == 'hex':
self.onclick_hex(pos)
self.window.close()
イベントの内容により各処理を呼び出します。
Exitボタン押下 : 終了
[+][-]ボタン押下 : onchange_plus_minus()
10進数テキスト変更 : onchange_dec()
2進数ボタン押下: onclick_bin()
8進数ボタン 押下: onclick_oct()
16進数ボタン 押下: onclick_hex()
まとめ
今回は、PySimpleGUIを使って、基底変換アプリを作成しました。
コメント