요즘 시퀀스를 공부하게 되면서

 

전동 드릴/드라이버 구경하다가

 

전기 회로에 사용할건 아니지만 신기하게 생긴 툴앤툴의 와우슬림을 찾았습니다.

 

 

 

팬 사이즈의 전동 드라이버라니 수동 드라이버만 쓰다가 왠건가 싶었죠

 

이거 말고도 샤오미나 다른 회사 제품들도 찾아봤지만

 

와우 슬림이 가성비 갑이기도하고, 다른 사은품도 준다고 하길래 구입했습니다.

 

 

 

 

배송온 와우슬림

 

 

딱 볼펜사이즈입니다.

 

 

 

보관 가방이 없는건 아쉽지만

 

제품 상자를 그대로 써도 괜찬을거같아요.

 

USB -C 케이블도 있고

 

 

 

 

 

 

실제 사용해본 영상입니다.

 

나중에 전자 제품 다룰때 쓰기 딱 좋아보이네요.

 

 

 

 

Tcl(tool command language)/Tk, tkinter

- Tcl :  웹, 데스트탑 어플, 네트워크, 테스팅 등 다양한 용도로 동적 프로그래밍 하기 좋은 언어

- Tk : GUI 라이브러리 제공하는 툴킷

- tkinter : Tcl/Tk 파이썬 레퍼로 tkinter 패키지로 gui 프로그래밍

 

 

1. tkinter window 관리 예제

- 윈도우 만들고, 크기 고정하고, X 누르면 메시지박스, iconify 버튼으로 아이콘화, quit버튼으로 종료

import tkinter
from tkinter import *
from tkinter import messagebox

global window

window = Tk()
window.title("window = Tk()")
window.geometry("300x300+100+100")
window.resizable(width=False, height = False)

def ask_quit():
    result = messagebox.askquestion("Msg", "quit?")
    if result == "yes":
        window.destroy()

label = Label(window, text="Buttons")
label.pack() # pack()윈도우에 배치
iconBtn = Button(window, text="iconify", command=window.iconify) #iconify 아이콘화
iconBtn.pack()
quitBtn = Button(window, text="quit", command=window.destroy)
quitBtn.pack()

window.protocol("WM_DELETE_WINDOW", ask_quit)
window.mainloop()

 

 

tkinter의 widget(window gadget) 클래스 

- tkinter의 위젯으로 frame, canvas가 있다.

- 하나의 윈도우에는 여러 프레임을 넣을 수 있다.

- 각 프레임에는 여러 캔버스를 넣을 수 있다.

- 각 캔버스에는 여러 라벨과 버튼 등의 위젯을 넣을 수 있다.

 

위젯 종류

- entry : 문자열 입력 공간

- scale : 슬라이드로 설정

- menu : 팝업 팝다운 메뉴

- 등

 

https://m.blog.naver.com/sisosw/221408280038

 

 

 

2. 윈도우 안에 프레임과 캔버스 그리기

import tkinter
from tkinter import *

window = Tk()
window.title("window - tk()")
window.geometry("600x600+200+100")
window.resizable(width=False, height=False)



frame1 = Frame(window, bg="light green", cursor="heart", bd=5, padx=10, pady=10, relief=GROOVE) #relief 프레임 기본 스타일
#relief : flat(기본), raised(버튼올린모양), sunken(버튼눌린모양), groove, ridge 등(대문자)
frame1.grid(row=0,column=0)
frame2 = Frame(window, bg="yellow", cursor="man", bd=5, padx=10, pady=10, relief=GROOVE)
frame2.grid(row=1,column=0)
frame3 = Frame(window, bg="yellow", cursor="plus", bd=5, padx=10, pady=10, relief=GROOVE)
frame3.grid(row=2, column=0)


