mySQL을 설치해서 파이썬과 같이 사용해 보는 GUI프로그래밍 입니다.
지난주와 이번주 보고 있는 책이 파이썬 GUI 프로그래밍 책입니다.
mySQL을 설치해서 파이썬과 같이 사용해 보는 GUI프로그래밍 입니다.
파이썬이 다방면에서 좋은 결과물들을 많이 만들어 내고 있습니다. IT개발 분야에서 프론트 엔드, 백엔드, 웹 분야, AI와 데이터 사이언스를 가리지 않고 힘을 내고 있습니다.
저는 주로 개발하고 강의하던 분야가 닷넷과 아이폰이였는데 4년전부터 파이썬 분야로 넘어와서 강의를 하고 있습니다. ^^
혹시 mySQL이 처음이시면 아래의 주소에서 커뮤니티 에디션을 받으시면 됩니다. 최신 버전은 8.0이고 이전 버전은 5.7을 받으셔도 됩니다. 저는 5.7 버전을 받았습니다.
아래의 주소에서 윈도우용 인스톨러가 있는 버전을 받으시면 설치가 편하게 진행됩니다.
https://dev.mysql.com/downloads/file/?id=479142
커뮤니티 버전은 대부분 무료로 제공됩니다.
연습용으로 또는 개발용으로 설치할 예정입니다. 대부분 기본 옵션을 선택하시면 됩니다.
암호만 추가로 입력하시면 되고 계정을 추가하시면 됩니다. 저는 "admin"이라는 계정을 추가해서 암호를 지정했습니다.
파이썬 3.6 버전이 미리 설치되어 있습니다. 여기에 mySQL에 접속하려면 약간의 추가 모듈을 pip명령으로 설치하시면 됩니다. 파이썬 커넥터 드라이버를 설치해야 한다.
https://dev.mysql.com/doc/connector-python/en/connector-python-installation-binary.html
커맨드창을 오픈해서 아래와 같이 실행한다.
pip install mysql-connector-python
아래의 샘플 코드는 크게 3개의 파일로 구성되어 있습니다.
- 연결문자열을 별도로 관리할 수 있는 파일입니다.
# GuiDBConfig.py
#접속 관련 정보를 딕셔너리에 저장
dbConfig = {
'user':'jonathan',
'password':'1234',
'host':'127.0.0.1',
}
2)SQL구문을 실행하는 데이터를 다루는 클래스 파일입니다.
# GUI_MySQL_class.py
# 아래의 코드를 수정해야 한다.
import mysql.connector as mysql
import GuiDBConfig as guiConf
class MySQL():
# class variable
GUIDB = 'GuiDB'
#------------------------------------------------------
def connect(self):
# connect by unpacking dictionary credentials
conn = mysql.connect(**guiConf.dbConfig)
# create cursor
cursor = conn.cursor()
return conn, cursor
#------------------------------------------------------
def close(self, cursor, conn):
# close cursor
cursor.close()
# close connection to MySQL
conn.close()
#------------------------------------------------------
def showDBs(self):
# connect to MySQL
conn, cursor = self.connect()
# print results
cursor.execute("SHOW DATABASES")
print(cursor)
print(cursor.fetchall())
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def createGuiDB(self):
# connect to MySQL
conn, cursor = self.connect()
try:
cursor.execute(
"CREATE DATABASE {} DEFAULT CHARACTER SET 'utf8'".format(MySQL.GUIDB))
except mysql.Error as err:
print("Failed to create DB: {}".format(err))
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def dropGuiDB(self):
# connect to MySQL
conn, cursor = self.connect()
try:
cursor.execute(
"DROP DATABASE {}".format(MySQL.GUIDB))
except mysql.Error as err:
print("Failed to drop DB: {}".format(err))
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def useGuiDB(self, cursor):
'''Expects open connection.'''
# select DB
cursor.execute("USE guidb")
#------------------------------------------------------
def createTables(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# create Table inside DB
cursor.execute("CREATE TABLE Books ( \
Book_ID INT NOT NULL AUTO_INCREMENT, \
Book_Title VARCHAR(25) NOT NULL, \
Book_Page INT NOT NULL, \
PRIMARY KEY (Book_ID) \
) ENGINE=InnoDB")
# create second Table inside DB
cursor.execute("CREATE TABLE Quotations ( \
Quote_ID INT AUTO_INCREMENT, \
Quotation VARCHAR(250), \
Books_Book_ID INT, \
PRIMARY KEY (Quote_ID), \
FOREIGN KEY (Books_Book_ID) \
REFERENCES Books(Book_ID) \
ON DELETE CASCADE \
) ENGINE=InnoDB")
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def createTablesNoFK(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# create Table inside DB
cursor.execute("CREATE TABLE Books ( \
Book_ID INT NOT NULL AUTO_INCREMENT, \
Book_Title VARCHAR(25) NOT NULL, \
Book_Page INT NOT NULL, \
PRIMARY KEY (Book_ID) \
) ENGINE=InnoDB")
# create second Table inside DB --
# No FOREIGN KEY relation to Books Table
cursor.execute("CREATE TABLE Quotations ( \
Quote_ID INT AUTO_INCREMENT, \
Quotation VARCHAR(250), \
Books_Book_ID INT, \
PRIMARY KEY (Quote_ID) \
) ENGINE=InnoDB")
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def dropTables(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
cursor.execute("DROP TABLE quotations")
cursor.execute("DROP TABLE books")
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def showTables(self):
# connect to MySQL
conn, cursor = self.connect()
# show Tables from guidb DB
cursor.execute("SHOW TABLES FROM guidb")
print(cursor.fetchall())
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def insertBooks(self, title, page, bookQuote):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# insert data
cursor.execute("INSERT INTO books (Book_Title, Book_Page) VALUES (%s,%s)", (title, page))
# last inserted auto increment value
keyID = cursor.lastrowid
# print(keyID)
cursor.execute("INSERT INTO quotations (Quotation, Books_Book_ID) VALUES (%s, %s)", \
(bookQuote, keyID))
# commit transaction
conn.commit ()
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def insertBooksExample(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# insert hard-coded data
cursor.execute("INSERT INTO books (Book_Title, Book_Page) VALUES ('Design Patterns', 17)")
# last inserted auto increment value
keyID = cursor.lastrowid
print(keyID)
cursor.execute("INSERT INTO quotations (Quotation, Books_Book_ID) VALUES (%s, %s)", \
('Programming to an Interface, not an Implementation', keyID))
# commit transaction
conn.commit ()
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def showBooks(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# print results
cursor.execute("SELECT * FROM Books")
allBooks = cursor.fetchall()
print(allBooks)
# close cursor and connection
self.close(cursor, conn)
return allBooks
#------------------------------------------------------
def showColumns(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# execute command
cursor.execute("SHOW COLUMNS FROM quotations")
print(cursor.fetchall())
print('\n Pretty Print:\n--------------')
from pprint import pprint
# execute command
cursor.execute("SHOW COLUMNS FROM quotations")
pprint(cursor.fetchall())
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def showData(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# execute command
cursor.execute("SELECT * FROM books")
print(cursor.fetchall())
cursor.execute("SELECT * FROM quotations")
print(cursor.fetchall())
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def showDataWithReturn(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# execute command
cursor.execute("SELECT * FROM books")
booksData = cursor.fetchall()
cursor.execute("SELECT * FROM quotations")
quoteData = cursor.fetchall()
# close cursor and connection
self.close(cursor, conn)
# print(booksData, quoteData)
for record in quoteData:
print(record)
return booksData, quoteData
#------------------------------------------------------
def updateGOF(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# execute command
cursor.execute("SELECT Book_ID FROM books WHERE Book_Title = 'Design Patterns'")
primKey = cursor.fetchall()[0][0]
print("Primary key=" + str(primKey))
cursor.execute("SELECT * FROM quotations WHERE Books_Book_ID = (%s)", (primKey,))
print(cursor.fetchall())
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def updateGOF_commit(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
# execute command
cursor.execute("SELECT Book_ID FROM books WHERE Book_Title = 'Design Patterns'")
primKey = cursor.fetchall()[0][0]
# print(primKey)
cursor.execute("SELECT * FROM quotations WHERE Books_Book_ID = (%s)", (primKey,))
# print(cursor.fetchall())
cursor.execute("UPDATE quotations SET Quotation = (%s) WHERE Books_Book_ID = (%s)", \
("Pythonic Duck Typing: If it walks like a duck and talks like a duck it probably is a duck...", primKey))
# commit transaction
conn.commit ()
cursor.execute("SELECT * FROM quotations WHERE Books_Book_ID = (%s)", (primKey,))
# print(cursor.fetchall())
# close cursor and connection
self.close(cursor, conn)
#------------------------------------------------------
def deleteRecord(self):
# connect to MySQL
conn, cursor = self.connect()
self.useGuiDB(cursor)
try:
# execute command
cursor.execute("SELECT Book_ID FROM books WHERE Book_Title = 'Design Patterns'")
primKey = cursor.fetchall()[0][0]
# print(primKey)
cursor.execute("DELETE FROM books WHERE Book_ID = (%s)", (primKey,))
# commit transaction
conn.commit ()
except:
pass
# close cursor and connection
self.close(cursor, conn)
#==========================================================
if __name__ == '__main__':
# Create class instance
mySQL = MySQL()
#------------------------
# mySQL.showTables()
# mySQL.dropTables()
# mySQL.createTables()
# mySQL.insertBooks()
# mySQL.showTables()
#------------------------
# mySQL.showDBs()
# mySQL.createGuiDB()
# mySQL.showDBs()
#------------------------
# mySQL.dropGuiDB()
# mySQL.showDBs()
#------------------------
# mySQL.createGuiDB()
# mySQL.dropTables()
# mySQL.createTables()
# mySQL.showTables()
#------------------------
# mySQL.showBooks()
#------------------------
# mySQL.showColumns()
#------------------------
# mySQL.insertBooksExample()
#------------------------
# mySQL.insertBooks('Design Patterns', 7, 'Programming to an Interface, not an Implementation')
# mySQL.insertBooks('xUnit Test Patterns', 31, 'Philosophy of Test Automation')
# mySQL.showData()
#------------------------
# mySQL.showData()
#------------------------
# mySQL.updateGOF()
#------------------------
# mySQL.updateGOF_commit()
#------------------------
# book, quote = mySQL.showData()
# book, quote = mySQL.showDataWithReturn()
# print(book, quote)
#------------------------
# mySQL.dropTables()
# mySQL.createTablesNoFK()
# mySQL.showTables()
# mySQL.insertBooks('Design Patterns', 7, 'Programming to an Interface, not an Implementation')
# mySQL.insertBooks('xUnit Test Patterns', 31, 'Philosophy of Test Automation')
# mySQL.showData()
#------------------------
# mySQL.deleteRecord()
#------------------------
# mySQL.deleteRecord()
mySQL.showData()
3)tkiner모듈 기반으로 만들어져 있는 GUI코드 입니다.
#GUI_MySQL.py
#======================
# imports
#======================
import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext
from tkinter import Menu
from tkinter import Spinbox
import ToolTip as tt
from threading import Thread
from time import sleep
from queue import Queue
from tkinter import filedialog as fd
from os import path, makedirs
from tkinter import messagebox as mBox
from GUI_MySQL_class import MySQL
# Module level GLOBALS
GLOBAL_CONST = 42
fDir = path.dirname(__file__)
netDir = fDir + '\\Backup'
if not path.exists(netDir):
makedirs(netDir, exist_ok = True)
WIDGET_LABEL = ' Widgets Frame '
#===================================================================
class OOP():
def __init__(self):
# Create instance
self.win = tk.Tk()
# Add a title
self.win.title("Python GUI")
# Disable resizing the window
self.win.resizable(0,0)
# Create a Queue
self.guiQueue = Queue()
self.createWidgets()
# populate Tab 2 Entries
self.defaultFileEntries()
# create MySQL instance
self.mySQL = MySQL()
def defaultFileEntries(self):
self.fileEntry.delete(0, tk.END)
self.fileEntry.insert(0, 'Z:\\') # bogus path
self.fileEntry.config(state='readonly')
self.netwEntry.delete(0, tk.END)
self.netwEntry.insert(0, 'Z:\\Backup') # bogus path
# Combobox callback
def _combo(self, val=0):
value = self.combo.get()
self.scr.insert(tk.INSERT, value + '\n')
# Spinbox callback
def _spin(self):
value = self.spin.get()
self.scr.insert(tk.INSERT, value + '\n')
# Checkbox callback
def checkCallback(self, *ignoredArgs):
# only enable one checkbutton
if self.chVarUn.get(): self.check3.configure(state='disabled')
else: self.check3.configure(state='normal')
if self.chVarEn.get(): self.check2.configure(state='disabled')
else: self.check2.configure(state='normal')
# Radiobutton callback function
def radCall(self):
radSel=self.radVar.get()
if radSel == 0: self.mySQL2.configure(text=WIDGET_LABEL + 'in Blue')
elif radSel == 1: self.mySQL2.configure(text=WIDGET_LABEL + 'in Gold')
elif radSel == 2: self.mySQL2.configure(text=WIDGET_LABEL + 'in Red')
# Exit GUI cleanly
def _quit(self):
self.win.quit()
self.win.destroy()
exit()
def methodInAThread(self, numOfLoops=10):
for idx in range(numOfLoops):
sleep(1)
self.scr.insert(tk.INSERT, str(idx) + '\n')
sleep(1)
print('methodInAThread():', self.runT.isAlive())
# Running methods in Threads
def createThread(self, num):
self.runT = Thread(target=self.methodInAThread, args=[num])
self.runT.setDaemon(True)
self.runT.start()
print(self.runT)
print('createThread():', self.runT.isAlive())
# textBoxes are the Consumers of Queue data
writeT = Thread(target=self.useQueues, daemon=True)
writeT.start()
# Create Queue instance
def useQueues(self):
# Now using a class member Queue
while True:
qItem = self.guiQueue.get()
print(qItem)
self.scr.insert(tk.INSERT, qItem + '\n')
# Button callback
def insertQuote(self):
title = self.bookTitle.get()
page = self.pageNumber.get()
quote = self.quote.get(1.0, tk.END)
print(title)
print(quote)
self.mySQL.insertBooks(title, page, quote)
# Button callback
def getQuote(self):
allBooks = self.mySQL.showBooks()
print(allBooks)
self.quote.insert(tk.INSERT, allBooks)
# Button callback
def modifyQuote(self):
raise NotImplementedError("This still needs to be implemented for the SQL command.")
#####################################################################################
def createWidgets(self):
# Tab Control introduced here --------------------------------------
tabControl = ttk.Notebook(self.win) # Create Tab Control
tab1 = ttk.Frame(tabControl) # Create a tab
tabControl.add(tab1, text='MySQL') # Add the tab
tab2 = ttk.Frame(tabControl) # Add a second tab
tabControl.add(tab2, text='Widgets') # Make second tab visible
tabControl.pack(expand=1, fill="both") # Pack to make visible
# ~ Tab Control introduced here -----------------------------------------
# We are creating a container frame to hold all other widgets
self.mySQL = ttk.LabelFrame(tab1, text=' Python Database ')
self.mySQL.grid(column=0, row=0, padx=8, pady=4)
# Creating a Label
ttk.Label(self.mySQL, text="Book Title:").grid(column=0, row=0, sticky='W')
# Adding a Textbox Entry widget
book = tk.StringVar()
self.bookTitle = ttk.Entry(self.mySQL, width=34, textvariable=book)
self.bookTitle.grid(column=0, row=1, sticky='W')
# Adding a Textbox Entry widget
book1 = tk.StringVar()
self.bookTitle1 = ttk.Entry(self.mySQL, width=34, textvariable=book1)
self.bookTitle1.grid(column=0, row=2, sticky='W')
# Adding a Textbox Entry widget
book2 = tk.StringVar()
self.bookTitle2 = ttk.Entry(self.mySQL, width=34, textvariable=book2)
self.bookTitle2.grid(column=0, row=3, sticky='W')
# Creating a Label
ttk.Label(self.mySQL, text="Page:").grid(column=1, row=0, sticky='W')
# Adding a Textbox Entry widget
page = tk.StringVar()
self.pageNumber = ttk.Entry(self.mySQL, width=6, textvariable=page)
self.pageNumber.grid(column=1, row=1, sticky='W')
# Adding a Textbox Entry widget
page = tk.StringVar()
self.pageNumber1 = ttk.Entry(self.mySQL, width=6, textvariable=page)
self.pageNumber1.grid(column=1, row=2, sticky='W')
# Adding a Textbox Entry widget
page = tk.StringVar()
self.pageNumber2 = ttk.Entry(self.mySQL, width=6, textvariable=page)
self.pageNumber2.grid(column=1, row=3, sticky='W')
# 입력 버튼 추가하기
self.action = ttk.Button(self.mySQL, text="Insert Quote", command=self.insertQuote)
self.action.grid(column=2, row=1)
# 검색 버튼 추가하기(콜백 메서드로 추가됨)
self.action1 = ttk.Button(self.mySQL, text="Get Quotes", command=self.getQuote)
self.action1.grid(column=2, row=2)
# 수정 버튼 추가하기
self.action2 = ttk.Button(self.mySQL, text="Mody Quote", command=self.modifyQuote)
self.action2.grid(column=2, row=3)
# Add some space around each widget
for child in self.mySQL.winfo_children():
child.grid_configure(padx=2, pady=4)
quoteFrame = ttk.LabelFrame(tab1, text=' Book Quotation ')
quoteFrame.grid(column=0, row=1, padx=8, pady=4)
# Using a scrolled Text control
quoteW = 40; quoteH = 6
self.quote = scrolledtext.ScrolledText(quoteFrame, width=quoteW, height=quoteH, wrap=tk.WORD)
self.quote.grid(column=0, row=8, sticky='WE', columnspan=3)
# Add some space around each widget
for child in quoteFrame.winfo_children():
child.grid_configure(padx=2, pady=4)
#======================================================================================================
# Tab Control 2
#======================================================================================================
# We are creating a container frame to hold all other widgets -- Tab2
self.mySQL2 = ttk.LabelFrame(tab2, text=WIDGET_LABEL)
self.mySQL2.grid(column=0, row=0, padx=8, pady=4)
# Creating three checkbuttons
self.chVarDis = tk.IntVar()
self.check1 = tk.Checkbutton(self.mySQL2, text="Disabled", variable=self.chVarDis, state='disabled')
self.check1.select()
self.check1.grid(column=0, row=0, sticky=tk.W)
self.chVarUn = tk.IntVar()
self.check2 = tk.Checkbutton(self.mySQL2, text="UnChecked", variable=self.chVarUn)
self.check2.deselect()
self.check2.grid(column=1, row=0, sticky=tk.W )
self.chVarEn = tk.IntVar()
self.check3 = tk.Checkbutton(self.mySQL2, text="Toggle", variable=self.chVarEn)
self.check3.deselect()
self.check3.grid(column=2, row=0, sticky=tk.W)
# trace the state of the two checkbuttons
self.chVarUn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback())
self.chVarEn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback())
# Radiobutton list
colors = ["Blue", "Gold", "Red"]
self.radVar = tk.IntVar()
# Selecting a non-existing index value for radVar
self.radVar.set(99)
# Creating all three Radiobutton widgets within one loop
for col in range(3):
curRad = 'rad' + str(col)
curRad = tk.Radiobutton(self.mySQL2, text=colors[col], variable=self.radVar, value=col, command=self.radCall)
curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3)
# And now adding tooltips
tt.create_ToolTip(curRad, 'This is a Radiobutton control.')
# Create a container to hold labels
labelsFrame = ttk.LabelFrame(self.mySQL2, text=' Labels within a Frame ')
labelsFrame.grid(column=0, row=7, pady=6)
# Place labels into the container element - vertically
ttk.Label(labelsFrame, text="Choose a number:").grid(column=0, row=0)
ttk.Label(labelsFrame, text="Label 2").grid(column=0, row=1)
# Add some space around each label
for child in labelsFrame.winfo_children():
child.grid_configure(padx=6, pady=1)
number = tk.StringVar()
self.combo = ttk.Combobox(self.mySQL2, width=12, textvariable=number)
self.combo['values'] = (1, 2, 4, 42, 100)
self.combo.grid(column=1, row=7, sticky=tk.W)
self.combo.current(0)
self.combo.bind('<<ComboboxSelected>>', self._combo)
# Adding a Spinbox widget using a set of values
self.spin = Spinbox(self.mySQL2, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self._spin)
self.spin.grid(column=2, row=7, sticky='W,', padx=6, pady=1)
# Using a scrolled Text control
scrolW = 40; scrolH = 1
self.scr = scrolledtext.ScrolledText(self.mySQL2, width=scrolW, height=scrolH, wrap=tk.WORD)
self.scr.grid(column=0, row=8, sticky='WE', columnspan=3)
# Create Manage Files Frame ------------------------------------------------
mngFilesFrame = ttk.LabelFrame(tab2, text=' Manage Files: ')
mngFilesFrame.grid(column=0, row=1, sticky='WE', padx=10, pady=5)
# Button Callback
def getFileName():
print('hello from getFileName')
fDir = path.dirname(__file__)
fName = fd.askopenfilename(parent=self.win, initialdir=fDir)
print(fName)
self.fileEntry.config(state='enabled')
self.fileEntry.delete(0, tk.END)
self.fileEntry.insert(0, fName)
if len(fName) > self.entryLen:
self.fileEntry.config(width=len(fName) + 3)
# Add Widgets to Manage Files Frame
lb = ttk.Button(mngFilesFrame, text="Browse to File...", command=getFileName)
lb.grid(column=0, row=0, sticky=tk.W)
#-----------------------------------------------------
file = tk.StringVar()
self.entryLen = scrolW - 4
self.fileEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=file)
self.fileEntry.grid(column=1, row=0, sticky=tk.W)
#-----------------------------------------------------
logDir = tk.StringVar()
self.netwEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=logDir)
self.netwEntry.grid(column=1, row=1, sticky=tk.W)
def copyFile():
import shutil
src = self.fileEntry.get()
file = src.split('/')[-1]
dst = self.netwEntry.get() + '\\'+ file
try:
shutil.copy(src, dst)
mBox.showinfo('Copy File to Network', 'Succes: File copied.')
except FileNotFoundError as err:
mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err))
except Exception as ex:
mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(ex))
cb = ttk.Button(mngFilesFrame, text="Copy File To : ", command=copyFile)
cb.grid(column=0, row=1, sticky=tk.E)
# Add some space around each label
for child in mngFilesFrame.winfo_children():
child.grid_configure(padx=6, pady=6)
# Creating a Menu Bar ==========================================================
menuBar = Menu(tab1)
self.win.config(menu=menuBar)
# Add menu items
fileMenu = Menu(menuBar, tearoff=0)
fileMenu.add_command(label="New")
fileMenu.add_separator()
fileMenu.add_command(label="Exit", command=self._quit)
menuBar.add_cascade(label="File", menu=fileMenu)
# Add another Menu to the Menu Bar and an item
helpMenu = Menu(menuBar, tearoff=0)
helpMenu.add_command(label="About")
menuBar.add_cascade(label="Help", menu=helpMenu)
# Change the main windows icon
self.win.iconbitmap('pyc.ico')
# Using tkinter Variable Classes
strData = tk.StringVar()
strData.set('Hello StringVar')
# It is not necessary to create a tk.StringVar()
strData = tk.StringVar()
strData = self.spin.get()
# Place cursor into name Entry
self.bookTitle.focus()
# Add a Tooltip to the Spinbox
tt.create_ToolTip(self.spin, 'This is a Spin control.')
# Add Tooltips to more widgets
tt.create_ToolTip(self.bookTitle, 'This is an Entry control.')
tt.create_ToolTip(self.action, 'This is a Button control.')
tt.create_ToolTip(self.scr, 'This is a ScrolledText control.')
#======================
# Start GUI
#======================
oop = OOP()
oop.win.mainloop()
세번째 파일을 바로 실행하면 아래와 같은 화면이 출력됩니다.
mySQL그룹에 설치된 워크벤치를 실행해서 암호를 입력하고 연결하시면 입력된 결과를 볼 수 있습니다.
요새 데이타사이언스가 뜨면서 어떤 종류든 SQL 하나 정도는 해야 명함을 내민다던데, 파이쏜과 이렇게 연결이 되는군요..
참, #kr-dev 태그 추천드립니다.
아^^ 태그 잊었네요. 고맙습니다.
곰돌이가 @dj-on-steem님의 소중한 댓글에 $0.018을 보팅해서 $0.005을 살려드리고 가요. 곰돌이가 지금까지 총 967번 $14.310을 보팅해서 $12.621을 구했습니다. @gomdory 곰도뤼~
Hello! Your post has been resteemed and upvoted by @ilovecoding because we love coding! Keep up good work! Consider upvoting this comment to support the @ilovecoding and increase your future rewards! ^_^ Steem On!
Reply !stop to disable the comment. Thanks!
Thanks^^