PySimpleGUI

  • Python 으로 GUI(Graphincal User Interface)를 만드는 작업.
  • PySimpleGUI는 기본적으로 tkinter(파이썬GUI 모듈)를 사용하지만, 사용자는 한 줄만 변경하여 지원되는 다른 GUI 라이브러리로 변경할 수 있음(파이썬위키).
  • PySimpleGUI 해당 사이트로 이동하면 다양한 실습 체험 가능!

PySimpleGUI install
pip install pysimplegui 또는
pip3 install pysimplegui 을 터미널에 입력.

window 창 만들기

code

python idle에 아래와 같은 코드를 작성하자.

import PySimpleGUI as sg

sg.theme('DarkAmber')   # Add a touch of color
# All the stuff inside your window.
layout = [  [sg.Text('Some text on Row 1')],
            [sg.Text('Enter something on Row 2'), sg.InputText()],
            [sg.Button('Ok'), sg.Button('Cancel')] ]

# Create the Window
window = sg.Window('Window Title Test1', layout)
# Event Loop to process "events" and get the "values" of the inputs
while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
        break
    print('You entered ', values[0])

window.close()

run

시행하면 아래와 같은 창이 뜬다. Enter somethin on Row 2 란에는 아무 글자나 입력이 가능하다.

이미지 뷰어 만들기

Real Python 을 참고함.

code

# img_viewer.py

import PySimpleGUI as sg
import os.path

# First the window layout in 2 columns

file_list_column = [
    [
        sg.Text("Image Folder"),
        sg.In(size=(25, 1), enable_events=True, key="-FOLDER-"),
        sg.FolderBrowse(),
    ],
    [
        sg.Listbox(
            values=[], enable_events=True, size=(40, 20), key="-FILE LIST-"
        )
    ],
]

# For now will only show the name of the file that was chosen
image_viewer_column = [
    [sg.Text("Choose an image from list on left:")],
    [sg.Text(size=(40, 1), key="-TOUT-")],
    [sg.Image(key="-IMAGE-")],
]

# ----- Full layout -----
layout = [
    [
        sg.Column(file_list_column),
        sg.VSeperator(),
        sg.Column(image_viewer_column),
    ]
]

window = sg.Window("Image Viewer", layout)

# Run the Event Loop
while True:
    event, values = window.read()
    if event == "Exit" or event == sg.WIN_CLOSED:
        break
    # Folder name was filled in, make a list of files in the folder
    if event == "-FOLDER-":
        folder = values["-FOLDER-"]
        try:
            # Get list of files in folder
            file_list = os.listdir(folder)
        except:
            file_list = []

        fnames = [
            f
            for f in file_list
            if os.path.isfile(os.path.join(folder, f))
            and f.lower().endswith((".png", ".gif"))
        ]
        window["-FILE LIST-"].update(fnames)
    elif event == "-FILE LIST-":  # A file was chosen from the listbox
        try:
            filename = os.path.join(
                values["-FOLDER-"], values["-FILE LIST-"][0]
            )
            window["-TOUT-"].update(filename)
            window["-IMAGE-"].update(filename=filename)

        except:
            pass

window.close()

들여쓰기 체크!

run

위와 같은 창이 뜨고 png, gif 파일을 볼 수 있다.

PySimpleGUI와 Matplotlib 통합

우선 Matplotlib를 설치해주어야 한다.
python -m pip install matplotlib
이후 matplot은 numpy를 이용하므로 numpy도 설치해주자.
python -m pip install numpy

error

패키지 설치 중 에러가 발생했다.

ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
.
.
.

* The following required packages can not be built: freetype 
* Try installing freetype with `apt-get install libfreetype6-dev` 
  and pkg-config with `apt-get install pkg-config`

일단 위에서 apt-get install libfreetype6-dev and pkg-config with apt-get install pkg-config을 확인했으니 해당 패키지를 설치해주었다.
이후 다시 python -m pip install matplotlib을 하니
Defaulting to user installation because normal site-packages is not writeable라는 코드가 뜨며 정상설치 되지 않는 모습을 보였다. 해당 코드를 구글링하여 https://forums.raspberrypi.com/viewtopic.php?t=272338 이 사이트에서 해결법을 찾았는데,

sudo python3 -m pip install -U pip numpy
sudo python3 -m pip install -U pip matplotlib

위 코드를 작성하면 정상적으로 matplotlib과 numpy가 설치된 것을 확인할 수 있다.

code

import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import PySimpleGUI as sg
import matplotlib

fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))

matplotlib.use("TkAgg")

def draw_figure(canvas, figure):
    figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
    figure_canvas_agg.draw()
    figure_canvas_agg.get_tk_widget().pack(side="top", fill="both", expand=1)
    return figure_canvas_agg

# Define the window layout
layout = [
    [sg.Text("Plot test")],
    [sg.Canvas(key="-CANVAS-")],
    [sg.Button("Ok")],
]

# Create the form and show it without the plot
window = sg.Window(
    "Matplotlib Single Graph",
    layout,
    location=(0, 0),
    finalize=True,
    element_justification="center",
    font="Helvetica 18",
)

# Add the plot to the window
draw_figure(window["-CANVAS-"].TKCanvas, fig)

event, values = window.read()

window.close()

run

PySimpleGUI와 OpenCV 통합

opencv가 설치되어 있지 않다면, 아래 코드를 통해 opencv를 설치하자.
python -m pip install opencv-python

code

import PySimpleGUI as sg
import cv2
import numpy as np