canvas_11 = Canvas(frame1, bg="lime", width=100, height=100)
canvas_11.grid(row=0, column=0, fill=None, padx=10, pady=10)
canvas_12 = Canvas(frame1, bg="orange", width=150, height=100)
canvas_12.grid(row=0, column=1, fill=None, padx=10, pady=10)
canvas_13 = Canvas(frame1, bg="grey", width=100, height=100)
canvas_13.grid(row=1, column=1, fill=None, padx=10, pady=10)


canvas_21 = Canvas(frame2, bg="magenta", width=200, height=50)
canvas_21.grid(row=0, column=0, fill=None, padx=10, pady=10)
canvas_22 = Canvas(frame2, bg="brown", width=200, height=50)
canvas_22.grid(row=0, column=1, fill=None, padx=10, pady=10)
canvas_23 = Canvas(frame2, bg="sky blue", width=200, height=50)
canvas_23.grid(row=1, column=0, fill=None, padx=10, pady=10)

canvas_31 = Canvas(frame3, bg="light green", width=400, height=50)
canvas_31.grid(row=0, column=0, fill=None, padx=10, pady=10)
window.mainloop()

 

위젯 배치 layout

- 압축 배치 pack() : pack(fill=BOTH)  # fill= X, Y, BOTH  

- 격자 배치 grid() : grid(row=2, column=1)

- 절대 위치 배치 place() : place(x=200, y=200)

 

 

 

3. 압축 배치 연습

 

from tkinter import *

window =Tk()
window.title("testing pack layout")
window.geometry("400x300+100+200")



label1 = Label(window, text="label 1", bg="red", fg="white").pack(fill=X, padx=10, pady=10)
label2 = Label(window, text="label 2", bg="green", fg="black").pack(fill=X, padx=10, pady=10)
label3 = Label(window, text="label 3", bg="yellow", fg="white").pack(fill=X, padx=10, pady=10)

label4 = Label(window, text="label 4", bg="red", fg="black").pack(fill=X,padx=10, pady=10, side=LEFT)
label5 = Label(window, text="label 5", bg="green", fg="black").pack(fill=X, padx=10, pady=10, side=LEFT)
label6 = Label(window, text="label 6", bg="blue", fg="black").pack(fill=X, padx=10, pady=10, side=LEFT)

listbox = Listbox(window)
listbox.pack(fill=BOTH, expand=1)
L = [100, 200, 300, 400, 500]
for i in range(len(L)):
    listbox.insert(END, str(L[i]))

mainloop()

 

 

grid 함수

- column = 열, row = 행

- columnspan = 위젯이 차지하는 열 칸 수, rowspan = 위젯이 차지할 행칸 수

- in : 위젯이 놓일 위젯, 디폴트는 부모 위젯

- sticky : 위젯을 어떻게 붙일건지 디폴트는 중앙, NSEW는 셀 경계 딱붙인다.

 

entry 위젯 주요 함수

- focus() : 키보드 입력 가능하게 함

- bind() : 특정 이벤트시 실행 함수 바인드

 

 

 

 

4. 그리드 레이아웃과 엔트리 바인드

- window.bind()와 Button(command=())로 엔터키를 누르거나("<Return>"), 버튼누를시 fetch()함수 호출

 -> 엔터누르거나 fetch 버튼 클릭 시 fetch 함수대로 입력 데이터가 잘 출력된다.

from tkinter import *

def fetch(cells):
    print("- input data -")
    for i, e in enumerate(cells):
        print("  {0}:{1}".format(fields[i], e.get()))

def make_form(fields):
    cells = []
    for r, field in enumerate(fields):
        label = Label(window, width=10, text= field)
        entry = Entry(window)
        label.grid(row=r, column=0, sticky=NSEW)
        entry.grid(row=r, column=1, sticky=NSEW)
        cells.append(entry)
    return cells