def main():
    sg.theme("LightGreen")

    # Define the window layout
    layout = [
        [sg.Text("OpenCV Demo", size=(60, 1), justification="center")],
        [sg.Image(filename="", key="-IMAGE-")],
        [sg.Radio("None", "Radio", True, size=(10, 1))],
        [
            sg.Radio("threshold", "Radio", size=(10, 1), key="-THRESH-"),
            sg.Slider(
                (0, 255),
                128,
                1,
                orientation="h",
                size=(40, 15),
                key="-THRESH SLIDER-",
            ),
        ],
        [
            sg.Radio("canny", "Radio", size=(10, 1), key="-CANNY-"),
            sg.Slider(
                (0, 255),
                128,
                1,
                orientation="h",
                size=(20, 15),
                key="-CANNY SLIDER A-",
            ),
            sg.Slider(
                (0, 255),
                128,
                1,
                orientation="h",
                size=(20, 15),
                key="-CANNY SLIDER B-",
            ),
        ],
        [
            sg.Radio("blur", "Radio", size=(10, 1), key="-BLUR-"),
            sg.Slider(
                (1, 11),
                1,
                1,
                orientation="h",
                size=(40, 15),
                key="-BLUR SLIDER-",
            ),
        ],
        [
            sg.Radio("hue", "Radio", size=(10, 1), key="-HUE-"),
            sg.Slider(
                (0, 225),
                0,
                1,
                orientation="h",
                size=(40, 15),
                key="-HUE SLIDER-",
            ),
        ],
        [
            sg.Radio("enhance", "Radio", size=(10, 1), key="-ENHANCE-"),
            sg.Slider(
                (1, 255),
                128,
                1,
                orientation="h",
                size=(40, 15),
                key="-ENHANCE SLIDER-",
            ),
        ],
        [sg.Button("Exit", size=(10, 1))],
    ]

    # Create the window and show it without the plot
    window = sg.Window("OpenCV Integration", layout, location=(800, 400))

    cap = cv2.VideoCapture(0)

    while True:
        event, values = window.read(timeout=20)
        if event == "Exit" or event == sg.WIN_CLOSED:
            break

        ret, frame = cap.read()

        if values["-THRESH-"]:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)[:, :, 0]
            frame = cv2.threshold(
                frame, values["-THRESH SLIDER-"], 255, cv2.THRESH_BINARY
            )[1]
        elif values["-CANNY-"]:
            frame = cv2.Canny(
                frame, values["-CANNY SLIDER A-"], values["-CANNY SLIDER B-"]
            )
        elif values["-BLUR-"]:
            frame = cv2.GaussianBlur(frame, (21, 21), values["-BLUR SLIDER-"])
        elif values["-HUE-"]:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
            frame[:, :, 0] += int(values["-HUE SLIDER-"])
            frame = cv2.cvtColor(frame, cv2.COLOR_HSV2BGR)
        elif values["-ENHANCE-"]:
            enh_val = values["-ENHANCE SLIDER-"] / 40
            clahe = cv2.createCLAHE(clipLimit=enh_val, tileGridSize=(8, 8))
            lab = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)
            lab[:, :, 0] = clahe.apply(lab[:, :, 0])
            frame = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)

        imgbytes = cv2.imencode(".png", frame)[1].tobytes()
        window["-IMAGE-"].update(data=imgbytes)

    window.close()

main()

run

동영상을 통해서 받아온 이미지를 흑백으로 변화시키기도 하고 흐르게 만들기도 하고 강도를 높이기도 한다. 흥미로운 경험을 함께 체험해보자.

https://pysimplegui.readthedocs.io/en/latest/#window-object-beginning-a-window 참고함

code

import PySimpleGUI as sg

text = sg.popup_get_file('Please enter a file name')
sg.popup('Results', 'The value returned from popup_get_file', text)

run

기본값은 아래와 같다.

save_As 매개변수를 True로 설정하면 대화상자가 save로 변경되는 걸 확인할 수 있다.

To Do List 창 만들기

code

import PySimpleGUI as sg

layout = [
    [sg.Text('1, '), sg.In(key=1)],
    [sg.Text('2, '), sg.In(key=2)],
    [sg.Text('3, '), sg.In(key=3)],
    [sg.Text('4, '), sg.In(key=4)],
    [sg.Text('5, '), sg.In(key=5)],
    [sg.Button('Save'), sg.Button('Exit')]
    ]

window = sg.Window('To Do List Example', layout)
event, value = window.read()

run

To Do List 창이 뜨는 걸 확인할 수 있다.

그렇다면 할 일이 5개가 넘어가는 경우엔 어떻게 할까?
for문을 정해진 range만큼 반복하면 된다.

code (할 일이 5개가 넘어가는 경우)

import PySimpleGUI as sg

layout = []
for i in range(1,11):  # 원하는 개수만큼 지정하자. 마지막 숫자-1개가 생성된다. 나는 10개의 항목을 원하는 경우 11개로 입력.
    layout += [sg.Text(f'{i}. '), sg.In(key=i)],
layout += [[sg.Button('Save'), sg.Button('Exit')]]

window = sg.Window('To Do List Example', layout)
event, values = window.read()

run

위의 코드를 좀 더 파이썬스럽게 바꿔보자. 리스트를 제대로 활용하는 것이다.

code (코드를 더 간략히)

import PySimpleGUI as sg

layout  = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)] + [[sg.Button('Save'), sg.Button('Exit')]]

window = sg.Window('To Do List Example', layout)

event, values = window.read()

run

code (두 줄로 표현하기)

파이썬에서는 코드를 더 압축하여 표현 가능하다.

import PySimpleGUI as sg

event, values = sg.Window('To Do List Example', layout=[[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)] + [[sg.Button('Save'), sg.Button('Exit')]]).read()

run

profile
개발자로 시작| 공부한 것을 기록합니다.

0개의 댓글