if __name__ == "__main__":
    window = Tk()
    window.title("Input Dialog with label and entry")
    fields = ("Name", "Age", "Address")
    cells = make_form(fields)
    window.bind("<Return>", (lambda event, e=cells: fetch(e)))
    #엔터키 눌릴떼 람다식 호출 바인드
    #cells를 e에 담고 fetch 호출
    # 주의 : bind 함수 호출시 lambda 식 앞단에 인수를 2개해야한다.
    Button(window, text="Fetch", bg="green",
           command=(lambda e=cells:fetch(e))).grid(row=3, column=0, sticky=NSEW)
    # 버튼 눌릴때도 fetch(e) 호
    Button(window, text="Quit", bg="Red", command=window.destroy).grid(row=3, column=1, sticky=NSEW)
    print("grid size : ", window.grid_size())
    window.grid_columnconfigure(1, weight=1)
    window.grid_rowconfigure(0, weight=1)
    window.mainloop()

 

 

캔버스 객체의 함수들

- after(delay_ms, callback=None, *args) : 딜레이 타임 후 콜백함수 호출

- bind(sequence=None, func=None, add=None)  : 시퀀스 이벤트에 func 바인딩

- bind_all(csequence=None, func=None, add=None) : 모든 위젯에 func 바인딩

- bind_class(className, sequence=None, func=None, addd=None) : 해당 클래스 모든 위젯에 이벤트 func 바인딩

- create_image/line/oval/polygon/rectangle/text/window

- pos = canvas.coords(객체이름, pos) : 해당 객체 위치

- destroy() : 위젯과 객체제거

- mainloop() : 반복 시작

- quit() 반복 중지

- move(item, dx, dy) : 해당 아이템 객체를 이동

- update() 디스플레이 갱신

 

 

 

Event

- 버튼 : <Button-1>(마우스 왼쪽버튼 클릭), <Button-2> (마우스 휠 클릭), <button-3> (마우스 우클릭)

- 모션 : <Motion>(마우스 움직일때), <B1-Motion> 마우스 좌클릭채 움직일때, ...

- 위젯 동작 : <Configure> 위젯 모양 변경시, <Enter> 위젯안으로 마우스 들어갈때, <Leave> 위젯에서 나올때

- etc ...

 

 

 

 

5. 프레임, 캔버스 크기변경 이벤트 시 함수 호출

- 모든 위젯 크기 변경시 onsize 호출

- 그 중 위젯이 프레임일때 현재 크기반영해 라벨 변경

from tkinter import *

def onSize(event):
    if event.widget == frame: # 이벤트 호출된 위젯이 프레임인경우
        frame.update() # 라벨 변경전 갱신
        label_fr.configure(text="frame size: {}x{}".format(frame.winfo_width(), frame.winfo_height()))
        canvas.update()
        label_cnv.configure(text="canvas size: {}x{}".format(canvas.winfo_width(), canvas.winfo_height()))
    
    
if __name__ == "__main__":
    global label_Fr, label_cnv, frame, canvas
    window =Tk()
    window.title("finding frame and canvas size at resizing events")
    frame = Frame(window, bg="light green", bd=10, padx=50, pady=50, relief=GROOVE)
    frame.pack(expand=YES, fill=BOTH)
    canvas = Canvas(frame, bg="white", width=600, height=400)
    canvas.pack(expand=YES, fill=BOTH, padx=10, pady=10) #frame, canvas 양방향 조절 가능
    frame.update()
    label_fr = Label(canvas, text="frame size: {} x {}".format(frame.winfo_width(), frame.winfo_height()))
    label_fr.grid(row=0, column=0, sticky=N)
    canvas.update()
    label_cnv = Label(canvas, text="canvas size: {} x {}".format(canvas.winfo_width(), canvas.winfo_height()))
    label_cnv.grid(row=1, column=0, sticky=S)
    
    # <Configure> : 위젯모양변경시 이벤트 -> onSize() 호출
    # bind_all(컨피겨, func) -> 모든 위젯 크게 변경시 onsize() 호출 
    window.bind_all("<Configure>", onSize)
    window.mainloop()

 

 

 

 

+ 깃 로컬 저장소를 원격 저장소에 올리기

1. git init으로 깃 저장소 초기화

2. git add . 모든 파일 스태징

3. 커밋

 

4. git remote add origint 원격저장소 주소

5. git remote -v로 연결되었는지 확인

6. git push -u origit master 로컬 저장소 브랜치를 원격 저장소 master로 푸시(u는 지역과 원격 연결을 위해 한번만)

 

 

7. 깃헙에 잘올라갔다.

우리 나라 시중에 나오는 대부분의 프로그래밍 강의나 교재들은

 

기본서가 대부분이지 않나 무슨 언어 교재 하나 목차를 보면

 

언어 만들어진 배경, 변수, 타입, 함수, 객체, 상속, 파일 입출력 정도는 다 있고

 

여기다가 조금 더 +알파만 하고 끝나는게 대부분이더라

 

 

 

 

내가 우리나라 교재나 자료에서 너무 답답하던게

 

이런 기초적인 내용들만 가지고 파는 책들이 대부분이고

 

'프로젝트로 배우는 %#!$#'라면서 프로젝트 한다는 책을 보면

 

주사위 게임, 계산기, 크롤링해서 머신러닝 돌리기 같이 처음 언어 배우는 사람들에게야 연습하는데 도움되도

 

프로그래밍 기본적인 감각은 땟지만 실제 프로젝트 경험이 없는 나한태는 완전히 도움이 안된다고는 하기는 어려워도

 

그렇다고 그런 책들 보고 연습해서 준비해도 실제 경험해본 프로젝트니 포트폴리오라고 하기에는 민망한 내용들 밖에 없었다.

 

 

 

그냥 편하게 말하면 opencv를 처음에 빌드해서 쓰려고하는데 cmake로 경로 설정해서 makefile 만들고 어째저째진행했는데 cmake가 뭐고 makefile이 뭐고, 파이썬으로 opencv를 쓰면 파이썬 래퍼니 뭐니 하는것들을 제대로 설명해주는 책을 거의 보질 못했엇다. 파이썬에서 느린거 c/c++로 구현하면 그걸 어떻게 쓸수있게 햇냐.

 

 

내가 어디 박혀서 독학만 하느라 나만 모르는 걸수도 있지만

 

기본적인 내용 말고 실제 써먹을수 있는건 어디서 배우나 답답하던 차에 이책을 찾게 되었다.

 

이 책도 절반정도는 기본적인 내용이지만 절반은 너무 깊게 파고들지도 않으면서 기본서보다는 더 멀리 나간 내용들이다.

 

 

 

 

중간에 아는 내용도 많다보니 1 ~ 2시간 정도 쭉 봤는데,

 

thinker나 matplotlib까지는 보통 책들에도 자주 나오기는 하지만 실제로 뭔가 만드는듯한 예제들이 꽤 있고

 

동시/병렬처리 프로그래밍, 코딩 테스트에 관심없지만 공부하기엔 적당한 분량으로 자료구조와 알고리즘도 있다. 

 

 

특히 가장 마음에 드는 부분은 마지막에 사용자 정의 패키지/모듈 c/c++ 확장 모듈

 

이런 내용들까지 알려주는 프로그래밍 교재가 우리나라 책중에 이거말고 있는진 모르겠다.

 

 

 

 

우리나라 대부분 코딩 교재란게 클래스 만들고 조금만 더하고 끝나니까

오픈 소스봐도 빌드에서 막히고, 다른 뭔지도 모를 문제로 정말 삽질을 많이 했었다.

 

 

글만 잘 찾아보고 읽었어도 해맬 일이 훨씬 적었겠지만 그렇게까지 머리 좋지도 끈기도 없어서

이렇게 친절하게 이만큼이라도 알려주는 책이 있는게 어딘가 싶었다.

 

 

 

+ Recent posts