├── Ch03_Code ├── pyc.ico ├── GUI_independent_msg.py ├── GUI_independent_msg_info.py ├── GUI_independent_msg_one_window.py └── GUI_independent_msg_one_window_title.py ├── Ch04_Code ├── pyc.ico ├── GUI_PyVar_Get.py ├── GUI_StringVar.py ├── GUI_PyDoubleVar_to_Float_Get.py ├── GUI_PyVar_defaults.py └── ToolTip.py ├── Ch06_Code ├── pyc.ico ├── URL.py ├── TCP_Server.py ├── Queues.py └── ToolTip.py ├── Ch07_Code ├── pyc.ico ├── MySQL_connect_import_dict.py ├── MySQL_connect.py ├── MySQL_show_DBs.py ├── MySQL_connect_with_dict.py ├── GuiDBConfig.py ├── MySQL_create_DB.py └── ToolTip.py ├── Ch08_Code ├── pyc.ico ├── UnitTestsMinimum.py ├── UnitTests_One.py ├── UnitTestsFail.py ├── UnitTestsEnglish.py ├── ToolTip.py ├── UnitTests.py ├── Logger.py └── LanguageResources.py ├── Ch11_Code ├── pyc.ico ├── __init__.py ├── GUI__init.py ├── GUI__init_import_folder.py ├── GUI_Spaghetti.py ├── GUI__init_import_folder_directly.py ├── ToolTip.py ├── GUI_Not_OOP.py ├── GUI_NOT_Spaghetti.py ├── GUI_OOP.py ├── GUI_DesignPattern.py ├── GUI_FallDown.py └── GUI_FallDown_Tooltip.py ├── Ch09_Code ├── Hello_wxPython.py ├── wxPython_frame_GUI.py ├── Embed_tkinter.py ├── Embed_wxPython.py ├── wxPython_panel_GUI.py ├── Control_Frameworks_NOT_working.py ├── Control_Frameworks.py └── Communicate.py ├── Ch05_Code ├── Matplotlib_our_first_chart.py ├── Matplotlib_chart.py ├── Matplotlib_labels.py ├── Matplotlib_labels_two_charts_scaled.py ├── Matplotlib_labels_two_charts_not_scaled.py ├── Matplotlib_labels_two_charts_scaled_dynamic_spike.py ├── Matplotlib_labels_two_charts.py ├── Matplotlib_chart_with_legend_colors.py ├── Matplotlib_chart_with_legend.py ├── Matplotlib_chart_with_legend_missing_comma.py ├── Matplotlib_labels_two_charts_scaled_dynamic.py └── Matplotlib_labels_four.py ├── Ch01_Code ├── First_GUI.py ├── GUI_add_label.py ├── GUI_not_resizable.py ├── GUI_create_button_change_property.py ├── GUI_textbox_widget.py ├── GUI_set_focus.py ├── GUI_disable_button_widget.py ├── GUI_combobox_widget_readonly.py ├── GUI_combobox_widget_readonly_plus_display_number.py ├── GUI_combobox_widget.py ├── GUI_checkbutton_widget.py ├── GUI_radiobutton_widget.py ├── GUI_scrolledtext_widget.py └── GUI_adding_widgets_in_loop.py ├── Ch10_Code ├── Designer_GUI_modular.py ├── Designer_GUI_modular_exit.py ├── First_GUI_PyQt5.py ├── GUI_PyQt5_title.py ├── GUI_PyQt5_refactored_OOP.py ├── GUI_PyQt5_QMainWindow.py ├── GUI_PyQt5_statusbar.py ├── Designer_GUI_modular_exit_class.py ├── Designer_First_UI.ui ├── GUI_PyQt5_menubar.py ├── Designer_Second_UI.ui ├── Designer_First_UI.py ├── Designer_First_UI_Exit.py ├── Designer_Second_UI_layout.ui ├── Designer_Second_UI.py ├── Designer_Second_UI_layout_button.ui ├── Designer_Second_UI_layout.py └── Designer_Second_UI_layout_button.py ├── Ch02_Code ├── GUI_tabbed.py ├── GUI_tabbed_two.py ├── GUI_tabbed_two_mighty.py ├── GUI_tabbed_two_mighty_labels.py ├── GUI_arranging_labels_vertical.py ├── GUI_arranging_labels.py ├── GUI_add_padding.py ├── GUI_remove_sticky.py ├── GUI_add_padding_loop.py ├── GUI_LabelFrame_column_one.py ├── GUI_long_label.py ├── GUI_remove_columnspan.py ├── GUI_embed_frames_align.py ├── GUI_embed_frames.py ├── GUI_embed_frames_align_west.py ├── GUI_LabelFrame_no_name.py └── GUI_embed_frames_align_entry_west.py └── LICENSE /Ch03_Code/pyc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-GUI-Programming-Cookbook-Third-Edition/HEAD/Ch03_Code/pyc.ico -------------------------------------------------------------------------------- /Ch04_Code/pyc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-GUI-Programming-Cookbook-Third-Edition/HEAD/Ch04_Code/pyc.ico -------------------------------------------------------------------------------- /Ch06_Code/pyc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-GUI-Programming-Cookbook-Third-Edition/HEAD/Ch06_Code/pyc.ico -------------------------------------------------------------------------------- /Ch07_Code/pyc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-GUI-Programming-Cookbook-Third-Edition/HEAD/Ch07_Code/pyc.ico -------------------------------------------------------------------------------- /Ch08_Code/pyc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-GUI-Programming-Cookbook-Third-Edition/HEAD/Ch08_Code/pyc.ico -------------------------------------------------------------------------------- /Ch11_Code/pyc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-GUI-Programming-Cookbook-Third-Edition/HEAD/Ch11_Code/pyc.ico -------------------------------------------------------------------------------- /Ch03_Code/GUI_independent_msg.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 3, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | from tkinter import messagebox as msg 8 | msg.showinfo('Python GUI created using tkinter:\nThe year is 2019') 9 | -------------------------------------------------------------------------------- /Ch09_Code/Hello_wxPython.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 15, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | import wx 7 | app = wx.App() 8 | frame = wx.Frame(None, -1, "Hello World") 9 | frame.Show() 10 | app.MainLoop() 11 | -------------------------------------------------------------------------------- /Ch03_Code/GUI_independent_msg_info.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 3, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | from tkinter import messagebox as msg 8 | msg.showinfo('', 'Python GUI created using tkinter:\nThe year is 2019') 9 | 10 | 11 | -------------------------------------------------------------------------------- /Ch08_Code/UnitTestsMinimum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 9, 2019 3 | Ch08 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | import unittest 8 | 9 | class GuiUnitTests(unittest.TestCase): 10 | pass 11 | 12 | if __name__ == '__main__': 13 | unittest.main() 14 | -------------------------------------------------------------------------------- /Ch03_Code/GUI_independent_msg_one_window.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 3, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | from tkinter import messagebox as msg 8 | from tkinter import Tk 9 | root = Tk() 10 | root.withdraw() 11 | msg.showinfo('', 'Python GUI created using tkinter:\nThe year is 2019') 12 | -------------------------------------------------------------------------------- /Ch07_Code/MySQL_connect_import_dict.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 29, 2019 3 | Ch07 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | import mysql.connector 8 | import Ch07_Code.GuiDBConfig as guiConf 9 | 10 | # unpack dictionary credentials 11 | conn = mysql.connector.connect(**guiConf.dbConfig) 12 | print(conn) -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_our_first_chart.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jul 26, 2019 3 | Chapter 05 4 | @author: Burkhard 5 | ''' 6 | 7 | 8 | import matplotlib.pyplot as plt 9 | from pylab import show 10 | 11 | x_values = [1,2,3,4] 12 | y_values = [5,7,6,8] 13 | plt.plot(x_values, y_values) 14 | 15 | show() 16 | -------------------------------------------------------------------------------- /Ch03_Code/GUI_independent_msg_one_window_title.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 3, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | from tkinter import messagebox as msg 8 | from tkinter import Tk 9 | root = Tk() 10 | root.withdraw() 11 | msg.showinfo('This is a Title', 'Python GUI created using tkinter:\nThe year is 2019') 12 | -------------------------------------------------------------------------------- /Ch07_Code/MySQL_connect.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 29, 2019 3 | Ch07 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | import mysql.connector 8 | # conn = mysql.connect(user=, password=, host='127.0.0.1') 9 | conn = mysql.connector.connect(user='Admin', password='admin', host='127.0.0.1') 10 | print(conn) 11 | conn.close() 12 | -------------------------------------------------------------------------------- /Ch01_Code/First_GUI.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | 11 | # Create instance 12 | win = tk.Tk() 13 | 14 | # Add a title 15 | win.title("Python GUI") 16 | 17 | #====================== 18 | # Start GUI 19 | #====================== 20 | win.mainloop() -------------------------------------------------------------------------------- /Ch07_Code/MySQL_show_DBs.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 29, 2019 3 | Ch07 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | import mysql.connector 8 | import Ch07_Code.GuiDBConfig as guiConf 9 | 10 | GUIDB = 'GuiDB' 11 | 12 | # unpack dictionary credentials 13 | conn = mysql.connector.connect(**guiConf.dbConfig) 14 | 15 | cursor = conn.cursor() 16 | 17 | cursor.execute("SHOW DATABASES") 18 | print(cursor.fetchall()) 19 | 20 | conn.close() -------------------------------------------------------------------------------- /Ch07_Code/MySQL_connect_with_dict.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 29, 2019 3 | Ch07 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | import mysql.connector 8 | 9 | # create dictionary to hold connection info 10 | dbConfig = { 11 | 'user': 'Admin', # your user name 12 | 'password': 'admin', # your password 13 | 'host': '127.0.0.1', 14 | } 15 | 16 | conn = mysql.connector.connect(**dbConfig) 17 | print(conn) 18 | conn.close() 19 | -------------------------------------------------------------------------------- /Ch04_Code/GUI_PyVar_Get.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 16, 2019 3 | Ch04 4 | @author: Burkhard 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | 10 | import tkinter as tk 11 | 12 | # Create instance of tkinter 13 | win = tk.Tk() 14 | 15 | # Print out the default tkinter variable values 16 | intData = tk.IntVar() 17 | print(intData) 18 | print(intData.get()) 19 | 20 | # Set a breakpoint here to see the values in the debugger 21 | print() 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Ch10_Code/Designer_GUI_modular.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 18, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | 7 | from PyQt5 import QtWidgets 8 | from Ch10_Code.Designer_First_UI import Ui_MainWindow 9 | 10 | if __name__ == "__main__": 11 | import sys 12 | app = QtWidgets.QApplication(sys.argv) 13 | MainWindow = QtWidgets.QMainWindow() 14 | ui = Ui_MainWindow() 15 | ui.setupUi(MainWindow) 16 | MainWindow.show() 17 | sys.exit(app.exec_()) 18 | 19 | 20 | -------------------------------------------------------------------------------- /Ch10_Code/Designer_GUI_modular_exit.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 21, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | 7 | from PyQt5 import QtWidgets 8 | from Ch10_Code.Designer_First_UI_Exit import Ui_MainWindow 9 | 10 | if __name__ == "__main__": 11 | import sys 12 | app = QtWidgets.QApplication(sys.argv) 13 | MainWindow = QtWidgets.QMainWindow() 14 | ui = Ui_MainWindow() 15 | ui.setupUi(MainWindow) 16 | MainWindow.show() 17 | sys.exit(app.exec_()) 18 | 19 | 20 | -------------------------------------------------------------------------------- /Ch07_Code/GuiDBConfig.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 29, 2019 3 | Ch07 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | 8 | # create dictionary to hold connection info 9 | dbConfig = { 10 | 'user': 'Admin', 11 | 'password': 'admin', 12 | 'host': '127.0.0.1', 13 | } 14 | 15 | 16 | # # create dictionary to hold connection info 17 | # dbConfig = { 18 | # 'user': , # your user name 19 | # 'password': , # your password 20 | # 'host': '127.0.0.1', 21 | # } 22 | 23 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_add_label.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Adding a Label 19 | ttk.Label(win, text="A Label").grid(column=0, row=0) 20 | 21 | #====================== 22 | # Start GUI 23 | #====================== 24 | win.mainloop() -------------------------------------------------------------------------------- /Ch10_Code/First_GUI_PyQt5.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 18, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | 7 | import sys 8 | from PyQt5.QtWidgets import QApplication, QWidget 9 | 10 | app = QApplication(sys.argv) # sys.argv accepts arguments when run from the command line 11 | gui = QWidget() # creates top-level window 12 | gui.show() # have to call show() to make it visible 13 | sys.exit(app.exec_()) # run the application; PyQt5 exec_ ends with an underscore 14 | 15 | 16 | -------------------------------------------------------------------------------- /Ch08_Code/UnitTests_One.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 9, 2019 3 | Ch08 4 | @author: Burkhard 5 | ''' 6 | 7 | import unittest 8 | from Ch08_Code.LanguageResources import I18N 9 | 10 | class GuiUnitTests(unittest.TestCase): 11 | 12 | def test_TitleIsEnglish(self): 13 | i18n = I18N('en') 14 | self.assertEqual(i18n.title, 15 | "Python Graphical User Interface") 16 | 17 | #========================== 18 | if __name__ == '__main__': 19 | unittest.main() 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Ch04_Code/GUI_StringVar.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 16, 2019 3 | Ch04 4 | @author: Burkhard 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | 10 | import tkinter as tk 11 | 12 | # Create instance of tkinter 13 | win = tk.Tk() 14 | 15 | # Assign tkinter Variable to strData variable 16 | strData = tk.StringVar() 17 | 18 | # Set strData variable 19 | strData.set('Hello StringVar') 20 | 21 | # Get value of strData variable 22 | varData = strData.get() 23 | 24 | # Print out current value of strData 25 | print(varData) 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Ch04_Code/GUI_PyDoubleVar_to_Float_Get.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 16, 2019 3 | Ch04 4 | @author: Burkhard 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | 10 | import tkinter as tk 11 | 12 | # Create instance of tkinter 13 | win = tk.Tk() 14 | 15 | # Create DoubleVar 16 | doubleData = tk.DoubleVar() 17 | print(doubleData.get()) # default value 18 | doubleData.set(2.4) 19 | print(type(doubleData)) 20 | 21 | add_doubles = 1.222222222222222222222222 + doubleData.get() 22 | print(add_doubles) 23 | print(type(add_doubles)) 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_not_resizable.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | 11 | # Create instance 12 | win = tk.Tk() 13 | 14 | # Add a title 15 | win.title("Python GUI") 16 | 17 | # Disable resizing the GUI by passing in False/False 18 | win.resizable(False, False) 19 | 20 | # Enable resizing x-dimension, disable y-dimension 21 | # win.resizable(True, False) 22 | 23 | #====================== 24 | # Start GUI 25 | #====================== 26 | win.mainloop() -------------------------------------------------------------------------------- /Ch10_Code/GUI_PyQt5_title.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 18, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | 7 | import sys 8 | from PyQt5.QtWidgets import QApplication, QWidget 9 | 10 | app = QApplication(sys.argv) # sys.argv accepts arguments when run from the command line 11 | gui = QWidget() # creates top-level window 12 | 13 | gui.setWindowTitle('PyQt5 GUI') # give our Window a title 14 | 15 | gui.show() # have to call show() to make it visible 16 | sys.exit(app.exec_()) # run the application; PyQt5 exec_ ends with an underscore 17 | 18 | 19 | -------------------------------------------------------------------------------- /Ch07_Code/MySQL_create_DB.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 29, 2019 3 | Ch07 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | import mysql.connector 8 | import Ch07_Code.GuiDBConfig as guiConf 9 | 10 | GUIDB = 'GuiDB' 11 | 12 | # unpack dictionary credentials 13 | conn = mysql.connector.connect(**guiConf.dbConfig) 14 | 15 | cursor = conn.cursor() 16 | 17 | try: 18 | cursor.execute("CREATE DATABASE {} \ 19 | DEFAULT CHARACTER SET 'utf8'".format(GUIDB)) 20 | except mysql.connector.Error as err: 21 | print("Failed to create DB: {}".format(err)) 22 | 23 | conn.close() -------------------------------------------------------------------------------- /Ch06_Code/URL.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 28, 2019 3 | Ch06 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | from urllib.request import urlopen 8 | link = 'http://python.org/' 9 | 10 | def get_html(): 11 | try: 12 | http_rsp = urlopen(link) 13 | print(http_rsp) 14 | html = http_rsp.read() 15 | print(html) 16 | html_decoded = html.decode() 17 | print(html_decoded) 18 | except Exception as ex: 19 | print('*** Failed to get Html! ***\n\n' + str(ex)) 20 | else: 21 | return html_decoded 22 | 23 | #------------------------------- 24 | if __name__ == '__main__': 25 | get_html() -------------------------------------------------------------------------------- /Ch02_Code/GUI_tabbed.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | win = tk.Tk() # Create instance 13 | win.title("Python GUI") # Add a title 14 | tabControl = ttk.Notebook(win) # Create Tab Control 15 | tab1 = ttk.Frame(tabControl) # Create a tab 16 | tabControl.add(tab1, text='Tab 1') # Add the tab 17 | tabControl.pack(expand=1, fill="both") # Pack to make visible 18 | 19 | #====================== 20 | # Start GUI 21 | #====================== 22 | win.mainloop() 23 | -------------------------------------------------------------------------------- /Ch04_Code/GUI_PyVar_defaults.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 16, 2019 3 | Ch04 4 | @author: Burkhard 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | 10 | import tkinter as tk 11 | 12 | # Create instance of tkinter 13 | win = tk.Tk() 14 | 15 | # Assign tkinter Variable to strData variable 16 | strData = tk.StringVar() 17 | 18 | # Set strData variable 19 | strData.set('Hello StringVar') 20 | 21 | # Get value of strData variable 22 | varData = strData.get() 23 | 24 | # Print out current value of strData 25 | print(varData) 26 | 27 | # Print out the default tkinter variable values 28 | print(tk.IntVar()) 29 | print(tk.DoubleVar()) 30 | print(tk.BooleanVar()) 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Ch11_Code/__init__.py: -------------------------------------------------------------------------------- 1 | print('hi from GUI init\n') 2 | from sys import path 3 | from pprint import pprint 4 | #======================================================= 5 | # Required setup for the PYTONPATH in order to find 6 | # all package folders 7 | #======================================================= 8 | from site import addsitedir 9 | from os import getcwd, chdir, pardir 10 | for _ in range(10): 11 | curFull = getcwd() 12 | curDir = curFull.split('\\')[-1] 13 | if 'Ch11_Code' == curDir: 14 | addsitedir(curFull) 15 | addsitedir(curFull + '\\Folder1\\Folder2\\Folder3\\') 16 | break 17 | chdir(pardir) 18 | pprint(path) 19 | #======================================================= 20 | 21 | -------------------------------------------------------------------------------- /Ch06_Code/TCP_Server.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 28, 2019 3 | Ch06 4 | @author: Burkhard 5 | ''' 6 | 7 | from socketserver import BaseRequestHandler, TCPServer 8 | 9 | class RequestHandler(BaseRequestHandler): 10 | # override base class handle method 11 | def handle(self): 12 | print('Server connected to: ', self.client_address) 13 | while True: 14 | rsp = self.request.recv(512) 15 | if not rsp: break 16 | self.request.send(b'Server received: ' + rsp) 17 | 18 | def start_server(): 19 | server = TCPServer(('localhost', 24000), RequestHandler) 20 | server.serve_forever() 21 | 22 | 23 | # TODO: Implement stop server. Check if running before starting the server. 24 | # I leave this as an exercise for the reader. 25 | -------------------------------------------------------------------------------- /Ch02_Code/GUI_tabbed_two.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | tabControl = ttk.Notebook(win) # Create Tab Control 19 | 20 | tab1 = ttk.Frame(tabControl) # Create a tab 21 | tabControl.add(tab1, text='Tab 1') # Add the tab 22 | tab2 = ttk.Frame(tabControl) # Add a second tab 23 | tabControl.add(tab2, text='Tab 2') # Add second tab 24 | 25 | tabControl.pack(expand=1, fill="both") # Pack to make visible 26 | 27 | #====================== 28 | # Start GUI 29 | #====================== 30 | win.mainloop() 31 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_create_button_change_property.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Adding a Label that will get modified 19 | a_label = ttk.Label(win, text="A Label") 20 | a_label.grid(column=0, row=0) 21 | 22 | # Button Click Event Function 23 | def click_me(): 24 | action.configure(text="** I have been Clicked! **") 25 | a_label.configure(foreground='red') 26 | a_label.configure(text='A Red Label') 27 | 28 | # Adding a Button 29 | action = ttk.Button(win, text="Click Me!", command=click_me) 30 | action.grid(column=1, row=0) 31 | 32 | #====================== 33 | # Start GUI 34 | #====================== 35 | win.mainloop() -------------------------------------------------------------------------------- /Ch10_Code/GUI_PyQt5_refactored_OOP.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 18, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | 7 | 8 | import sys 9 | from PyQt5.QtWidgets import QApplication, QWidget 10 | 11 | 12 | class GUI(QWidget): # inherit from QWidget 13 | def __init__(self): 14 | super().__init__() # initialize super class, which creates the Window 15 | self.initUI() # refer to Window as 'self' 16 | 17 | def initUI(self): 18 | self.setWindowTitle('PyQt5 GUI') # call method 19 | 20 | 21 | if __name__ == '__main__': 22 | app = QApplication(sys.argv) # create Application 23 | gui = GUI() # create instance of class 24 | gui.show() # show the constructed PyQt window 25 | sys.exit(app.exec_()) # execute the application 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Ch06_Code/Queues.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 28, 2019 3 | Ch06 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | def write_to_scrol(inst): 8 | print('hi from Queue', inst) 9 | for idx in range(10): 10 | inst.gui_queue.put('Message from a queue: ' + str(idx)) 11 | inst.create_thread(6) 12 | 13 | 14 | # using TCP/IP 15 | from socket import socket, AF_INET, SOCK_STREAM 16 | 17 | def write_to_scrol_TCP(inst): 18 | print('hi from Queue', inst) 19 | sock = socket(AF_INET, SOCK_STREAM) 20 | sock.connect(('localhost', 24000)) 21 | for idx in range(10): 22 | sock.send(b'Message from a queue: ' + bytes(str(idx).encode()) ) 23 | recv = sock.recv(8192).decode() 24 | inst.gui_queue.put(recv) 25 | inst.create_thread(6) 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Ch08_Code/UnitTestsFail.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 9, 2019 3 | Ch08 4 | @author: Burkhard 5 | ''' 6 | 7 | import unittest 8 | from Ch08_Code.LanguageResources import I18N 9 | from Ch08_Code.GUI_Refactored import OOP as GUI 10 | 11 | class GuiUnitTests(unittest.TestCase): 12 | 13 | def test_TitleIsEnglish(self): 14 | i18n = I18N('en') 15 | self.assertEqual(i18n.title, 16 | "Python Graphical User Interface") 17 | 18 | def test_TitleIsGerman(self): 19 | i18n = I18N('en') # <= Bug in Unit Test 20 | # i18n = I18N('de') 21 | self.assertEqual(i18n.title, 22 | 'Python Grafische Benutzeroberfl' 23 | + "\u00E4" + 'che') 24 | 25 | 26 | #========================================================== 27 | if __name__ == '__main__': 28 | unittest.main() 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_chart.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This code was downloaded from the official matplotlib.org website. 3 | It is one of the examples freely available on this website. 4 | It's name at the time of printing was: surface3d_demo.py''' 5 | 6 | from mpl_toolkits.mplot3d import Axes3D #@UnresolvedImport 7 | from matplotlib import cm 8 | from matplotlib.ticker import LinearLocator, FormatStrFormatter 9 | import matplotlib.pyplot as plt 10 | import numpy as np 11 | 12 | fig = plt.figure() 13 | ax = fig.gca(projection='3d') 14 | X = np.arange(-5, 5, 0.25) 15 | Y = np.arange(-5, 5, 0.25) 16 | X, Y = np.meshgrid(X, Y) 17 | R = np.sqrt(X**2 + Y**2) 18 | Z = np.sin(R) 19 | surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False) 20 | ax.set_zlim(-1.01, 1.01) 21 | 22 | ax.zaxis.set_major_locator(LinearLocator(10)) 23 | ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) 24 | 25 | fig.colorbar(surf, shrink=0.5, aspect=5) 26 | 27 | plt.show() 28 | 29 | -------------------------------------------------------------------------------- /Ch10_Code/GUI_PyQt5_QMainWindow.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 18, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | 7 | import sys 8 | from PyQt5.QtWidgets import QApplication, QMainWindow 9 | 10 | 11 | class GUI(QMainWindow): # inherit from QMainWindow 12 | def __init__(self): 13 | super().__init__() # initialize super class, which creates the Window 14 | self.initUI() # refer to Window as 'self' 15 | 16 | def initUI(self): 17 | self.setWindowTitle('PyQt5 GUI') # call method 18 | self.resize(400, 300) # resize window (width, height) 19 | 20 | 21 | if __name__ == '__main__': 22 | app = QApplication(sys.argv) # create Application 23 | gui = GUI() # create instance of class 24 | gui.show() # show the constructed PyQt window 25 | sys.exit(app.exec_()) # execute the application 26 | 27 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_textbox_widget.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Modify adding a Label 19 | a_label = ttk.Label(win, text="A Label") 20 | a_label.grid(column=0, row=0) 21 | 22 | # Modified Button Click Function 23 | def click_me(): 24 | action.configure(text='Hello ' + name.get()) 25 | 26 | # Changing our Label 27 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 28 | 29 | # Adding a Text box Entry widget 30 | name = tk.StringVar() 31 | name_entered = ttk.Entry(win, width=12, textvariable=name) 32 | name_entered.grid(column=0, row=1) 33 | 34 | # Adding a Button 35 | action = ttk.Button(win, text="Click Me!", command=click_me) 36 | action.grid(column=1, row=1) 37 | 38 | #====================== 39 | # Start GUI 40 | #====================== 41 | win.mainloop() -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_set_focus.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Modify adding a Label 19 | a_label = ttk.Label(win, text="A Label") 20 | a_label.grid(column=0, row=0) 21 | 22 | # Modified Button Click Function 23 | def click_me(): 24 | action.configure(text='Hello ' + name.get()) 25 | 26 | # Changing our Label 27 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 28 | 29 | # Adding a Textbox Entry widget 30 | name = tk.StringVar() 31 | name_entered = ttk.Entry(win, width=12, textvariable=name) 32 | name_entered.grid(column=0, row=1) 33 | 34 | # Adding a Button 35 | action = ttk.Button(win, text="Click Me!", command=click_me) 36 | action.grid(column=1, row=1) 37 | 38 | name_entered.focus() # Place cursor into name Entry 39 | #====================== 40 | # Start GUI 41 | #====================== 42 | win.mainloop() -------------------------------------------------------------------------------- /Ch02_Code/GUI_tabbed_two_mighty.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | tabControl = ttk.Notebook(win) # Create Tab Control 19 | 20 | tab1 = ttk.Frame(tabControl) # Create a tab 21 | tabControl.add(tab1, text='Tab 1') # Add the tab 22 | tab2 = ttk.Frame(tabControl) # Add a second tab 23 | tabControl.add(tab2, text='Tab 2') # Make second tab visible 24 | 25 | tabControl.pack(expand=1, fill="both") # Pack to make visible 26 | 27 | # LabelFrame using tab1 as the parent 28 | mighty = ttk.LabelFrame(tab1, text=' Mighty Python ') 29 | mighty.grid(column=0, row=0, padx=8, pady=4) 30 | 31 | # Label using mighty as the parent 32 | a_label = ttk.Label(mighty, text="Enter a name:") 33 | a_label.grid(column=0, row=0, sticky='W') 34 | 35 | 36 | #====================== 37 | # Start GUI 38 | #====================== 39 | win.mainloop() 40 | -------------------------------------------------------------------------------- /Ch11_Code/GUI__init.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | 8 | #====================== 9 | # imports 10 | #====================== 11 | import tkinter as tk 12 | from tkinter import ttk 13 | 14 | #====================== 15 | # Create instance 16 | #====================== 17 | win = tk.Tk() 18 | 19 | #====================== 20 | # Add a title 21 | #====================== 22 | win.title("Python GUI") 23 | 24 | #=============================================================================== 25 | # Adding a LabelFrame and a Button 26 | #=============================================================================== 27 | lFrame = ttk.LabelFrame(win, text="Python GUI Programming Cookbook") 28 | lFrame.grid(column=0, row=0, sticky='WE', padx=10, pady=10) 29 | 30 | def clickMe(): 31 | from tkinter import messagebox 32 | messagebox.showinfo('Message Box', 'Hi from same Level.') 33 | 34 | button = ttk.Button(lFrame, text="Click Me ", command=clickMe) 35 | button.grid(column=1, row=0, sticky=tk.S) 36 | 37 | #====================== 38 | # Start GUI 39 | #====================== 40 | win.mainloop() -------------------------------------------------------------------------------- /Ch10_Code/GUI_PyQt5_statusbar.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 18, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | 7 | # class inheriting from QMainWindow 8 | import sys 9 | from PyQt5.QtWidgets import QApplication, QMainWindow 10 | 11 | 12 | class GUI(QMainWindow): # inherit from QMainWindow 13 | def __init__(self): 14 | super().__init__() # initialize super class, which creates the window 15 | self.initUI() # refer to window as 'self' 16 | 17 | def initUI(self): 18 | self.setWindowTitle('PyQt5 GUI') # call method 19 | self.resize(400, 300) # resize window (width, height) 20 | self.add_widgets() 21 | 22 | def add_widgets(self): 23 | self.statusBar().showMessage('Text in statusbar') 24 | 25 | 26 | if __name__ == '__main__': 27 | app = QApplication(sys.argv) # create Application 28 | gui = GUI() # create instance of class 29 | gui.show() # show the constructed PyQt window 30 | sys.exit(app.exec_()) # execute the application 31 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_disable_button_widget.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Modify adding a Label 19 | a_label = ttk.Label(win, text="A Label") 20 | a_label.grid(column=0, row=0) 21 | 22 | # Modified Button Click Function 23 | def click_me(): 24 | action.configure(text='Hello ' + name.get()) 25 | 26 | # Changing our Label 27 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 28 | 29 | # Adding a Textbox Entry widget 30 | name = tk.StringVar() 31 | name_entered = ttk.Entry(win, width=12, textvariable=name) 32 | name_entered.grid(column=0, row=1) 33 | 34 | # Adding a Button 35 | action = ttk.Button(win, text="Click Me!", command=click_me) 36 | action.grid(column=1, row=1) 37 | action.configure(state='disabled') # Disable the Button Widget 38 | 39 | name_entered.focus() # Place cursor into name Entry 40 | #====================== 41 | # Start GUI 42 | #====================== 43 | win.mainloop() -------------------------------------------------------------------------------- /Ch11_Code/GUI__init_import_folder.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | #====================== 8 | # imports 9 | #====================== 10 | import tkinter as tk 11 | from tkinter import ttk 12 | from Ch11_Code.Folder1.Folder2.Folder3.MessageBox import clickMe 13 | 14 | #====================== 15 | # Create instance 16 | #====================== 17 | win = tk.Tk() 18 | 19 | #====================== 20 | # Add a title 21 | #====================== 22 | win.title("Python GUI") 23 | 24 | #=============================================================================== 25 | # Adding a LabelFrame and a Button 26 | #=============================================================================== 27 | lFrame = ttk.LabelFrame(win, text="Python GUI Programming Cookbook") 28 | lFrame.grid(column=0, row=0, sticky='WE', padx=10, pady=10) 29 | 30 | # def clickMe(): 31 | # from tkinter import messagebox 32 | # messagebox.showinfo('Message Box', 'Hi from same Level.') 33 | # 34 | button = ttk.Button(lFrame, text="Click Me ", command=clickMe) 35 | button.grid(column=1, row=0, sticky=tk.S) 36 | 37 | #====================== 38 | # Start GUI 39 | #====================== 40 | win.mainloop() -------------------------------------------------------------------------------- /Ch10_Code/Designer_GUI_modular_exit_class.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 21, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | import sys 7 | from PyQt5 import QtWidgets 8 | from Ch10_Code.Designer_First_UI_Exit import Ui_MainWindow 9 | 10 | class ExitDesignerGUI(): 11 | def __init__(self): 12 | app = QtWidgets.QApplication(sys.argv) 13 | self.MainWindow = QtWidgets.QMainWindow() 14 | self.ui = Ui_MainWindow() 15 | self.ui.setupUi(self.MainWindow) 16 | self.update_widgets() 17 | self.widget_actions() 18 | self.MainWindow.show() 19 | sys.exit(app.exec_()) 20 | 21 | def widget_actions(self): 22 | self.ui.actionExit.setStatusTip('Click to exit the application') # use ui reference to update status bar 23 | self.ui.actionExit.triggered.connect(self.close_GUI) # connect widget to method when triggered (clicked) 24 | 25 | def close_GUI(self): 26 | self.MainWindow.close() # call MainWindow close method, which closes the GUI 27 | 28 | def update_widgets(self): 29 | self.MainWindow.setWindowTitle('PyQt5 GUI') # use: self.MainWindow 30 | 31 | if __name__ == "__main__": 32 | ExitDesignerGUI() -------------------------------------------------------------------------------- /Ch11_Code/GUI_Spaghetti.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | # Spaghetti Code ############################# 8 | def PRINTME(me):print(me) 9 | import tkinter 10 | x=y=z=1 11 | PRINTME(z) 12 | from tkinter import * 13 | scrolW=30;scrolH=6 14 | win=tkinter.Tk() 15 | if x:chVarUn=tkinter.IntVar() 16 | from tkinter import ttk 17 | WE='WE' 18 | import tkinter.scrolledtext 19 | outputFrame=tkinter.ttk.LabelFrame(win,text=' Type into the scrolled text control: ') 20 | scr=tkinter.scrolledtext.ScrolledText(outputFrame,width=scrolW,height=scrolH,wrap=tkinter.WORD) 21 | e='E' 22 | scr.grid(column=1,row=1,sticky=WE) 23 | outputFrame.grid(column=0,row=2,sticky=e,padx=8) 24 | lFrame=None 25 | if y:chck2=tkinter.Checkbutton(lFrame,text="Enabled",variable=chVarUn) 26 | wE='WE' 27 | if y==x:PRINTME(x) 28 | lFrame=tkinter.ttk.LabelFrame(win,text="Spaghetti") 29 | chck2.grid(column=1,row=4,sticky=tkinter.W,columnspan=3) 30 | PRINTME(z) 31 | lFrame.grid(column=0,row=0,sticky=wE,padx=10,pady=10) 32 | chck2.select() 33 | try: win.mainloop() 34 | except:PRINTME(x) 35 | chck2.deselect() 36 | if y==x:PRINTME(x) 37 | # End Pasta ############################# 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Ch11_Code/GUI__init_import_folder_directly.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | #====================== 8 | # imports 9 | #====================== 10 | import tkinter as tk 11 | from tkinter import ttk 12 | 13 | import __init__ #@UnresolvedImport #@UnusedImport 14 | from MessageBox import clickMe #@UnresolvedImport 15 | 16 | #====================== 17 | # Create instance 18 | #====================== 19 | win = tk.Tk() 20 | 21 | #====================== 22 | # Add a title 23 | #====================== 24 | win.title("Python GUI") 25 | 26 | #=============================================================================== 27 | # Adding a LabelFrame and a Button 28 | #=============================================================================== 29 | lFrame = ttk.LabelFrame(win, text="Python GUI Programming Cookbook") 30 | lFrame.grid(column=0, row=0, sticky='WE', padx=10, pady=10) 31 | 32 | # def clickMe(): 33 | # from tkinter import messagebox 34 | # messagebox.showinfo('Message Box', 'Hi from same Level.') 35 | # 36 | button = ttk.Button(lFrame, text="Click Me ", command=clickMe) 37 | button.grid(column=1, row=0, sticky=tk.S) 38 | 39 | #====================== 40 | # Start GUI 41 | #====================== 42 | win.mainloop() -------------------------------------------------------------------------------- /Ch10_Code/Designer_First_UI.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 0 22 | 400 23 | 21 24 | 25 | 26 | 27 | 28 | File 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | New 39 | 40 | 41 | 42 | 43 | Exit 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Ch02_Code/GUI_tabbed_two_mighty_labels.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | tabControl = ttk.Notebook(win) # Create Tab Control 19 | 20 | tab1 = ttk.Frame(tabControl) # Create a tab 21 | tabControl.add(tab1, text='Tab 1') # Add the tab 22 | tab2 = ttk.Frame(tabControl) # Add a second tab 23 | tabControl.add(tab2, text='Tab 2') # Make second tab visible 24 | 25 | tabControl.pack(expand=1, fill="both") # Pack to make visible 26 | 27 | # LabelFrame using tab1 as the parent 28 | mighty = ttk.LabelFrame(tab1, text=' Mighty Python ') 29 | mighty.grid(column=0, row=0, padx=8, pady=4) 30 | 31 | # Label using mighty as the parent 32 | a_label = ttk.Label(mighty, text="Enter a name:") 33 | a_label.grid(column=0, row=0, sticky='W') 34 | 35 | # Add another label 36 | ttk.Label(mighty, text="Choose a number:").grid(column=1, row=0) 37 | 38 | # Add some space around each label 39 | for child in mighty.winfo_children(): 40 | child.grid_configure(padx=8) 41 | 42 | #====================== 43 | # Start GUI 44 | #====================== 45 | win.mainloop() 46 | -------------------------------------------------------------------------------- /Ch08_Code/UnitTestsEnglish.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 9, 2019 3 | Ch08 4 | @author: Burkhard 5 | ''' 6 | 7 | import unittest 8 | from Ch08_Code.LanguageResources import I18N 9 | from Ch08_Code.GUI_Refactored import OOP as GUI 10 | 11 | class GuiUnitTests(unittest.TestCase): 12 | 13 | def test_TitleIsEnglish(self): 14 | i18n = I18N('en') 15 | self.assertEqual(i18n.title, 16 | "Python Graphical User Interface") 17 | 18 | def test_TitleIsGerman(self): 19 | # i18n = I18N('en') # <= Bug in Unit Test 20 | i18n = I18N('de') 21 | self.assertEqual(i18n.title, 22 | 'Python Grafische Benutzeroberfl' 23 | + "\u00E4" + 'che') 24 | 25 | class WidgetsTestsEnglish(unittest.TestCase): 26 | 27 | def setUp(self): 28 | self.gui = GUI('en') 29 | 30 | def tearDown(self): 31 | self.gui = None 32 | 33 | def test_WidgetLabels(self): 34 | self.assertEqual(self.gui.i18n.file, "File") 35 | self.assertEqual(self.gui.i18n.mgrFiles, ' Manage Files ') 36 | self.assertEqual(self.gui.i18n.browseTo, 37 | "Browse to File...") 38 | 39 | #========================== 40 | if __name__ == '__main__': 41 | unittest.main() 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Ch09_Code/wxPython_frame_GUI.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 15, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | # Import wxPython GUI toolkit 7 | import wx 8 | 9 | # Subclass wxPython frame 10 | class GUI(wx.Frame): 11 | def __init__(self, parent, title, size=(200,100)): 12 | # Initialize super class 13 | wx.Frame.__init__(self, parent, title=title, size=size) 14 | 15 | # Change the frame color 16 | self.SetBackgroundColour('white') 17 | 18 | # Create Status Bar 19 | self.CreateStatusBar() 20 | 21 | # Create the Menu 22 | menu= wx.Menu() 23 | 24 | # Add Menu Items to the Menu 25 | menu.Append(wx.ID_ABOUT, "About", "wxPython GUI") 26 | menu.AppendSeparator() 27 | menu.Append(wx.ID_EXIT,"Exit"," Exit the GUI") 28 | 29 | # Create the MenuBar 30 | menuBar = wx.MenuBar() 31 | # Give the Menu a Title 32 | menuBar.Append(menu,"File") 33 | 34 | # Connect the Menu to the frame 35 | self.SetMenuBar(menuBar) 36 | 37 | # Display the frame 38 | self.Show() 39 | 40 | # Create instance of wxPython application 41 | app = wx.App() 42 | 43 | # Call sub-classed wxPython GUI 44 | GUI(None, "Python GUI using wxPython", (300,150)) 45 | 46 | # Run the main GUI event loop 47 | app.MainLoop() 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_combobox_widget_readonly.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Modify adding a Label 19 | a_label = ttk.Label(win, text="A Label") 20 | a_label.grid(column=0, row=0) 21 | 22 | # Modified Button Click Function 23 | def click_me(): 24 | action.configure(text='Hello ' + name.get()) 25 | # print(number) 26 | # print(number.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 41 | number = tk.StringVar() 42 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 43 | number_chosen['values'] = (1, 2, 4, 42, 100) 44 | number_chosen.grid(column=1, row=1) 45 | number_chosen.current(0) 46 | 47 | name_entered.focus() # Place cursor into name Entry 48 | #====================== 49 | # Start GUI 50 | #====================== 51 | win.mainloop() -------------------------------------------------------------------------------- /Ch01_Code/GUI_combobox_widget_readonly_plus_display_number.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Modify adding a Label 19 | a_label = ttk.Label(win, text="A Label") 20 | a_label.grid(column=0, row=0) 21 | 22 | # Modified Button Click Function 23 | def click_me(): 24 | action.configure(text='Hello ' + name.get() + ' ' + 25 | number_chosen.get()) 26 | 27 | # Changing our Label 28 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 29 | 30 | # Adding a Textbox Entry widget 31 | name = tk.StringVar() 32 | name_entered = ttk.Entry(win, width=12, textvariable=name) 33 | name_entered.grid(column=0, row=1) 34 | 35 | # Adding a Button 36 | action = ttk.Button(win, text="Click Me!", command=click_me) 37 | action.grid(column=2, row=1) # <= change column to 2 38 | 39 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 40 | number = tk.StringVar() 41 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 42 | number_chosen['values'] = (1, 2, 4, 42, 100) 43 | number_chosen.grid(column=1, row=1) 44 | number_chosen.current(0) 45 | 46 | name_entered.focus() # Place cursor into name Entry 47 | #====================== 48 | # Start GUI 49 | #====================== 50 | win.mainloop() -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_labels.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard A. Meier 5 | ''' 6 | 7 | from matplotlib.figure import Figure 8 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 9 | import tkinter as tk 10 | #-------------------------------------------------------------- 11 | fig = Figure(figsize=(12, 8), facecolor='white') 12 | #-------------------------------------------------------------- 13 | # axis = fig.add_subplot(111) # 1 row, 1 column, only graph 14 | axis = fig.add_subplot(211) # 2 rows, 1 column, Top graph 15 | #-------------------------------------------------------------- 16 | xValues = [1,2,3,4] 17 | yValues = [5,7,6,8] 18 | axis.plot(xValues, yValues) 19 | 20 | axis.set_xlabel('Horizontal Label') 21 | axis.set_ylabel('Vertical Label') 22 | 23 | # axis.grid() # default line style 24 | axis.grid(linestyle='-') # solid grid lines 25 | #-------------------------------------------------------------- 26 | def _destroyWindow(): 27 | root.quit() 28 | root.destroy() 29 | #-------------------------------------------------------------- 30 | root = tk.Tk() 31 | # root.withdraw() 32 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 33 | #-------------------------------------------------------------- 34 | canvas = FigureCanvasTkAgg(fig, master=root) 35 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 36 | #-------------------------------------------------------------- 37 | # root.update() 38 | # root.deiconify() 39 | root.mainloop() 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_combobox_widget.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Modify adding a Label 19 | a_label = ttk.Label(win, text="A Label") 20 | a_label.grid(column=0, row=0) 21 | 22 | # Modified Button Click Function 23 | def click_me(): 24 | action.configure(text='Hello ' + name.get()) 25 | # print(number) 26 | # print(number.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) # column 0 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 41 | number = tk.StringVar() 42 | number_chosen = ttk.Combobox(win, width=12, textvariable=number) 43 | number_chosen['values'] = (1, 2, 4, 42, 100) 44 | number_chosen.grid(column=1, row=1) # <= Combobox in column 1 45 | number_chosen.current(0) 46 | 47 | name_entered.focus() # Place cursor into name Entry 48 | #====================== 49 | # Start GUI 50 | #====================== 51 | win.mainloop() -------------------------------------------------------------------------------- /Ch09_Code/Embed_tkinter.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 15, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | #================================================================== 7 | def tkinterApp(): 8 | import tkinter as tk 9 | from tkinter import ttk 10 | win = tk.Tk() 11 | win.title("Python GUI") 12 | aLabel = ttk.Label(win, text="A Label") 13 | aLabel.grid(column=0, row=0) 14 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 15 | name = tk.StringVar() 16 | nameEntered = ttk.Entry(win, width=12, textvariable=name) 17 | nameEntered.grid(column=0, row=1) 18 | nameEntered.focus() 19 | 20 | def buttonCallback(): 21 | action.configure(text='Hello ' + name.get()) 22 | action = ttk.Button(win, text="Print", command=buttonCallback) 23 | action.grid(column=2, row=1) 24 | win.mainloop() 25 | 26 | #================================================================== 27 | import wx 28 | app = wx.App() 29 | frame = wx.Frame(None, -1, "wxPython GUI", size=(270,180)) 30 | frame.SetBackgroundColour('white') 31 | frame.CreateStatusBar() 32 | menu= wx.Menu() 33 | menu.Append(wx.ID_ABOUT, "About", "wxPython GUI") 34 | menuBar = wx.MenuBar() 35 | menuBar.Append(menu,"File") 36 | frame.SetMenuBar(menuBar) 37 | textBox = wx.TextCtrl(frame, size=(250, 50), style=wx.TE_MULTILINE) 38 | 39 | def writeToSharedQueue(event): 40 | tkinterApp() 41 | 42 | button = wx.Button(frame, label="Call tkinter GUI", pos=(0,60)) 43 | frame.Bind(wx.EVT_BUTTON, writeToSharedQueue, button) 44 | frame.Show() 45 | 46 | #====================== 47 | # Start wxPython GUI 48 | #====================== 49 | app.MainLoop() -------------------------------------------------------------------------------- /Ch10_Code/GUI_PyQt5_menubar.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Aug 18, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | 7 | # class inheriting from QMainWindow 8 | import sys 9 | from PyQt5.QtWidgets import QApplication, QMainWindow, QAction 10 | 11 | 12 | class GUI(QMainWindow): # inherit from QMainWindow 13 | def __init__(self): 14 | super().__init__() # initialize super class, which creates the window 15 | self.initUI() # refer to window as 'self' 16 | 17 | def initUI(self): 18 | self.setWindowTitle('PyQt5 GUI') # call method 19 | self.resize(400, 300) # resize window (width, height) 20 | self.add_widgets() 21 | 22 | def add_widgets(self): 23 | self.statusBar().showMessage('Text in statusbar') 24 | 25 | menubar = self.menuBar() # create menu bar 26 | file_menu = menubar.addMenu('File') # add menu to menu bar 27 | 28 | new_action = QAction('New', self) # create an Action 29 | file_menu.addAction(new_action) # add Action to menu 30 | 31 | new_action.setStatusTip('New File') # statusBar updated 32 | 33 | if __name__ == '__main__': 34 | app = QApplication(sys.argv) # create Application 35 | gui = GUI() # create instance of class 36 | gui.show() # show the constructed PyQt5 window 37 | sys.exit(app.exec_()) # execute the application 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_labels_two_charts_scaled.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard 5 | ''' 6 | from matplotlib.figure import Figure 7 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 8 | import tkinter as tk 9 | #-------------------------------------------------------------- 10 | fig = Figure(figsize=(12, 5), facecolor='white') 11 | #-------------------------------------------------------------- 12 | axis = fig.add_subplot(111) # 1 row, 1 column 13 | 14 | xValues = [1,2,3,4] 15 | 16 | yValues0 = [6,7.5,8,7.5] 17 | yValues1 = [5.5,6.5,50,6] # one very high value (50) 18 | yValues2 = [6.5,7,8,7] 19 | 20 | axis.set_ylim(5, 8) # limit the vertical display 21 | 22 | t0, = axis.plot(xValues, yValues0) 23 | t1, = axis.plot(xValues, yValues1) 24 | t2, = axis.plot(xValues, yValues2) 25 | 26 | axis.set_ylabel('Vertical Label') 27 | axis.set_xlabel('Horizontal Label') 28 | 29 | axis.grid() 30 | 31 | fig.legend((t0, t1, t2), ('First line', 'Second line', 'Third line'), 'upper right') 32 | 33 | #-------------------------------------------------------------- 34 | def _destroyWindow(): 35 | root.quit() 36 | root.destroy() 37 | #-------------------------------------------------------------- 38 | root = tk.Tk() 39 | root.withdraw() 40 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 41 | #-------------------------------------------------------------- 42 | canvas = FigureCanvasTkAgg(fig, master=root) 43 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 44 | #-------------------------------------------------------------- 45 | root.update() 46 | root.deiconify() 47 | root.mainloop() 48 | -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_labels_two_charts_not_scaled.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard 5 | ''' 6 | from matplotlib.figure import Figure 7 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 8 | import tkinter as tk 9 | #-------------------------------------------------------------- 10 | fig = Figure(figsize=(12, 5), facecolor='white') 11 | #-------------------------------------------------------------- 12 | axis = fig.add_subplot(111) # 1 row, 1 column 13 | 14 | xValues = [1,2,3,4] 15 | 16 | yValues0 = [6,7.5,8,7.5] 17 | yValues1 = [5.5,6.5,50,6] # one very high value (50) 18 | yValues2 = [6.5,7,8,7] 19 | 20 | # axis.set_ylim(5, 8) # limit the vertical display 21 | 22 | t0, = axis.plot(xValues, yValues0) 23 | t1, = axis.plot(xValues, yValues1) 24 | t2, = axis.plot(xValues, yValues2) 25 | 26 | axis.set_ylabel('Vertical Label') 27 | axis.set_xlabel('Horizontal Label') 28 | 29 | axis.grid() 30 | 31 | fig.legend((t0, t1, t2), ('First line', 'Second line', 'Third line'), 'upper right') 32 | 33 | #-------------------------------------------------------------- 34 | def _destroyWindow(): 35 | root.quit() 36 | root.destroy() 37 | #-------------------------------------------------------------- 38 | root = tk.Tk() 39 | root.withdraw() 40 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 41 | #-------------------------------------------------------------- 42 | canvas = FigureCanvasTkAgg(fig, master=root) 43 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 44 | #-------------------------------------------------------------- 45 | root.update() 46 | root.deiconify() 47 | root.mainloop() 48 | -------------------------------------------------------------------------------- /Ch04_Code/ToolTip.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 16, 2019 3 | Ch04 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | 11 | #=================================================================== 12 | class ToolTip(object): 13 | def __init__(self, widget, tip_text=None): 14 | self.widget = widget 15 | self.tip_text = tip_text 16 | widget.bind('', self.mouse_enter) # bind mouse events 17 | widget.bind('', self.mouse_leave) 18 | 19 | def mouse_enter(self, _event): 20 | self.show_tooltip() 21 | 22 | def mouse_leave(self, _event): 23 | self.hide_tooltip() 24 | 25 | def show_tooltip(self): 26 | if self.tip_text: 27 | x_left = self.widget.winfo_rootx() # get widget top-left coordinates 28 | y_top = self.widget.winfo_rooty() - 18 # place tooltip above widget or it flickers 29 | 30 | self.tip_window = tk.Toplevel(self.widget) # create Toplevel window; parent=widget 31 | self.tip_window.overrideredirect(True) # remove surrounding toolbar window 32 | self.tip_window.geometry("+%d+%d" % (x_left, y_top)) # position tooltip 33 | 34 | label = tk.Label(self.tip_window, text=self.tip_text, justify=tk.LEFT, 35 | background="#ffffe0", relief=tk.SOLID, borderwidth=1, 36 | font=("tahoma", "8", "normal")) 37 | label.pack(ipadx=1) 38 | 39 | def hide_tooltip(self): 40 | if self.tip_window: 41 | self.tip_window.destroy() 42 | 43 | -------------------------------------------------------------------------------- /Ch06_Code/ToolTip.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 16, 2019 3 | Ch04 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | 11 | #=================================================================== 12 | class ToolTip(object): 13 | def __init__(self, widget, tip_text=None): 14 | self.widget = widget 15 | self.tip_text = tip_text 16 | widget.bind('', self.mouse_enter) # bind mouse events 17 | widget.bind('', self.mouse_leave) 18 | 19 | def mouse_enter(self, _event): 20 | self.show_tooltip() 21 | 22 | def mouse_leave(self, _event): 23 | self.hide_tooltip() 24 | 25 | def show_tooltip(self): 26 | if self.tip_text: 27 | x_left = self.widget.winfo_rootx() # get widget top-left coordinates 28 | y_top = self.widget.winfo_rooty() - 18 # place tooltip above widget or it flickers 29 | 30 | self.tip_window = tk.Toplevel(self.widget) # create Toplevel window; parent=widget 31 | self.tip_window.overrideredirect(True) # remove surrounding toolbar window 32 | self.tip_window.geometry("+%d+%d" % (x_left, y_top)) # position tooltip 33 | 34 | label = tk.Label(self.tip_window, text=self.tip_text, justify=tk.LEFT, 35 | background="#ffffe0", relief=tk.SOLID, borderwidth=1, 36 | font=("tahoma", "8", "normal")) 37 | label.pack(ipadx=1) 38 | 39 | def hide_tooltip(self): 40 | if self.tip_window: 41 | self.tip_window.destroy() 42 | 43 | -------------------------------------------------------------------------------- /Ch07_Code/ToolTip.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 16, 2019 3 | Ch04 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | 11 | #=================================================================== 12 | class ToolTip(object): 13 | def __init__(self, widget, tip_text=None): 14 | self.widget = widget 15 | self.tip_text = tip_text 16 | widget.bind('', self.mouse_enter) # bind mouse events 17 | widget.bind('', self.mouse_leave) 18 | 19 | def mouse_enter(self, _event): 20 | self.show_tooltip() 21 | 22 | def mouse_leave(self, _event): 23 | self.hide_tooltip() 24 | 25 | def show_tooltip(self): 26 | if self.tip_text: 27 | x_left = self.widget.winfo_rootx() # get widget top-left coordinates 28 | y_top = self.widget.winfo_rooty() - 18 # place tooltip above widget or it flickers 29 | 30 | self.tip_window = tk.Toplevel(self.widget) # create Toplevel window; parent=widget 31 | self.tip_window.overrideredirect(True) # remove surrounding toolbar window 32 | self.tip_window.geometry("+%d+%d" % (x_left, y_top)) # position tooltip 33 | 34 | label = tk.Label(self.tip_window, text=self.tip_text, justify=tk.LEFT, 35 | background="#ffffe0", relief=tk.SOLID, borderwidth=1, 36 | font=("tahoma", "8", "normal")) 37 | label.pack(ipadx=1) 38 | 39 | def hide_tooltip(self): 40 | if self.tip_window: 41 | self.tip_window.destroy() 42 | 43 | -------------------------------------------------------------------------------- /Ch08_Code/ToolTip.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 16, 2019 3 | Ch04 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | 11 | #=================================================================== 12 | class ToolTip(object): 13 | def __init__(self, widget, tip_text=None): 14 | self.widget = widget 15 | self.tip_text = tip_text 16 | widget.bind('', self.mouse_enter) # bind mouse events 17 | widget.bind('', self.mouse_leave) 18 | 19 | def mouse_enter(self, _event): 20 | self.show_tooltip() 21 | 22 | def mouse_leave(self, _event): 23 | self.hide_tooltip() 24 | 25 | def show_tooltip(self): 26 | if self.tip_text: 27 | x_left = self.widget.winfo_rootx() # get widget top-left coordinates 28 | y_top = self.widget.winfo_rooty() - 18 # place tooltip above widget or it flickers 29 | 30 | self.tip_window = tk.Toplevel(self.widget) # create Toplevel window; parent=widget 31 | self.tip_window.overrideredirect(True) # remove surrounding toolbar window 32 | self.tip_window.geometry("+%d+%d" % (x_left, y_top)) # position tooltip 33 | 34 | label = tk.Label(self.tip_window, text=self.tip_text, justify=tk.LEFT, 35 | background="#ffffe0", relief=tk.SOLID, borderwidth=1, 36 | font=("tahoma", "8", "normal")) 37 | label.pack(ipadx=1) 38 | 39 | def hide_tooltip(self): 40 | if self.tip_window: 41 | self.tip_window.destroy() 42 | 43 | -------------------------------------------------------------------------------- /Ch11_Code/ToolTip.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 16, 2019 3 | Ch04 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | 11 | #=================================================================== 12 | class ToolTip(object): 13 | def __init__(self, widget, tip_text=None): 14 | self.widget = widget 15 | self.tip_text = tip_text 16 | widget.bind('', self.mouse_enter) # bind mouse events 17 | widget.bind('', self.mouse_leave) 18 | 19 | def mouse_enter(self, _event): 20 | self.show_tooltip() 21 | 22 | def mouse_leave(self, _event): 23 | self.hide_tooltip() 24 | 25 | def show_tooltip(self): 26 | if self.tip_text: 27 | x_left = self.widget.winfo_rootx() # get widget top-left coordinates 28 | y_top = self.widget.winfo_rooty() - 18 # place tooltip above widget or it flickers 29 | 30 | self.tip_window = tk.Toplevel(self.widget) # create Toplevel window; parent=widget 31 | self.tip_window.overrideredirect(True) # remove surrounding toolbar window 32 | self.tip_window.geometry("+%d+%d" % (x_left, y_top)) # position tooltip 33 | 34 | label = tk.Label(self.tip_window, text=self.tip_text, justify=tk.LEFT, 35 | background="#ffffe0", relief=tk.SOLID, borderwidth=1, 36 | font=("tahoma", "8", "normal")) 37 | label.pack(ipadx=1) 38 | 39 | def hide_tooltip(self): 40 | if self.tip_window: 41 | self.tip_window.destroy() 42 | 43 | -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_labels_two_charts_scaled_dynamic_spike.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard 5 | ''' 6 | from matplotlib.figure import Figure 7 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 8 | import tkinter as tk 9 | #-------------------------------------------------------------- 10 | fig = Figure(figsize=(12, 5), facecolor='white') 11 | #-------------------------------------------------------------- 12 | axis = fig.add_subplot(111) # 1 row, 1 column 13 | 14 | xValues = [1,2,3,4] 15 | 16 | yValues0 = [6,7.5,8,7.5] 17 | yValues1 = [5.5,6.5,50,6] # one very high value (50) 18 | yValues2 = [6.5,7,8,7] 19 | 20 | axis.set_ylim(0, 8) # lower limit (0) 21 | axis.set_xlim(0, 8) # use same limits for x 22 | 23 | t0, = axis.plot(xValues, yValues0) 24 | t1, = axis.plot(xValues, yValues1) 25 | t2, = axis.plot(xValues, yValues2) 26 | 27 | axis.set_ylabel('Vertical Label') 28 | axis.set_xlabel('Horizontal Label') 29 | 30 | axis.grid() 31 | fig.legend((t0, t1, t2), ('First line', 'Second line', 'Third line'), 'upper right') 32 | #-------------------------------------------------------------- 33 | def _destroyWindow(): 34 | root.quit() 35 | root.destroy() 36 | #-------------------------------------------------------------- 37 | root = tk.Tk() 38 | root.withdraw() 39 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 40 | #-------------------------------------------------------------- 41 | canvas = FigureCanvasTkAgg(fig, master=root) 42 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 43 | #-------------------------------------------------------------- 44 | root.update() 45 | root.deiconify() 46 | root.mainloop() 47 | -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_labels_two_charts.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard 5 | ''' 6 | 7 | from matplotlib.figure import Figure 8 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 9 | import tkinter as tk 10 | #-------------------------------------------------------------- 11 | fig = Figure(figsize=(12, 8), facecolor='white') 12 | #-------------------------------------------------------------- 13 | axis = fig.add_subplot(211) # 2 rows, 1 column, Top graph 14 | #-------------------------------------------------------------- 15 | xValues = [1,2,3,4] 16 | yValues0 = [5,7,6,8] 17 | axis.plot(xValues, yValues0) 18 | 19 | axis.set_xlabel('Horizontal Label') 20 | axis.set_ylabel('Vertical Label') 21 | 22 | axis.grid(linestyle='-') # solid grid lines 23 | #-------------------------------------------------------------- 24 | axis1 = fig.add_subplot(212) # 2 rows, 1 column, Bottom graph 25 | #-------------------------------------------------------------- 26 | xValues1 = [1,2,3,4] 27 | yValues1 = [7,5,8,6] 28 | axis1.plot(xValues1, yValues1) 29 | axis1.grid() # default line style 30 | #-------------------------------------------------------------- 31 | def _destroyWindow(): 32 | root.quit() 33 | root.destroy() 34 | #-------------------------------------------------------------- 35 | root = tk.Tk() 36 | root.withdraw() 37 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 38 | #-------------------------------------------------------------- 39 | canvas = FigureCanvasTkAgg(fig, master=root) 40 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 41 | #-------------------------------------------------------------- 42 | root.update() 43 | root.deiconify() 44 | root.mainloop() 45 | -------------------------------------------------------------------------------- /Ch09_Code/Embed_wxPython.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 15, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | #================================================================== 7 | import tkinter as tk 8 | from tkinter import ttk 9 | from tkinter import scrolledtext 10 | 11 | win = tk.Tk() 12 | 13 | win.title("Python GUI") 14 | aLabel = ttk.Label(win, text="A Label") 15 | aLabel.grid(column=0, row=0) 16 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 17 | name = tk.StringVar() 18 | nameEntered = ttk.Entry(win, width=12, textvariable=name) 19 | nameEntered.grid(column=0, row=1) 20 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 21 | number = tk.StringVar() 22 | numberChosen = ttk.Combobox(win, width=12, textvariable=number) 23 | numberChosen['values'] = (1, 2, 4, 42, 100) 24 | numberChosen.grid(column=1, row=1) 25 | numberChosen.current(0) 26 | scrolW = 30 27 | scrolH = 3 28 | scr = scrolledtext.ScrolledText(win, width=scrolW, height=scrolH, wrap=tk.WORD) 29 | scr.grid(column=0, sticky='WE', columnspan=3) 30 | nameEntered.focus() 31 | 32 | #================================================================== 33 | def wxPythonApp(): 34 | import wx 35 | app = wx.App() 36 | frame = wx.Frame(None, -1, "wxPython GUI", size=(200,150)) 37 | frame.SetBackgroundColour('white') 38 | frame.CreateStatusBar() 39 | menu= wx.Menu() 40 | menu.Append(wx.ID_ABOUT, "About", "wxPython GUI") 41 | menuBar = wx.MenuBar() 42 | menuBar.Append(menu, "File") 43 | frame.SetMenuBar(menuBar) 44 | frame.Show() 45 | app.MainLoop() 46 | 47 | 48 | action = ttk.Button(win, text="Call wxPython GUI", command=wxPythonApp) 49 | action.grid(column=2, row=1) 50 | 51 | #====================== 52 | # Start GUI 53 | #====================== 54 | win.mainloop() -------------------------------------------------------------------------------- /Ch11_Code/GUI_Not_OOP.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | import tkinter as tk 8 | from tkinter import ttk 9 | from tkinter import scrolledtext 10 | from tkinter import Menu 11 | 12 | def createWidgets(): 13 | tabControl = ttk.Notebook(win) 14 | tab1 = ttk.Frame(tabControl) 15 | tabControl.add(tab1, text='Tab 1') 16 | tabControl.pack(expand=1, fill="both") 17 | monty = ttk.LabelFrame(tab1, text=' Mighty Python ') 18 | monty.grid(column=0, row=0, padx=8, pady=4) 19 | 20 | ttk.Label(monty, text="Enter a name:").grid(column=0, row=0, sticky='W') 21 | name = tk.StringVar() 22 | nameEntered = ttk.Entry(monty, width=12, textvariable=name) 23 | nameEntered.grid(column=0, row=1, sticky='W') 24 | 25 | action = ttk.Button(monty, text="Click Me!") 26 | action.grid(column=2, row=1) 27 | 28 | ttk.Label(monty, text="Choose a number:").grid(column=1, row=0) 29 | number = tk.StringVar() 30 | numberChosen = ttk.Combobox(monty, width=12, textvariable=number) 31 | numberChosen['values'] = (42) 32 | numberChosen.grid(column=1, row=1) 33 | numberChosen.current(0) 34 | 35 | scrolW = 30; scrolH = 3 36 | scr = scrolledtext.ScrolledText(monty, width=scrolW, height=scrolH, wrap=tk.WORD) 37 | scr.grid(column=0, row=3, sticky='WE', columnspan=3) 38 | 39 | menuBar = Menu(tab1) 40 | win.config(menu=menuBar) 41 | fileMenu = Menu(menuBar, tearoff=0) 42 | menuBar.add_cascade(label="File", menu=fileMenu) 43 | helpMenu = Menu(menuBar, tearoff=0) 44 | menuBar.add_cascade(label="Help", menu=helpMenu) 45 | 46 | nameEntered.focus() 47 | #====================== 48 | win = tk.Tk() 49 | win.title("Python GUI") 50 | createWidgets() 51 | win.mainloop() 52 | 53 | -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_chart_with_legend_colors.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard 5 | ''' 6 | from matplotlib.figure import Figure 7 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 8 | import tkinter as tk 9 | #-------------------------------------------------------------- 10 | fig = Figure(figsize=(12, 5), facecolor='white') 11 | #-------------------------------------------------------------- 12 | axis = fig.add_subplot(111) # 1 row, 1 column 13 | 14 | xValues = [1,2,3,4] 15 | 16 | yValues0 = [6,7.5,8,7.5] 17 | yValues1 = [5.5,6.5,8,6] 18 | yValues2 = [6.5,7,8,7] 19 | 20 | # the commas after t0, t1 and t2 are required 21 | # t0, = axis.plot(xValues, yValues0) 22 | # t1, = axis.plot(xValues, yValues1) 23 | # t2, = axis.plot(xValues, yValues2) 24 | 25 | t0, = axis.plot(xValues, yValues0, color = 'purple') # change the color of the plotted line 26 | t1, = axis.plot(xValues, yValues1, color = 'red') 27 | t2, = axis.plot(xValues, yValues2, color = 'blue') 28 | 29 | axis.set_ylabel('Vertical Label') 30 | axis.set_xlabel('Horizontal Label') 31 | 32 | axis.grid() 33 | 34 | fig.legend((t0, t1, t2), ('First line', 'Second line', 'Third line'), 'upper right') 35 | 36 | #-------------------------------------------------------------- 37 | def _destroyWindow(): 38 | root.quit() 39 | root.destroy() 40 | #-------------------------------------------------------------- 41 | root = tk.Tk() 42 | # root.withdraw() 43 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 44 | #-------------------------------------------------------------- 45 | canvas = FigureCanvasTkAgg(fig, master=root) 46 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 47 | #-------------------------------------------------------------- 48 | # root.update() 49 | # root.deiconify() 50 | root.mainloop() 51 | -------------------------------------------------------------------------------- /Ch09_Code/wxPython_panel_GUI.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 15, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | import wx # Import wxPython GUI toolkit 7 | class GUI(wx.Panel): # Subclass wxPython Panel 8 | def __init__(self, parent): 9 | 10 | # Initialize super class 11 | wx.Panel.__init__(self, parent) 12 | 13 | # Create Status Bar 14 | parent.CreateStatusBar() 15 | 16 | # Create the Menu 17 | menu= wx.Menu() 18 | 19 | # Add Menu Items to the Menu 20 | menu.Append(wx.ID_ABOUT, "About", "wxPython GUI") 21 | menu.AppendSeparator() 22 | menu.Append(wx.ID_EXIT, "Exit"," Exit the GUI") 23 | 24 | # Create the MenuBar 25 | menuBar = wx.MenuBar() 26 | 27 | # Give the Menu a Title 28 | menuBar.Append(menu, "File") 29 | 30 | # Connect the MenuBar to the frame 31 | parent.SetMenuBar(menuBar) 32 | 33 | # Create a Print Button 34 | button = wx.Button(self, label="Print", pos=(0,60)) 35 | 36 | # Connect Button to Click Event method 37 | self.Bind(wx.EVT_BUTTON, self.printButton, button) 38 | 39 | # Create a Text Control widget 40 | self.textBox = wx.TextCtrl(self, size=(280,50), style=wx.TE_MULTILINE) 41 | 42 | 43 | # callback event handler 44 | def printButton(self, event): 45 | # Click Event method 46 | self.textBox.AppendText("The Print Button has been clicked!") 47 | 48 | 49 | app = wx.App() # Create instance of wxPython application 50 | # Create frame 51 | frame = wx.Frame(None, title="Python GUI using wxPython", size=(300,180)) 52 | GUI(frame) # Pass frame into GUI 53 | frame.Show() # Display the frame 54 | app.MainLoop() # Run the main GUI event loop 55 | -------------------------------------------------------------------------------- /Ch10_Code/Designer_Second_UI.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 0 22 | 391 23 | 241 24 | 25 | 26 | 27 | 28 | Tab 1 29 | 30 | 31 | 32 | 33 | Tab 2 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 0 42 | 0 43 | 400 44 | 21 45 | 46 | 47 | 48 | 49 | File 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | New 60 | 61 | 62 | 63 | 64 | Exit 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Ch11_Code/GUI_NOT_Spaghetti.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | #====================== 8 | # imports 9 | #====================== 10 | import tkinter as tk 11 | from tkinter import ttk 12 | from tkinter import scrolledtext 13 | 14 | #====================== 15 | # Create instance 16 | #====================== 17 | win = tk.Tk() 18 | 19 | #====================== 20 | # Add a title 21 | #====================== 22 | win.title("Python GUI") 23 | 24 | #========================= 25 | # Disable resizing the GUI 26 | #========================= 27 | win.resizable(0,0) 28 | 29 | #=============================================================================== 30 | # Adding a LabelFrame, Textbox (Entry) and Combobox 31 | #=============================================================================== 32 | lFrame = ttk.LabelFrame(win, text="Python GUI Programming Cookbook") 33 | lFrame.grid(column=0, row=0, sticky='WE', padx=10, pady=10) 34 | 35 | #=============================================================================== 36 | # Using a scrolled Text control 37 | #=============================================================================== 38 | outputFrame = ttk.LabelFrame(win, text=' Type into the scrolled text control: ') 39 | outputFrame.grid(column=0, row=2, sticky='E', padx=8) 40 | scrolW = 30 41 | scrolH = 6 42 | scr = scrolledtext.ScrolledText(outputFrame, width=scrolW, height=scrolH, wrap=tk.WORD) 43 | scr.grid(column=1, row=0, sticky='WE') 44 | 45 | #=============================================================================== 46 | # Creating a checkbutton 47 | #=============================================================================== 48 | chVarUn = tk.IntVar() 49 | check2 = tk.Checkbutton(lFrame, text="Enabled", variable=chVarUn) 50 | check2.deselect() 51 | check2.grid(column=1, row=4, sticky=tk.W, columnspan=3) 52 | 53 | #====================== 54 | # Start GUI 55 | #====================== 56 | win.mainloop() -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_chart_with_legend.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard 5 | ''' 6 | from matplotlib.figure import Figure 7 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 8 | import tkinter as tk 9 | #-------------------------------------------------------------- 10 | fig = Figure(figsize=(12, 5), facecolor='white') 11 | #-------------------------------------------------------------- 12 | axis = fig.add_subplot(111) # 1 row, 1 column 13 | 14 | xValues = [1,2,3,4] 15 | 16 | yValues0 = [6,7.5,8,7.5] 17 | yValues1 = [5.5,6.5,8,6] 18 | yValues2 = [6.5,7,8,7] 19 | 20 | # the commas after t0, t1 and t2 are required 21 | t0, = axis.plot(xValues, yValues0) 22 | t1, = axis.plot(xValues, yValues1) 23 | t2, = axis.plot(xValues, yValues2) 24 | 25 | # t0, = axis.plot(xValues, yValues0, color = 'purple') # change the color of the plotted line to purple 26 | # t0, = axis.plot(xValues, yValues0, color = 'r') # change the color of the plotted line 27 | # t1, = axis.plot(xValues, yValues1, color = 'b') 28 | # t2, = axis.plot(xValues, yValues2, color = 'purple') 29 | 30 | axis.set_ylabel('Vertical Label') 31 | axis.set_xlabel('Horizontal Label') 32 | 33 | axis.grid() 34 | 35 | fig.legend((t0, t1, t2), ('First line', 'Second line', 'Third line'), 'upper right') 36 | 37 | #-------------------------------------------------------------- 38 | def _destroyWindow(): 39 | root.quit() 40 | root.destroy() 41 | #-------------------------------------------------------------- 42 | root = tk.Tk() 43 | # root.withdraw() 44 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 45 | #-------------------------------------------------------------- 46 | canvas = FigureCanvasTkAgg(fig, master=root) 47 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 48 | #-------------------------------------------------------------- 49 | # root.update() 50 | # root.deiconify() 51 | root.mainloop() 52 | -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_chart_with_legend_missing_comma.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard 5 | ''' 6 | from matplotlib.figure import Figure 7 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 8 | import tkinter as tk 9 | #-------------------------------------------------------------- 10 | fig = Figure(figsize=(12, 5), facecolor='white') 11 | #-------------------------------------------------------------- 12 | axis = fig.add_subplot(111) # 1 row, 1 column 13 | 14 | xValues = [1,2,3,4] 15 | 16 | yValues0 = [6,7.5,8,7.5] 17 | yValues1 = [5.5,6.5,8,6] 18 | yValues2 = [6.5,7,8,7] 19 | 20 | # the commas after t0, t1 and t2 are required to unpack the list of Matplotlib Line2D objects 21 | t0 = axis.plot(xValues, yValues0) # no comma here 22 | t1, = axis.plot(xValues, yValues1) 23 | t2, = axis.plot(xValues, yValues2) 24 | 25 | # t0, = axis.plot(xValues, yValues0, color = 'purple') # change the color of the plotted line to purple 26 | # t0, = axis.plot(xValues, yValues0, color = 'r') # change the color of the plotted line 27 | # t1, = axis.plot(xValues, yValues1, color = 'b') 28 | # t2, = axis.plot(xValues, yValues2, color = 'purple') 29 | 30 | axis.set_ylabel('Vertical Label') 31 | axis.set_xlabel('Horizontal Label') 32 | 33 | axis.grid() 34 | 35 | fig.legend((t0, t1, t2), ('First line', 'Second line', 'Third line'), 'upper right') 36 | 37 | #-------------------------------------------------------------- 38 | def _destroyWindow(): 39 | root.quit() 40 | root.destroy() 41 | #-------------------------------------------------------------- 42 | root = tk.Tk() 43 | root.withdraw() 44 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 45 | #-------------------------------------------------------------- 46 | canvas = FigureCanvasTkAgg(fig, master=root) 47 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 48 | #-------------------------------------------------------------- 49 | root.update() 50 | root.deiconify() 51 | root.mainloop() 52 | -------------------------------------------------------------------------------- /Ch10_Code/Designer_First_UI.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'Designer_First_UI.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_MainWindow(object): 12 | def setupUi(self, MainWindow): 13 | MainWindow.setObjectName("MainWindow") 14 | MainWindow.resize(400, 300) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | MainWindow.setCentralWidget(self.centralwidget) 18 | self.menubar = QtWidgets.QMenuBar(MainWindow) 19 | self.menubar.setGeometry(QtCore.QRect(0, 0, 400, 21)) 20 | self.menubar.setObjectName("menubar") 21 | self.menuFile = QtWidgets.QMenu(self.menubar) 22 | self.menuFile.setObjectName("menuFile") 23 | MainWindow.setMenuBar(self.menubar) 24 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 25 | self.statusbar.setObjectName("statusbar") 26 | MainWindow.setStatusBar(self.statusbar) 27 | self.actionNew = QtWidgets.QAction(MainWindow) 28 | self.actionNew.setObjectName("actionNew") 29 | self.menuFile.addAction(self.actionNew) 30 | self.menubar.addAction(self.menuFile.menuAction()) 31 | 32 | self.retranslateUi(MainWindow) 33 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 34 | 35 | def retranslateUi(self, MainWindow): 36 | _translate = QtCore.QCoreApplication.translate 37 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 38 | self.menuFile.setTitle(_translate("MainWindow", "File")) 39 | self.actionNew.setText(_translate("MainWindow", "New")) 40 | 41 | 42 | if __name__ == "__main__": 43 | import sys 44 | app = QtWidgets.QApplication(sys.argv) 45 | MainWindow = QtWidgets.QMainWindow() 46 | ui = Ui_MainWindow() 47 | ui.setupUi(MainWindow) 48 | MainWindow.show() 49 | sys.exit(app.exec_()) 50 | 51 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_checkbutton_widget.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Modify adding a Label 19 | a_label = ttk.Label(win, text="A Label") 20 | a_label.grid(column=0, row=0) 21 | 22 | # Modified Button Click Function 23 | def click_me(): 24 | action.configure(text='Hello ' + name.get() + ' ' + 25 | number_chosen.get()) 26 | 27 | # Changing our Label 28 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 29 | 30 | # Adding a Textbox Entry widget 31 | name = tk.StringVar() 32 | name_entered = ttk.Entry(win, width=12, textvariable=name) 33 | name_entered.grid(column=0, row=1) 34 | 35 | # Adding a Button 36 | action = ttk.Button(win, text="Click Me!", command=click_me) 37 | action.grid(column=2, row=1) 38 | 39 | # Creating three checkbuttons 40 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 41 | number = tk.StringVar() 42 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 43 | number_chosen['values'] = (1, 2, 4, 42, 100) 44 | number_chosen.grid(column=1, row=1) 45 | number_chosen.current(0) 46 | 47 | chVarDis = tk.IntVar() 48 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 49 | check1.select() 50 | check1.grid(column=0, row=4, sticky=tk.W) 51 | 52 | chVarUn = tk.IntVar() 53 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 54 | check2.deselect() 55 | check2.grid(column=1, row=4, sticky=tk.W) 56 | 57 | chVarEn = tk.IntVar() 58 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 59 | check3.select() 60 | check3.grid(column=2, row=4, sticky=tk.W) 61 | 62 | name_entered.focus() # Place cursor into name Entry 63 | #====================== 64 | # Start GUI 65 | #====================== 66 | win.mainloop() -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_labels_two_charts_scaled_dynamic.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard 5 | ''' 6 | from matplotlib.figure import Figure 7 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 8 | import tkinter as tk 9 | #-------------------------------------------------------------- 10 | fig = Figure(figsize=(12, 5), facecolor='white') 11 | #-------------------------------------------------------------- 12 | axis = fig.add_subplot(111) # 1 row, 1 column 13 | 14 | xValues = [1,2,3,4] 15 | 16 | yValues0 = [6,7.5,8,7.5] 17 | yValues1 = [5.5,6.5,50,6] # one very high value (50) 18 | yValues2 = [6.5,7,8,7] 19 | yAll = [yValues0, yValues1, yValues2] # list of lists 20 | 21 | # flatten list of lists retrieving minimum value 22 | minY = min([y for yValues in yAll for y in yValues]) 23 | 24 | yUpperLimit = 20 25 | # flatten list of lists retrieving max value within defined limit 26 | maxY = max([y for yValues in yAll for y in yValues if y < yUpperLimit]) 27 | 28 | # dynamic limits 29 | axis.set_ylim(minY, maxY) 30 | axis.set_xlim(min(xValues), max(xValues)) 31 | 32 | t0, = axis.plot(xValues, yValues0) 33 | t1, = axis.plot(xValues, yValues1) 34 | t2, = axis.plot(xValues, yValues2) 35 | 36 | axis.set_ylabel('Vertical Label') 37 | axis.set_xlabel('Horizontal Label') 38 | 39 | axis.grid() 40 | fig.legend((t0, t1, t2), ('First line', 'Second line', 'Third line'), 'upper right') 41 | #-------------------------------------------------------------- 42 | def _destroyWindow(): 43 | root.quit() 44 | root.destroy() 45 | #-------------------------------------------------------------- 46 | root = tk.Tk() 47 | root.withdraw() 48 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 49 | #-------------------------------------------------------------- 50 | canvas = FigureCanvasTkAgg(fig, master=root) 51 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 52 | #-------------------------------------------------------------- 53 | root.update() 54 | root.deiconify() 55 | root.mainloop() 56 | -------------------------------------------------------------------------------- /Ch11_Code/GUI_OOP.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | import tkinter as tk 8 | from tkinter import ttk 9 | from tkinter import scrolledtext 10 | from tkinter import Menu 11 | 12 | class OOP(): 13 | def __init__(self): 14 | self.win = tk.Tk() 15 | self.win.title("Python GUI") 16 | self.createWidgets() 17 | 18 | def createWidgets(self): 19 | tabControl = ttk.Notebook(self.win) 20 | tab1 = ttk.Frame(tabControl) 21 | tabControl.add(tab1, text='Tab 1') 22 | tabControl.pack(expand=1, fill="both") 23 | self.monty = ttk.LabelFrame(tab1, text=' Mighty Python ') 24 | self.monty.grid(column=0, row=0, padx=8, pady=4) 25 | 26 | ttk.Label(self.monty, text="Enter a name:").grid(column=0, row=0, sticky='W') 27 | self.name = tk.StringVar() 28 | nameEntered = ttk.Entry(self.monty, width=12, textvariable=self.name) 29 | nameEntered.grid(column=0, row=1, sticky='W') 30 | 31 | self.action = ttk.Button(self.monty, text="Click Me!") 32 | self.action.grid(column=2, row=1) 33 | 34 | ttk.Label(self.monty, text="Choose a number:").grid(column=1, row=0) 35 | number = tk.StringVar() 36 | numberChosen = ttk.Combobox(self.monty, width=12, textvariable=number) 37 | numberChosen['values'] = (42) 38 | numberChosen.grid(column=1, row=1) 39 | numberChosen.current(0) 40 | 41 | scrolW = 30; scrolH = 3 42 | self.scr = scrolledtext.ScrolledText(self.monty, width=scrolW, height=scrolH, wrap=tk.WORD) 43 | self.scr.grid(column=0, row=3, sticky='WE', columnspan=3) 44 | 45 | menuBar = Menu(tab1) 46 | self.win.config(menu=menuBar) 47 | fileMenu = Menu(menuBar, tearoff=0) 48 | menuBar.add_cascade(label="File", menu=fileMenu) 49 | helpMenu = Menu(menuBar, tearoff=0) 50 | menuBar.add_cascade(label="Help", menu=helpMenu) 51 | 52 | nameEntered.focus() 53 | #========================== 54 | oop = OOP() 55 | oop.win.mainloop() 56 | 57 | -------------------------------------------------------------------------------- /Ch09_Code/Control_Frameworks_NOT_working.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 15, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | #================================================================== 7 | import tkinter as tk 8 | from tkinter import ttk 9 | from tkinter import scrolledtext 10 | from threading import Thread 11 | 12 | win = tk.Tk() 13 | 14 | win.title("Python GUI") 15 | aLabel = ttk.Label(win, text="A Label") 16 | aLabel.grid(column=0, row=0) 17 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 18 | name = tk.StringVar() 19 | nameEntered = ttk.Entry(win, width=12, textvariable=name) 20 | nameEntered.grid(column=0, row=1) 21 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 22 | number = tk.StringVar() 23 | numberChosen = ttk.Combobox(win, width=12, textvariable=number) 24 | numberChosen['values'] = (1, 2, 4, 42, 100) 25 | numberChosen.grid(column=1, row=1) 26 | numberChosen.current(0) 27 | scrolW = 30 28 | scrolH = 3 29 | scr = scrolledtext.ScrolledText(win, width=scrolW, height=scrolH, wrap=tk.WORD) 30 | scr.grid(column=0, sticky='WE', columnspan=3) 31 | nameEntered.focus() 32 | 33 | #================================================================== 34 | # NOT working - CRASHES Python ----------------------------------- 35 | def wxPythonApp(): 36 | import wx 37 | app = wx.App() 38 | frame = wx.Frame(None, -1, "wxPython GUI", size=(200,150)) 39 | frame.SetBackgroundColour('white') 40 | frame.CreateStatusBar() 41 | menu= wx.Menu() 42 | menu.Append(wx.ID_ABOUT, "About", "wxPython GUI") 43 | menuBar = wx.MenuBar() 44 | menuBar.Append(menu,"File") 45 | frame.SetMenuBar(menuBar) 46 | frame.Show() 47 | app.MainLoop() 48 | 49 | def tryRunInThread(): 50 | runT = Thread(target=wxPythonApp) 51 | runT.setDaemon(True) 52 | runT.start() 53 | print(runT) 54 | print('createThread():', runT.isAlive()) 55 | 56 | action = ttk.Button(win, text="Call wxPython GUI", command=tryRunInThread) 57 | action.grid(column=2, row=1) 58 | #----------------------------------------------------------------- 59 | 60 | #====================== 61 | # Start GUI 62 | #====================== 63 | win.mainloop() -------------------------------------------------------------------------------- /Ch08_Code/UnitTests.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 9, 2019 3 | Ch08 4 | @author: Burkhard 5 | ''' 6 | 7 | import unittest 8 | from Ch08_Code.LanguageResources import I18N 9 | from Ch08_Code.GUI_Refactored import OOP as GUI 10 | 11 | class GuiUnitTests(unittest.TestCase): 12 | 13 | def test_TitleIsEnglish(self): 14 | i18n = I18N('en') 15 | self.assertEqual(i18n.title, "Python Graphical User Interface") 16 | 17 | def test_TitleIsGerman(self): 18 | # i18n = I18N('en') # <= Bug in Unit Test 19 | i18n = I18N('de') 20 | self.assertEqual(i18n.title, 'Python Grafische Benutzeroberfl' + "\u00E4" + 'che') 21 | 22 | 23 | class WidgetsTestsEnglish(unittest.TestCase): 24 | 25 | def setUp(self): 26 | self.gui = GUI('en') 27 | 28 | def tearDown(self): 29 | self.gui = None 30 | 31 | def test_WidgetLabels(self): 32 | self.assertEqual(self.gui.i18n.file, "File") 33 | self.assertEqual(self.gui.i18n.mgrFiles, ' Manage Files ') 34 | self.assertEqual(self.gui.i18n.browseTo, "Browse to File...") 35 | 36 | def test_LabelFrameText(self): 37 | labelFrameText = self.gui.widgetFrame['text'] 38 | self.assertEqual(labelFrameText, " Widgets Frame ") 39 | 40 | 41 | class WidgetsTestsGerman(unittest.TestCase): 42 | 43 | def setUp(self): 44 | self.gui = GUI('de') 45 | 46 | def test_WidgetLabels(self): 47 | self.assertEqual(self.gui.i18n.file, "Datei") 48 | self.assertEqual(self.gui.i18n.mgrFiles, ' Dateien Organisieren ') 49 | self.assertEqual(self.gui.i18n.browseTo, "Waehle eine Datei... ") 50 | 51 | def test_LabelFrameText(self): 52 | labelFrameText = self.gui.widgetFrame['text'] 53 | self.assertEqual(labelFrameText, " Widgets Rahmen ") 54 | self.gui.radVar.set(1) 55 | self.gui.callBacks.radCall() 56 | labelFrameText = self.gui.widgetFrame['text'] 57 | self.assertEqual(labelFrameText, 58 | " Widgets Rahmen in Gold") 59 | 60 | 61 | #========================== 62 | if __name__ == '__main__': 63 | unittest.main() 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Ch10_Code/Designer_First_UI_Exit.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'Designer_First_UI.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_MainWindow(object): 12 | def setupUi(self, MainWindow): 13 | MainWindow.setObjectName("MainWindow") 14 | MainWindow.resize(400, 300) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | MainWindow.setCentralWidget(self.centralwidget) 18 | self.menubar = QtWidgets.QMenuBar(MainWindow) 19 | self.menubar.setGeometry(QtCore.QRect(0, 0, 400, 21)) 20 | self.menubar.setObjectName("menubar") 21 | self.menuFile = QtWidgets.QMenu(self.menubar) 22 | self.menuFile.setObjectName("menuFile") 23 | MainWindow.setMenuBar(self.menubar) 24 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 25 | self.statusbar.setObjectName("statusbar") 26 | MainWindow.setStatusBar(self.statusbar) 27 | self.actionNew = QtWidgets.QAction(MainWindow) 28 | self.actionNew.setObjectName("actionNew") 29 | self.actionExit = QtWidgets.QAction(MainWindow) 30 | self.actionExit.setObjectName("actionExit") 31 | self.menuFile.addAction(self.actionNew) 32 | self.menuFile.addAction(self.actionExit) 33 | self.menubar.addAction(self.menuFile.menuAction()) 34 | 35 | self.retranslateUi(MainWindow) 36 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 37 | 38 | def retranslateUi(self, MainWindow): 39 | _translate = QtCore.QCoreApplication.translate 40 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 41 | self.menuFile.setTitle(_translate("MainWindow", "File")) 42 | self.actionNew.setText(_translate("MainWindow", "New")) 43 | self.actionExit.setText(_translate("MainWindow", "Exit")) 44 | 45 | 46 | if __name__ == "__main__": 47 | import sys 48 | app = QtWidgets.QApplication(sys.argv) 49 | MainWindow = QtWidgets.QMainWindow() 50 | ui = Ui_MainWindow() 51 | ui.setupUi(MainWindow) 52 | MainWindow.show() 53 | sys.exit(app.exec_()) 54 | 55 | -------------------------------------------------------------------------------- /Ch05_Code/Matplotlib_labels_four.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 24, 2019 3 | Chp05 4 | @author: Burkhard 5 | ''' 6 | 7 | from matplotlib.figure import Figure 8 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 9 | import tkinter as tk 10 | #-------------------------------------------------------------- 11 | fig = Figure(figsize=(12, 8), facecolor='white') 12 | xValues = [1,2,3,4] 13 | yValues = [5,7,6,8] 14 | #-------------------------------------------------------------- 15 | axis1 = fig.add_subplot(211) 16 | axis2 = fig.add_subplot(222, sharex=axis1, sharey=axis1) 17 | axis3 = fig.add_subplot(223, sharex=axis1, sharey=axis1) 18 | axis4 = fig.add_subplot(224, sharex=axis1, sharey=axis1) 19 | #-------------------------------------------------------------- 20 | axis1.plot(xValues, yValues) 21 | axis1.set_xlabel('Horizontal Label 1') 22 | axis1.set_ylabel('Vertical Label 1') 23 | axis1.grid(linestyle='-') # solid grid lines 24 | #-------------------------------------------------------------- 25 | axis2.plot(xValues, yValues) 26 | axis2.set_xlabel('Horizontal Label 2') 27 | axis2.set_ylabel('Vertical Label 2') 28 | axis2.grid(linestyle='-') # solid grid lines 29 | #-------------------------------------------------------------- 30 | axis3.plot(xValues, yValues) 31 | axis3.set_xlabel('Horizontal Label3') 32 | axis3.set_ylabel('Vertical Label 3') 33 | axis3.grid(linestyle='-') # solid grid lines 34 | #-------------------------------------------------------------- 35 | axis4.plot(xValues, yValues) 36 | axis4.set_xlabel('Horizontal Label 4') 37 | axis4.set_ylabel('Vertical Label 4') 38 | axis4.grid(linestyle='-') # solid grid lines 39 | #-------------------------------------------------------------- 40 | 41 | #-------------------------------------------------------------- 42 | def _destroyWindow(): 43 | root.quit() 44 | root.destroy() 45 | #-------------------------------------------------------------- 46 | root = tk.Tk() 47 | root.withdraw() 48 | root.protocol('WM_DELETE_WINDOW', _destroyWindow) 49 | #-------------------------------------------------------------- 50 | canvas = FigureCanvasTkAgg(fig, master=root) 51 | canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) 52 | #-------------------------------------------------------------- 53 | root.update() 54 | root.deiconify() 55 | root.mainloop() 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /Ch10_Code/Designer_Second_UI_layout.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 0 22 | 391 23 | 241 24 | 25 | 26 | 27 | 28 | Tab 1 29 | 30 | 31 | 32 | 33 | 20 34 | 120 35 | 361 36 | 80 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 20 45 | 20 46 | 160 47 | 80 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Tab 2 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 0 64 | 0 65 | 400 66 | 21 67 | 68 | 69 | 70 | 71 | File 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | New 82 | 83 | 84 | 85 | 86 | Exit 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /Ch08_Code/Logger.py: -------------------------------------------------------------------------------- 1 | import os, time 2 | from datetime import datetime 3 | 4 | class LogLevel: 5 | '''Define logging levels.''' 6 | OFF = 0 7 | MINIMUM = 1 8 | NORMAL = 2 9 | DEBUG = 3 10 | 11 | 12 | class Logger: 13 | ''' Create a test log and write to it. ''' 14 | #-------------------------------------------------------------------------- 15 | def __init__(self, fullTestName, loglevel=LogLevel.DEBUG): 16 | testName = os.path.splitext(os.path.basename(fullTestName))[0] 17 | logName = testName + '.log' 18 | 19 | logsFolder = 'logs' 20 | if not os.path.exists(logsFolder): 21 | os.makedirs(logsFolder, exist_ok = True) 22 | 23 | self.log = os.path.join(logsFolder, logName) 24 | self.createLog() 25 | 26 | self.loggingLevel = loglevel 27 | self.startTime = time.perf_counter() 28 | 29 | #-------------------------------------------------------------------------- 30 | def createLog(self): 31 | with open(self.log, mode='w', encoding='utf-8') as logFile: 32 | logFile.write(self.getDateTime() + 33 | '\t\t*** Starting Test ***\n') 34 | logFile.close() 35 | 36 | #-------------------------------------------------------------------------- 37 | def setLoggingLevel(self, level): 38 | '''change logging level in the middle of a test.''' 39 | self.loggingLevel = level 40 | 41 | #-------------------------------------------------------------------------- 42 | def writeToLog(self, msg='', loglevel=LogLevel.DEBUG): 43 | # control how much gets logged 44 | if loglevel > self.loggingLevel: 45 | return 46 | 47 | # open log file in append mode 48 | with open(self.log, mode='a', encoding='utf-8') as logFile: 49 | msg = str(msg) 50 | if msg.startswith('\n'): 51 | msg = msg[1:] 52 | logFile.write(self.getDateTime() + '\t\t' + msg + '\n') 53 | 54 | logFile.close() 55 | 56 | #-------------------------------------------------------------------------- 57 | def getDateTime(self,): 58 | return datetime.now().strftime("%Y-%m-%d %H:%M:%S") 59 | 60 | #-------------------------------------------------------------------------- 61 | def writeTestRunTime(self): 62 | elapsed = time.perf_counter() - self.startTime 63 | self.writeToLog('\nElapsed Test Time (seconds): {0:.2f}'.format(elapsed), loglevel=LogLevel.OFF) 64 | 65 | 66 | -------------------------------------------------------------------------------- /Ch10_Code/Designer_Second_UI.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'Designer_Second_UI.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_MainWindow(object): 12 | def setupUi(self, MainWindow): 13 | MainWindow.setObjectName("MainWindow") 14 | MainWindow.resize(400, 300) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) 18 | self.tabWidget.setGeometry(QtCore.QRect(0, 0, 391, 241)) 19 | self.tabWidget.setObjectName("tabWidget") 20 | self.tab = QtWidgets.QWidget() 21 | self.tab.setObjectName("tab") 22 | self.tabWidget.addTab(self.tab, "") 23 | self.tab_2 = QtWidgets.QWidget() 24 | self.tab_2.setObjectName("tab_2") 25 | self.tabWidget.addTab(self.tab_2, "") 26 | MainWindow.setCentralWidget(self.centralwidget) 27 | self.menubar = QtWidgets.QMenuBar(MainWindow) 28 | self.menubar.setGeometry(QtCore.QRect(0, 0, 400, 21)) 29 | self.menubar.setObjectName("menubar") 30 | self.menuFile = QtWidgets.QMenu(self.menubar) 31 | self.menuFile.setObjectName("menuFile") 32 | MainWindow.setMenuBar(self.menubar) 33 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 34 | self.statusbar.setObjectName("statusbar") 35 | MainWindow.setStatusBar(self.statusbar) 36 | self.actionNew = QtWidgets.QAction(MainWindow) 37 | self.actionNew.setObjectName("actionNew") 38 | self.actionExit = QtWidgets.QAction(MainWindow) 39 | self.actionExit.setObjectName("actionExit") 40 | self.menuFile.addAction(self.actionNew) 41 | self.menuFile.addAction(self.actionExit) 42 | self.menubar.addAction(self.menuFile.menuAction()) 43 | 44 | self.retranslateUi(MainWindow) 45 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 46 | 47 | def retranslateUi(self, MainWindow): 48 | _translate = QtCore.QCoreApplication.translate 49 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 50 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1")) 51 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2")) 52 | self.menuFile.setTitle(_translate("MainWindow", "File")) 53 | self.actionNew.setText(_translate("MainWindow", "New")) 54 | self.actionExit.setText(_translate("MainWindow", "Exit")) 55 | 56 | 57 | if __name__ == "__main__": 58 | import sys 59 | app = QtWidgets.QApplication(sys.argv) 60 | MainWindow = QtWidgets.QMainWindow() 61 | ui = Ui_MainWindow() 62 | ui.setupUi(MainWindow) 63 | MainWindow.show() 64 | sys.exit(app.exec_()) 65 | 66 | -------------------------------------------------------------------------------- /Ch09_Code/Control_Frameworks.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 15, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | #================================================================== 7 | import tkinter as tk 8 | from tkinter import ttk 9 | from tkinter import scrolledtext 10 | from threading import Thread 11 | 12 | win = tk.Tk() 13 | 14 | win.title("Python GUI") 15 | aLabel = ttk.Label(win, text="A Label") 16 | aLabel.grid(column=0, row=0) 17 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 18 | name = tk.StringVar() 19 | nameEntered = ttk.Entry(win, width=12, textvariable=name) 20 | nameEntered.grid(column=0, row=1) 21 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 22 | number = tk.StringVar() 23 | numberChosen = ttk.Combobox(win, width=12, textvariable=number) 24 | numberChosen['values'] = (1, 2, 4, 42, 100) 25 | numberChosen.grid(column=1, row=1) 26 | numberChosen.current(0) 27 | scrolW = 30 28 | scrolH = 3 29 | scr = scrolledtext.ScrolledText(win, width=scrolW, height=scrolH, wrap=tk.WORD) 30 | scr.grid(column=0, sticky='WE', columnspan=3) 31 | nameEntered.focus() 32 | 33 | #================================================================== 34 | ## working 35 | def wxPythonApp(): 36 | import wx 37 | app = wx.App() 38 | frame = wx.Frame(None, -1, "wxPython GUI", size=(200,150)) 39 | frame.SetBackgroundColour('white') 40 | frame.CreateStatusBar() 41 | menu= wx.Menu() 42 | menu.Append(wx.ID_ABOUT, "About", "wxPython GUI") 43 | menuBar = wx.MenuBar() 44 | menuBar.Append(menu,"File") 45 | frame.SetMenuBar(menuBar) 46 | frame.Show() 47 | 48 | runT = Thread(target=app.MainLoop) 49 | runT.setDaemon(True) 50 | runT.start() 51 | print(runT) 52 | print('createThread():', runT.isAlive()) 53 | 54 | action = ttk.Button(win, text="Call wxPython GUI", command=wxPythonApp) 55 | action.grid(column=2, row=1) 56 | #================================================================== 57 | 58 | 59 | ## NOT working - CRASHES Python ----------------------------------- 60 | # def wxPythonApp(): 61 | # import wx 62 | # app = wx.App() 63 | # frame = wx.Frame(None, -1, "wxPython GUI", size=(200,150)) 64 | # frame.SetBackgroundColour('white') 65 | # frame.CreateStatusBar() 66 | # menu= wx.Menu() 67 | # menu.Append(wx.ID_ABOUT, "About", "wxPython GUI") 68 | # menuBar = wx.MenuBar() 69 | # menuBar.Append(menu,"File") 70 | # frame.SetMenuBar(menuBar) 71 | # frame.Show() 72 | # app.MainLoop() 73 | # 74 | # def tryRunInThread(): 75 | # runT = Thread(target=wxPythonApp) 76 | # runT.setDaemon(True) 77 | # runT.start() 78 | # print(runT) 79 | # print('createThread():', runT.isAlive()) 80 | # 81 | # action = ttk.Button(win, text="Call wxPython GUI", command=tryRunInThread) 82 | # action.grid(column=2, row=1) 83 | ##----------------------------------------------------------------- 84 | 85 | #====================== 86 | # Start GUI 87 | #====================== 88 | win.mainloop() -------------------------------------------------------------------------------- /Ch08_Code/LanguageResources.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 9, 2019 3 | Ch08 4 | @author: Burkhard 5 | ''' 6 | 7 | class I18N(): 8 | '''Internationalization''' 9 | def __init__(self, language): 10 | if language == 'en': self.resourceLanguageEnglish() 11 | elif language == 'de': self.resourceLanguageGerman() 12 | else: raise NotImplementedError('Unsupported language.') 13 | 14 | def resourceLanguageEnglish(self): 15 | self.title = "Python Graphical User Interface" 16 | 17 | self.file = "File" 18 | self.new = "New" 19 | self.exit = "Exit" 20 | self.help = "Help" 21 | self.about = "About" 22 | 23 | self.WIDGET_LABEL = ' Widgets Frame ' 24 | 25 | self.disabled = "Disabled" 26 | self.unChecked = "UnChecked" 27 | self.toggle = "Toggle" 28 | 29 | # Radiobutton list 30 | self.colors = ["Blue", "Gold", "Red"] 31 | self.colorsIn = ["in Blue", "in Gold", "in Red"] 32 | 33 | self.labelsFrame = ' Labels within a Frame ' 34 | self.chooseNumber = "Choose a number:" 35 | self.label2 = "Label 2" 36 | 37 | self.timeZones = "All Time Zones" 38 | self.localZone = "Local Zone" 39 | self.getTime = "New York" 40 | 41 | self.mgrFiles = ' Manage Files ' 42 | 43 | self.browseTo = "Browse to File..." 44 | self.copyTo = "Copy File To : " 45 | 46 | 47 | def resourceLanguageGerman(self): 48 | self.title = 'Python Grafische Benutzeroberflaeche' # w/out umlaut 49 | # self.title = 'Python Grafische Benutzeroberfl' + "\u00E4" + 'che' # with umlaut via Unicode 50 | self.title = 'Python Grafische Benutzeroberfläche' # with umlaut UTF-8 51 | 52 | self.file = "Datei" 53 | self.new = "Neu" 54 | self.exit = "Schliessen" 55 | self.help = "Hilfe" 56 | self.about = "\u00DC" + "ber" 57 | self.about = "Über" 58 | 59 | self.WIDGET_LABEL = ' Widgets Rahmen ' 60 | 61 | self.disabled = "Deaktiviert" 62 | self.unChecked = "Nicht Markiert" 63 | self.toggle = "Markieren" 64 | 65 | # Radiobutton list 66 | self.colors = ["Blau", "Gold", "Rot"] 67 | self.colorsIn = ["in Blau", "in Gold", "in Rot"] 68 | 69 | self.labelsFrame = ' Etiketten im Rahmen ' 70 | self.chooseNumber = "Waehle eine Nummer:" 71 | self.label2 = "Etikette 2" 72 | 73 | self.timeZones = "Alle Zeitzonen" 74 | self.localZone = "Lokale Zone" 75 | self.getTime = "Zeit" 76 | 77 | self.mgrFiles = ' Dateien Organisieren ' 78 | 79 | self.browseTo = "Waehle eine Datei... " 80 | self.copyTo = "Kopiere Datei zu : " 81 | 82 | #================================================= 83 | if __name__ == '__main__': 84 | language = 'en' 85 | inst = I18N(language) 86 | print(inst.title) 87 | 88 | language = 'de' 89 | inst = I18N(language) 90 | print(inst.title) 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Ch09_Code/Communicate.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 15, 2019 3 | @author: Burkhard A. Meier 4 | ''' 5 | 6 | #================================================================== 7 | import tkinter as tk 8 | from tkinter import ttk 9 | from threading import Thread 10 | 11 | win = tk.Tk() 12 | win.title("Python GUI") 13 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 14 | 15 | name = tk.StringVar() 16 | nameEntered = ttk.Entry(win, width=12, textvariable=name) 17 | nameEntered.grid(column=0, row=1) 18 | nameEntered.focus() 19 | 20 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 21 | number = tk.StringVar() 22 | numberChosen = ttk.Combobox(win, width=12, textvariable=number) 23 | numberChosen['values'] = (1, 2, 4, 42, 100) 24 | numberChosen.grid(column=1, row=1) 25 | numberChosen.current(0) 26 | 27 | text = tk.Text(win, height=10, width=40, borderwidth=2, wrap='word') 28 | text.grid(column=0, sticky='WE', columnspan=3) 29 | 30 | #================================================================== 31 | from multiprocessing import Queue 32 | # from queue import Queue 33 | sharedQueue = Queue() 34 | dataInQueue = False 35 | 36 | def putDataIntoQueue(data): 37 | global dataInQueue 38 | dataInQueue = True 39 | sharedQueue.put(data) 40 | 41 | def readDataFromQueue(): 42 | global dataInQueue 43 | dataInQueue = False 44 | return sharedQueue.get() 45 | 46 | #================================================================== 47 | import wx 48 | class GUI(wx.Panel): 49 | def __init__(self, parent): 50 | wx.Panel.__init__(self, parent) 51 | parent.CreateStatusBar() 52 | menu= wx.Menu() 53 | menu.Append(wx.ID_ABOUT, "About", "wxPython GUI") 54 | menuBar = wx.MenuBar() 55 | menuBar.Append(menu, "File") 56 | parent.SetMenuBar(menuBar) 57 | button = wx.Button(self, label="Print", pos=(0,60)) 58 | self.Bind(wx.EVT_BUTTON, self.writeToSharedQueue, button) 59 | self.textBox = wx.TextCtrl(self, size=(280,50), style=wx.TE_MULTILINE) 60 | 61 | #----------------------------------------------------------------- 62 | def writeToSharedQueue(self, event): 63 | self.textBox.AppendText( 64 | "The Print Button has been clicked!\n") 65 | putDataIntoQueue('Hi from wxPython via Shared Queue.\n') 66 | if dataInQueue: 67 | data = readDataFromQueue() 68 | self.textBox.AppendText(data) 69 | 70 | text.insert('0.0', data) # insert data into tkinter GUI 71 | 72 | #================================================================== 73 | def wxPythonApp(): 74 | app = wx.App() 75 | frame = wx.Frame( 76 | None, title="Python GUI using wxPython", size=(300,180)) 77 | GUI(frame) 78 | frame.Show() 79 | runT = Thread(target=app.MainLoop) 80 | runT.setDaemon(True) 81 | runT.start() 82 | print(runT) 83 | print('createThread():', runT.isAlive()) 84 | 85 | #================================================================== 86 | action = ttk.Button(win, text="Call wxPython GUI", command=wxPythonApp) 87 | action.grid(column=2, row=1) 88 | 89 | #====================== 90 | # Start GUI 91 | #====================== 92 | win.mainloop() -------------------------------------------------------------------------------- /Ch11_Code/GUI_DesignPattern.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | import tkinter as tk 8 | from tkinter import ttk 9 | from tkinter import scrolledtext 10 | from tkinter import Menu 11 | 12 | class ButtonFactory(): 13 | def createButton(self, type_): 14 | return buttonTypes[type_]() 15 | 16 | class ButtonBase(): 17 | relief ='flat' 18 | foreground ='white' 19 | def getButtonConfig(self): 20 | return self.relief, self.foreground 21 | 22 | class ButtonRidge(ButtonBase): 23 | relief ='ridge' 24 | foreground ='red' 25 | 26 | class ButtonSunken(ButtonBase): 27 | relief ='sunken' 28 | foreground ='blue' 29 | 30 | class ButtonGroove(ButtonBase): 31 | relief ='groove' 32 | foreground ='green' 33 | 34 | buttonTypes = [ButtonRidge, ButtonSunken, ButtonGroove] 35 | 36 | class OOP(): 37 | def __init__(self): 38 | self.win = tk.Tk() 39 | self.win.title("Python GUI") 40 | self.createWidgets() 41 | 42 | def createWidgets(self): 43 | tabControl = ttk.Notebook(self.win) 44 | tab1 = ttk.Frame(tabControl) 45 | tabControl.add(tab1, text='Tab 1') 46 | tabControl.pack(expand=1, fill="both") 47 | self.monty = ttk.LabelFrame(tab1, text=' Monty Python ') 48 | self.monty.grid(column=0, row=0, padx=8, pady=4) 49 | 50 | scr = scrolledtext.ScrolledText(self.monty, width=30, height=3, wrap=tk.WORD) 51 | scr.grid(column=0, row=3, sticky='WE', columnspan=3) 52 | 53 | menuBar = Menu(tab1) 54 | self.win.config(menu=menuBar) 55 | fileMenu = Menu(menuBar, tearoff=0) 56 | menuBar.add_cascade(label="File", menu=fileMenu) 57 | helpMenu = Menu(menuBar, tearoff=0) 58 | menuBar.add_cascade(label="Help", menu=helpMenu) 59 | 60 | self.createButtons() 61 | 62 | 63 | def createButtons(self): 64 | 65 | factory = ButtonFactory() 66 | 67 | # Button 1 68 | rel = factory.createButton(0).getButtonConfig()[0] 69 | fg = factory.createButton(0).getButtonConfig()[1] 70 | action = tk.Button(self.monty, text="Button "+str(0+1), relief=rel, foreground=fg) 71 | action.grid(column=0, row=1) 72 | 73 | # Button 2 74 | rel = factory.createButton(1).getButtonConfig()[0] 75 | fg = factory.createButton(1).getButtonConfig()[1] 76 | action = tk.Button(self.monty, text="Button "+str(1+1), relief=rel, foreground=fg) 77 | action.grid(column=1, row=1) 78 | 79 | # Button 3 80 | rel = factory.createButton(2).getButtonConfig()[0] 81 | fg = factory.createButton(2).getButtonConfig()[1] 82 | action = tk.Button(self.monty, text="Button "+str(2+1), relief=rel, foreground=fg) 83 | action.grid(column=2, row=1) 84 | 85 | # # using a loop to do the above 86 | # for idx in range(len(buttonTypes)): 87 | # rel = factory.createButton(idx).getButtonConfig()[0] 88 | # fg = factory.createButton(idx).getButtonConfig()[1] 89 | # 90 | # action = tk.Button(self.monty, text="Button "+str(idx+1), relief=rel, foreground=fg) 91 | # action.grid(column=idx, row=1) 92 | 93 | #========================== 94 | oop = OOP() 95 | oop.win.mainloop() 96 | 97 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_radiobutton_widget.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | 12 | # Create instance 13 | win = tk.Tk() 14 | 15 | # Add a title 16 | win.title("Python GUI") 17 | 18 | # Modify adding a Label 19 | a_label = ttk.Label(win, text="A Label") 20 | a_label.grid(column=0, row=0) 21 | 22 | # Modified Button Click Function 23 | def click_me(): 24 | action.configure(text='Hello ' + name.get() + ' ' + 25 | number_chosen.get()) 26 | 27 | # Changing our Label 28 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 29 | 30 | # Adding a Textbox Entry widget 31 | name = tk.StringVar() 32 | name_entered = ttk.Entry(win, width=12, textvariable=name) 33 | name_entered.grid(column=0, row=1) 34 | 35 | # Adding a Button 36 | action = ttk.Button(win, text="Click Me!", command=click_me) 37 | action.grid(column=2, row=1) # <= change column to 2 38 | 39 | # Creating three checkbuttons 40 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 41 | number = tk.StringVar() 42 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 43 | number_chosen['values'] = (1, 2, 4, 42, 100) 44 | number_chosen.grid(column=1, row=1) 45 | number_chosen.current(0) 46 | 47 | chVarDis = tk.IntVar() 48 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 49 | check1.select() 50 | check1.grid(column=0, row=4, sticky=tk.W) 51 | 52 | chVarUn = tk.IntVar() 53 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 54 | check2.deselect() 55 | check2.grid(column=1, row=4, sticky=tk.W) 56 | 57 | chVarEn = tk.IntVar() 58 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 59 | check3.deselect() 60 | check3.grid(column=2, row=4, sticky=tk.W) 61 | 62 | # GUI Callback function 63 | def checkCallback(*ignoredArgs): 64 | # only enable one checkbutton 65 | if chVarUn.get(): check3.configure(state='disabled') 66 | else: check3.configure(state='normal') 67 | if chVarEn.get(): check2.configure(state='disabled') 68 | else: check2.configure(state='normal') 69 | 70 | # trace the state of the two checkbuttons 71 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 72 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | 74 | # Radiobutton Globals 75 | COLOR1 = "Blue" 76 | COLOR2 = "Gold" 77 | COLOR3 = "Red" 78 | 79 | # Radiobutton Callback 80 | def radCall(): 81 | radSel=radVar.get() 82 | if radSel == 1: win.configure(background=COLOR1) 83 | elif radSel == 2: win.configure(background=COLOR2) 84 | elif radSel == 3: win.configure(background=COLOR3) 85 | 86 | # create three Radiobuttons using one variable 87 | radVar = tk.IntVar() 88 | 89 | rad1 = tk.Radiobutton(win, text=COLOR1, variable=radVar, value=1, command=radCall) 90 | rad1.grid(column=0, row=5, sticky=tk.W, columnspan=3) 91 | 92 | rad2 = tk.Radiobutton(win, text=COLOR2, variable=radVar, value=2, command=radCall) 93 | rad2.grid(column=1, row=5, sticky=tk.W, columnspan=3) 94 | 95 | rad3 = tk.Radiobutton(win, text=COLOR3, variable=radVar, value=3, command=radCall) 96 | rad3.grid(column=2, row=5, sticky=tk.W, columnspan=3) 97 | 98 | name_entered.focus() # Place cursor into name Entry 99 | #====================== 100 | # Start GUI 101 | #====================== 102 | win.mainloop() -------------------------------------------------------------------------------- /Ch10_Code/Designer_Second_UI_layout_button.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 0 22 | 391 23 | 241 24 | 25 | 26 | 27 | 28 | Tab 1 29 | 30 | 31 | 32 | 33 | 20 34 | 120 35 | 361 36 | 80 37 | 38 | 39 | 40 | 41 | 42 | 43 | PushButton 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 20 53 | 20 54 | 160 55 | 80 56 | 57 | 58 | 59 | 60 | 61 | 62 | TextLabel 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Tab 2 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 0 80 | 0 81 | 400 82 | 21 83 | 84 | 85 | 86 | 87 | File 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | New 98 | 99 | 100 | 101 | 102 | Exit 103 | 104 | 105 | 106 | 107 | 108 | 109 | pushButton 110 | clicked() 111 | label 112 | clear() 113 | 114 | 115 | 78 116 | 195 117 | 118 | 119 | 59 120 | 104 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /Ch10_Code/Designer_Second_UI_layout.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'Designer_Second_UI_layout.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_MainWindow(object): 12 | def setupUi(self, MainWindow): 13 | MainWindow.setObjectName("MainWindow") 14 | MainWindow.resize(400, 300) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) 18 | self.tabWidget.setGeometry(QtCore.QRect(0, 0, 391, 241)) 19 | self.tabWidget.setObjectName("tabWidget") 20 | self.tab = QtWidgets.QWidget() 21 | self.tab.setObjectName("tab") 22 | self.horizontalLayoutWidget = QtWidgets.QWidget(self.tab) 23 | self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 120, 361, 80)) 24 | self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") 25 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget) 26 | self.horizontalLayout.setContentsMargins(0, 0, 0, 0) 27 | self.horizontalLayout.setObjectName("horizontalLayout") 28 | self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.tab) 29 | self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(20, 20, 160, 80)) 30 | self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2") 31 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2) 32 | self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) 33 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 34 | self.tabWidget.addTab(self.tab, "") 35 | self.tab_2 = QtWidgets.QWidget() 36 | self.tab_2.setObjectName("tab_2") 37 | self.tabWidget.addTab(self.tab_2, "") 38 | MainWindow.setCentralWidget(self.centralwidget) 39 | self.menubar = QtWidgets.QMenuBar(MainWindow) 40 | self.menubar.setGeometry(QtCore.QRect(0, 0, 400, 21)) 41 | self.menubar.setObjectName("menubar") 42 | self.menuFile = QtWidgets.QMenu(self.menubar) 43 | self.menuFile.setObjectName("menuFile") 44 | MainWindow.setMenuBar(self.menubar) 45 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 46 | self.statusbar.setObjectName("statusbar") 47 | MainWindow.setStatusBar(self.statusbar) 48 | self.actionNew = QtWidgets.QAction(MainWindow) 49 | self.actionNew.setObjectName("actionNew") 50 | self.actionExit = QtWidgets.QAction(MainWindow) 51 | self.actionExit.setObjectName("actionExit") 52 | self.menuFile.addAction(self.actionNew) 53 | self.menuFile.addAction(self.actionExit) 54 | self.menubar.addAction(self.menuFile.menuAction()) 55 | 56 | self.retranslateUi(MainWindow) 57 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 58 | 59 | def retranslateUi(self, MainWindow): 60 | _translate = QtCore.QCoreApplication.translate 61 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 62 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1")) 63 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2")) 64 | self.menuFile.setTitle(_translate("MainWindow", "File")) 65 | self.actionNew.setText(_translate("MainWindow", "New")) 66 | self.actionExit.setText(_translate("MainWindow", "Exit")) 67 | 68 | 69 | if __name__ == "__main__": 70 | import sys 71 | app = QtWidgets.QApplication(sys.argv) 72 | MainWindow = QtWidgets.QMainWindow() 73 | ui = Ui_MainWindow() 74 | ui.setupUi(MainWindow) 75 | MainWindow.show() 76 | sys.exit(app.exec_()) 77 | 78 | -------------------------------------------------------------------------------- /Ch01_Code/GUI_scrolledtext_widget.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | # Radiobutton Globals 76 | COLOR1 = "Blue" 77 | COLOR2 = "Gold" 78 | COLOR3 = "Red" 79 | 80 | # Radiobutton Callback 81 | def radCall(): 82 | radSel=radVar.get() 83 | if radSel == 1: win.configure(background=COLOR1) 84 | elif radSel == 2: win.configure(background=COLOR2) 85 | elif radSel == 3: win.configure(background=COLOR3) 86 | 87 | # create three Radiobuttons using one variable 88 | radVar = tk.IntVar() 89 | 90 | rad1 = tk.Radiobutton(win, text=COLOR1, variable=radVar, value=1, command=radCall) 91 | rad1.grid(column=0, row=5, sticky=tk.W, columnspan=3) 92 | 93 | rad2 = tk.Radiobutton(win, text=COLOR2, variable=radVar, value=2, command=radCall) 94 | rad2.grid(column=1, row=5, sticky=tk.W, columnspan=3) 95 | 96 | rad3 = tk.Radiobutton(win, text=COLOR3, variable=radVar, value=3, command=radCall) 97 | rad3.grid(column=2, row=5, sticky=tk.W, columnspan=3) 98 | 99 | # Using a scrolled Text control 100 | scrol_w = 30 101 | scrol_h = 3 102 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 103 | scr.grid(column=0, columnspan=3) 104 | 105 | name_entered.focus() # Place cursor into name Entry 106 | #====================== 107 | # Start GUI 108 | #====================== 109 | win.mainloop() -------------------------------------------------------------------------------- /Ch01_Code/GUI_adding_widgets_in_loop.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Apr 30, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # First, we change our Radiobutton global variables into a list 77 | colors = ["Blue", "Gold", "Red"] 78 | 79 | # We have also changed the callback function to be zero-based, using the list 80 | # instead of module-level global variables 81 | # Radiobutton Callback 82 | def radCall(): 83 | radSel=radVar.get() 84 | if radSel == 0: win.configure(background=colors[0]) # now zero-based 85 | elif radSel == 1: win.configure(background=colors[1]) # and using list 86 | elif radSel == 2: win.configure(background=colors[2]) 87 | 88 | # create three Radiobuttons using one variable 89 | radVar = tk.IntVar() 90 | 91 | # Next we are selecting a non-existing index value for radVar 92 | radVar.set(99) 93 | 94 | # Now we are creating all three Radiobutton widgets within one loop 95 | for col in range(3): 96 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 97 | value=col, command=radCall) 98 | curRad.grid(column=col, row=5, sticky=tk.W) 99 | 100 | # Using a scrolled Text control 101 | scrol_w = 30 102 | scrol_h = 3 103 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 104 | scr.grid(column=0, columnspan=3) 105 | 106 | name_entered.focus() # Place cursor into name Entry 107 | 108 | #====================== 109 | # Start GUI 110 | #====================== 111 | win.mainloop() -------------------------------------------------------------------------------- /Ch10_Code/Designer_Second_UI_layout_button.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'Designer_Second_UI_layout_button.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_MainWindow(object): 12 | def setupUi(self, MainWindow): 13 | MainWindow.setObjectName("MainWindow") 14 | MainWindow.resize(400, 300) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) 18 | self.tabWidget.setGeometry(QtCore.QRect(0, 0, 391, 241)) 19 | self.tabWidget.setObjectName("tabWidget") 20 | self.tab = QtWidgets.QWidget() 21 | self.tab.setObjectName("tab") 22 | self.horizontalLayoutWidget = QtWidgets.QWidget(self.tab) 23 | self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 120, 361, 80)) 24 | self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") 25 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget) 26 | self.horizontalLayout.setContentsMargins(0, 0, 0, 0) 27 | self.horizontalLayout.setObjectName("horizontalLayout") 28 | self.pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget) 29 | self.pushButton.setObjectName("pushButton") 30 | self.horizontalLayout.addWidget(self.pushButton) 31 | self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.tab) 32 | self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(20, 20, 160, 80)) 33 | self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2") 34 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2) 35 | self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) 36 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 37 | self.label = QtWidgets.QLabel(self.horizontalLayoutWidget_2) 38 | self.label.setObjectName("label") 39 | self.horizontalLayout_2.addWidget(self.label) 40 | self.tabWidget.addTab(self.tab, "") 41 | self.tab_2 = QtWidgets.QWidget() 42 | self.tab_2.setObjectName("tab_2") 43 | self.tabWidget.addTab(self.tab_2, "") 44 | MainWindow.setCentralWidget(self.centralwidget) 45 | self.menubar = QtWidgets.QMenuBar(MainWindow) 46 | self.menubar.setGeometry(QtCore.QRect(0, 0, 400, 21)) 47 | self.menubar.setObjectName("menubar") 48 | self.menuFile = QtWidgets.QMenu(self.menubar) 49 | self.menuFile.setObjectName("menuFile") 50 | MainWindow.setMenuBar(self.menubar) 51 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 52 | self.statusbar.setObjectName("statusbar") 53 | MainWindow.setStatusBar(self.statusbar) 54 | self.actionNew = QtWidgets.QAction(MainWindow) 55 | self.actionNew.setObjectName("actionNew") 56 | self.actionExit = QtWidgets.QAction(MainWindow) 57 | self.actionExit.setObjectName("actionExit") 58 | self.menuFile.addAction(self.actionNew) 59 | self.menuFile.addAction(self.actionExit) 60 | self.menubar.addAction(self.menuFile.menuAction()) 61 | 62 | self.retranslateUi(MainWindow) 63 | self.pushButton.clicked.connect(self.label.clear) 64 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 65 | 66 | def retranslateUi(self, MainWindow): 67 | _translate = QtCore.QCoreApplication.translate 68 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 69 | self.pushButton.setText(_translate("MainWindow", "PushButton")) 70 | self.label.setText(_translate("MainWindow", "TextLabel")) 71 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1")) 72 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2")) 73 | self.menuFile.setTitle(_translate("MainWindow", "File")) 74 | self.actionNew.setText(_translate("MainWindow", "New")) 75 | self.actionExit.setText(_translate("MainWindow", "Exit")) 76 | 77 | 78 | if __name__ == "__main__": 79 | import sys 80 | app = QtWidgets.QApplication(sys.argv) 81 | MainWindow = QtWidgets.QMainWindow() 82 | ui = Ui_MainWindow() 83 | ui.setupUi(MainWindow) 84 | MainWindow.show() 85 | sys.exit(app.exec_()) 86 | 87 | -------------------------------------------------------------------------------- /Ch02_Code/GUI_arranging_labels_vertical.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # Using a scrolled Text control 77 | scrol_w = 30 78 | scrol_h = 3 79 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 80 | scr.grid(column=0, row=5, sticky='WE', columnspan=3) # now row=5 81 | 82 | # First, we change our Radiobutton global variables into a list 83 | colors = ["Blue", "Gold", "Red"] 84 | 85 | # We have also changed the callback function to be zero-based, using the list 86 | # instead of module-level global variables 87 | # Radiobutton Callback 88 | def radCall(): 89 | radSel=radVar.get() 90 | if radSel == 0: win.configure(background=colors[0]) # now zero-based 91 | elif radSel == 1: win.configure(background=colors[1]) # and using list 92 | elif radSel == 2: win.configure(background=colors[2]) 93 | 94 | # create three Radiobuttons using one variable 95 | radVar = tk.IntVar() 96 | 97 | # Next we are selecting a non-existing index value for radVar 98 | radVar.set(99) 99 | 100 | # Now we are creating all three Radiobutton widgets within one loop 101 | for col in range(3): 102 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 103 | value=col, command=radCall) 104 | curRad.grid(column=col, row=6, sticky=tk.W) # now row=6 105 | 106 | # Create a container to hold labels 107 | buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ') 108 | buttons_frame.grid(column=0, row=7) 109 | 110 | # Place labels into the container element - vertically 111 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0) 112 | ttk.Label(buttons_frame, text="Label2").grid(column=0, row=1) 113 | ttk.Label(buttons_frame, text="Label3").grid(column=0, row=2) 114 | 115 | name_entered.focus() # Place cursor into name Entry 116 | #====================== 117 | # Start GUI 118 | #====================== 119 | win.mainloop() 120 | -------------------------------------------------------------------------------- /Ch02_Code/GUI_arranging_labels.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # Using a scrolled Text control 77 | scrol_w = 30 78 | scrol_h = 3 79 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 80 | scr.grid(column=0, row=5, sticky='WE', columnspan=3) # now row=5 81 | 82 | # First, we change our Radiobutton global variables into a list 83 | colors = ["Blue", "Gold", "Red"] 84 | 85 | # We have also changed the callback function to be zero-based, using the list 86 | # instead of module-level global variables 87 | # Radiobutton Callback 88 | def radCall(): 89 | radSel=radVar.get() 90 | if radSel == 0: win.configure(background=colors[0]) # now zero-based 91 | elif radSel == 1: win.configure(background=colors[1]) # and using list 92 | elif radSel == 2: win.configure(background=colors[2]) 93 | 94 | # create three Radiobuttons using one variable 95 | radVar = tk.IntVar() 96 | 97 | # Next we are selecting a non-existing index value for radVar 98 | radVar.set(99) 99 | 100 | # Now we are creating all three Radiobutton widgets within one loop 101 | for col in range(3): 102 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 103 | value=col, command=radCall) 104 | curRad.grid(column=col, row=6, sticky=tk.W) # now row=6 105 | 106 | # Create a container to hold labels 107 | buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ') 108 | buttons_frame.grid(column=0, row=7) 109 | 110 | # Place labels into the container element 111 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0, sticky=tk.W) 112 | ttk.Label(buttons_frame, text="Label2").grid(column=1, row=0, sticky=tk.W) 113 | ttk.Label(buttons_frame, text="Label3").grid(column=2, row=0, sticky=tk.W) 114 | 115 | name_entered.focus() # Place cursor into name Entry 116 | #====================== 117 | # Start GUI 118 | #====================== 119 | win.mainloop() -------------------------------------------------------------------------------- /Ch02_Code/GUI_add_padding.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # Using a scrolled Text control 77 | scrol_w = 30 78 | scrol_h = 3 79 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 80 | scr.grid(column=0, row=5, sticky='WE', columnspan=3) # now row=5 81 | 82 | # First, we change our Radiobutton global variables into a list 83 | colors = ["Blue", "Gold", "Red"] 84 | 85 | # We have also changed the callback function to be zero-based, using the list 86 | # instead of module-level global variables 87 | # Radiobutton Callback 88 | def radCall(): 89 | radSel=radVar.get() 90 | if radSel == 0: win.configure(background=colors[0]) # now zero-based 91 | elif radSel == 1: win.configure(background=colors[1]) # and using list 92 | elif radSel == 2: win.configure(background=colors[2]) 93 | 94 | # create three Radiobuttons using one variable 95 | radVar = tk.IntVar() 96 | 97 | # Next we are selecting a non-existing index value for radVar 98 | radVar.set(99) 99 | 100 | # Now we are creating all three Radiobutton widgets within one loop 101 | for col in range(3): 102 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 103 | value=col, command=radCall) 104 | curRad.grid(column=col, row=6, sticky=tk.W) # now row=6 105 | 106 | # Create a container to hold labels 107 | buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ') 108 | buttons_frame.grid(column=0, row=7, padx=20, pady=40) # padx, pady 109 | 110 | # Place labels into the container element - vertically 111 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0) 112 | ttk.Label(buttons_frame, text="Label2").grid(column=0, row=1) 113 | ttk.Label(buttons_frame, text="Label3").grid(column=0, row=2) 114 | 115 | name_entered.focus() # Place cursor into name Entry 116 | #====================== 117 | # Start GUI 118 | #====================== 119 | win.mainloop() 120 | -------------------------------------------------------------------------------- /Ch02_Code/GUI_remove_sticky.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # Using a scrolled Text control 77 | scrol_w = 30 78 | scrol_h = 3 79 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 80 | #### scr.grid(column=0, row=5, sticky='WE', columnspan=3) 81 | scr.grid(column=0, row=5, columnspan=3) # sticky property removed 82 | 83 | 84 | # First, we change our Radiobutton global variables into a list 85 | colors = ["Blue", "Gold", "Red"] 86 | 87 | # We have also changed the callback function to be zero-based, using the list 88 | # instead of module-level global variables 89 | # Radiobutton Callback 90 | def radCall(): 91 | radSel=radVar.get() 92 | if radSel == 0: win.configure(background=colors[0]) # zero-based 93 | elif radSel == 1: win.configure(background=colors[1]) # using list 94 | elif radSel == 2: win.configure(background=colors[2]) 95 | 96 | # create three Radiobuttons using one variable 97 | radVar = tk.IntVar() 98 | 99 | # Next we are selecting a non-existing index value for radVar 100 | radVar.set(99) 101 | 102 | # Now we are creating all three Radiobutton widgets within one loop 103 | for col in range(3): 104 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 105 | value=col, command=radCall) 106 | curRad.grid(column=col, row=6, sticky=tk.W) # now row=6 107 | 108 | # Create a container to hold labels 109 | buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ') 110 | buttons_frame.grid(column=0, row=7) 111 | 112 | # Place labels into the container element 113 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0, sticky=tk.W) 114 | ttk.Label(buttons_frame, text="Label2").grid(column=1, row=0, sticky=tk.W) 115 | ttk.Label(buttons_frame, text="Label3").grid(column=2, row=0, sticky=tk.W) 116 | 117 | name_entered.focus() # Place cursor into name Entry 118 | #====================== 119 | # Start GUI 120 | #====================== 121 | win.mainloop() -------------------------------------------------------------------------------- /Ch02_Code/GUI_add_padding_loop.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # Using a scrolled Text control 77 | scrol_w = 30 78 | scrol_h = 3 79 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 80 | scr.grid(column=0, row=5, sticky='WE', columnspan=3) # now row=5 81 | 82 | # First, we change our Radiobutton global variables into a list 83 | colors = ["Blue", "Gold", "Red"] 84 | 85 | # We have also changed the callback function to be zero-based, using the list 86 | # instead of module-level global variables 87 | # Radiobutton Callback 88 | def radCall(): 89 | radSel=radVar.get() 90 | if radSel == 0: win.configure(background=colors[0]) # now zero-based 91 | elif radSel == 1: win.configure(background=colors[1]) # and using list 92 | elif radSel == 2: win.configure(background=colors[2]) 93 | 94 | # create three Radiobuttons using one variable 95 | radVar = tk.IntVar() 96 | 97 | # Next we are selecting a non-existing index value for radVar 98 | radVar.set(99) 99 | 100 | # Now we are creating all three Radiobutton widgets within one loop 101 | for col in range(3): 102 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 103 | value=col, command=radCall) 104 | curRad.grid(column=col, row=6, sticky=tk.W) # now row=6 105 | 106 | # Create a container to hold labels 107 | buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ') 108 | buttons_frame.grid(column=0, row=7, padx=20, pady=40) # padx, pady 109 | 110 | # Place labels into the container element - vertically 111 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0) 112 | ttk.Label(buttons_frame, text="Label2").grid(column=0, row=1) 113 | ttk.Label(buttons_frame, text="Label3").grid(column=0, row=2) 114 | 115 | for child in buttons_frame.winfo_children(): 116 | child.grid_configure(padx=8, pady=4) 117 | 118 | 119 | name_entered.focus() # Place cursor into name Entry 120 | #====================== 121 | # Start GUI 122 | #====================== 123 | win.mainloop() 124 | -------------------------------------------------------------------------------- /Ch02_Code/GUI_LabelFrame_column_one.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # Using a scrolled Text control 77 | scrol_w = 30 78 | scrol_h = 3 79 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 80 | #### scr.grid(column=0, row=5, sticky='WE', columnspan=3) 81 | scr.grid(column=0, row=5, columnspan=3) # sticky property removed 82 | 83 | 84 | # First, we change our Radiobutton global variables into a list 85 | colors = ["Blue", "Gold", "Red"] 86 | 87 | # We have also changed the callback function to be zero-based, using the list 88 | # instead of module-level global variables 89 | # Radiobutton Callback 90 | def radCall(): 91 | radSel=radVar.get() 92 | if radSel == 0: win.configure(background=colors[0]) # zero-based 93 | elif radSel == 1: win.configure(background=colors[1]) # using list 94 | elif radSel == 2: win.configure(background=colors[2]) 95 | 96 | # create three Radiobuttons using one variable 97 | radVar = tk.IntVar() 98 | 99 | # Next we are selecting a non-existing index value for radVar 100 | radVar.set(99) 101 | 102 | # Now we are creating all three Radiobutton widgets within one loop 103 | for col in range(3): 104 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 105 | value=col, command=radCall) 106 | curRad.grid(column=col, row=6, sticky=tk.W) # row=6 107 | 108 | # Create a container to hold labels 109 | buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ') 110 | buttons_frame.grid(column=0, row=7) 111 | # buttons_frame.grid(column=1, row=7) # now in col 1 112 | 113 | # Place labels into the container element 114 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0, sticky=tk.W) 115 | ttk.Label(buttons_frame, text="Label2").grid(column=1, row=0, sticky=tk.W) 116 | ttk.Label(buttons_frame, text="Label3").grid(column=2, row=0, sticky=tk.W) 117 | 118 | name_entered.focus() # Place cursor into name Entry 119 | #====================== 120 | # Start GUI 121 | #====================== 122 | win.mainloop() -------------------------------------------------------------------------------- /Ch02_Code/GUI_long_label.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # Using a scrolled Text control 77 | scrol_w = 30 78 | scrol_h = 3 79 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 80 | scr.grid(column=0, row=5, sticky='WE', columnspan=3) # row=5 81 | 82 | # First, we change our Radiobutton global variables into a list 83 | colors = ["Blue", "Gold", "Red"] 84 | 85 | # We have also changed the callback function to be zero-based, using the list 86 | # instead of module-level global variables 87 | # Radiobutton Callback 88 | def radCall(): 89 | radSel=radVar.get() 90 | if radSel == 0: win.configure(background=colors[0]) # zero-based 91 | elif radSel == 1: win.configure(background=colors[1]) # using list 92 | elif radSel == 2: win.configure(background=colors[2]) 93 | 94 | # create three Radiobuttons using one variable 95 | radVar = tk.IntVar() 96 | 97 | # Next we are selecting a non-existing index value for radVar 98 | radVar.set(99) 99 | 100 | # Now we are creating all three Radiobutton widgets within one loop 101 | for col in range(3): 102 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 103 | value=col, command=radCall) 104 | curRad.grid(column=col, row=6, sticky=tk.W) # row=6 105 | 106 | # Create a container to hold labels 107 | buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ') 108 | buttons_frame.grid(column=0, row=7, padx=20, pady=40) # padx, pady 109 | 110 | 111 | 112 | 113 | # Place labels into the container element - vertically with long label 114 | ttk.Label(buttons_frame, text="Label1 -- sooooo much loooonger...").grid(column=0, row=0) 115 | ttk.Label(buttons_frame, text="Label2").grid(column=0, row=1) 116 | ttk.Label(buttons_frame, text="Label3").grid(column=0, row=2) 117 | 118 | for child in buttons_frame.winfo_children(): 119 | child.grid_configure(padx=8, pady=4) 120 | 121 | name_entered.focus() # Place cursor into name Entry 122 | #====================== 123 | # Start GUI 124 | #====================== 125 | win.mainloop() 126 | -------------------------------------------------------------------------------- /Ch02_Code/GUI_remove_columnspan.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # Using a scrolled Text control 77 | scrol_w = 30 78 | scrol_h = 3 79 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 80 | #### scr.grid(column=0, row=5, sticky='WE', columnspan=3) 81 | #### scr.grid(column=0, row=5, columnspan=3) # sticky property removed 82 | scr.grid(column=0, row=5) # columnspan removed 83 | 84 | # First, we change our Radiobutton global variables into a list 85 | colors = ["Blue", "Gold", "Red"] 86 | 87 | # We have also changed the callback function to be zero-based, using the list 88 | # instead of module-level global variables 89 | # Radiobutton Callback 90 | def radCall(): 91 | radSel=radVar.get() 92 | if radSel == 0: win.configure(background=colors[0]) # zero-based 93 | elif radSel == 1: win.configure(background=colors[1]) # using list 94 | elif radSel == 2: win.configure(background=colors[2]) 95 | 96 | # create three Radiobuttons using one variable 97 | radVar = tk.IntVar() 98 | 99 | # Next we are selecting a non-existing index value for radVar 100 | radVar.set(99) 101 | 102 | # Now we are creating all three Radiobutton widgets within one loop 103 | for col in range(3): 104 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 105 | value=col, command=radCall) 106 | curRad.grid(column=col, row=6, sticky=tk.W) # now row=6 107 | 108 | # Create a container to hold labels 109 | buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ') 110 | buttons_frame.grid(column=0, row=7) 111 | 112 | # Place labels into the container element 113 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0, sticky=tk.W) 114 | ttk.Label(buttons_frame, text="Label2").grid(column=1, row=0, sticky=tk.W) 115 | ttk.Label(buttons_frame, text="Label3").grid(column=2, row=0, sticky=tk.W) 116 | 117 | name_entered.focus() # Place cursor into name Entry 118 | #====================== 119 | # Start GUI 120 | #====================== 121 | win.mainloop() -------------------------------------------------------------------------------- /Ch02_Code/GUI_embed_frames_align.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # We are creating a container frame to hold all other widgets 20 | mighty = ttk.LabelFrame(win, text=' Mighty Python ') 21 | mighty.grid(column=0, row=0, padx=8, pady=4) 22 | 23 | # Modify adding a Label using mighty as the parent instead of win 24 | a_label = ttk.Label(mighty, text="Enter a name:") 25 | a_label.grid(column=0, row=0) 26 | 27 | # Modified Button Click Function 28 | def click_me(): 29 | action.configure(text='Hello ' + name.get() + ' ' + 30 | number_chosen.get()) 31 | 32 | # Adding a Textbox Entry widget 33 | name = tk.StringVar() 34 | name_entered = ttk.Entry(mighty, width=12, textvariable=name) 35 | name_entered.grid(column=0, row=1) 36 | 37 | # Adding a Button 38 | action = ttk.Button(mighty, text="Click Me!", command=click_me) 39 | action.grid(column=2, row=1) # <= change column to 2 40 | 41 | # Creating three checkbuttons 42 | ttk.Label(mighty, text="Choose a number:").grid(column=1, row=0) 43 | number = tk.StringVar() 44 | number_chosen = ttk.Combobox(mighty, width=12, textvariable=number, state='readonly') 45 | number_chosen['values'] = (1, 2, 4, 42, 100) 46 | number_chosen.grid(column=1, row=1) 47 | number_chosen.current(0) 48 | 49 | chVarDis = tk.IntVar() 50 | check1 = tk.Checkbutton(mighty, text="Disabled", variable=chVarDis, state='disabled') 51 | check1.select() 52 | check1.grid(column=0, row=4, sticky=tk.W) 53 | 54 | chVarUn = tk.IntVar() 55 | check2 = tk.Checkbutton(mighty, text="UnChecked", variable=chVarUn) 56 | check2.deselect() 57 | check2.grid(column=1, row=4, sticky=tk.W) 58 | 59 | chVarEn = tk.IntVar() 60 | check3 = tk.Checkbutton(mighty, text="Enabled", variable=chVarEn) 61 | check3.deselect() 62 | check3.grid(column=2, row=4, sticky=tk.W) 63 | 64 | # GUI Callback function 65 | def checkCallback(*ignoredArgs): 66 | # only enable one checkbutton 67 | if chVarUn.get(): check3.configure(state='disabled') 68 | else: check3.configure(state='normal') 69 | if chVarEn.get(): check2.configure(state='disabled') 70 | else: check2.configure(state='normal') 71 | 72 | # trace the state of the two checkbuttons 73 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 75 | 76 | 77 | # Using a scrolled Text control 78 | scrol_w = 30 79 | scrol_h = 3 80 | scr = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) 81 | #### scr.grid(column=0, row=5, sticky='WE', columnspan=3) 82 | scr.grid(column=0, row=5, columnspan=3) # sticky property removed 83 | 84 | 85 | # First, we change our Radiobutton global variables into a list 86 | colors = ["Blue", "Gold", "Red"] 87 | 88 | # We have also changed the callback function to be zero-based, using the list 89 | # instead of module-level global variables 90 | # Radiobutton Callback 91 | def radCall(): 92 | radSel=radVar.get() 93 | if radSel == 0: win.configure(background=colors[0]) # zero-based 94 | elif radSel == 1: win.configure(background=colors[1]) # using list 95 | elif radSel == 2: win.configure(background=colors[2]) 96 | 97 | # create three Radiobuttons using one variable 98 | radVar = tk.IntVar() 99 | 100 | # Next we are selecting a non-existing index value for radVar 101 | radVar.set(99) 102 | 103 | # Now we are creating all three Radiobutton widgets within one loop 104 | for col in range(3): 105 | curRad = tk.Radiobutton(mighty, text=colors[col], variable=radVar, 106 | value=col, command=radCall) 107 | curRad.grid(column=col, row=6, sticky=tk.W) # row=6 108 | 109 | # Create a container to hold labels 110 | buttons_frame = ttk.LabelFrame(mighty, text=' Labels in a Frame ') 111 | buttons_frame.grid(column=0, row=7) 112 | 113 | # Place labels into the container element 114 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0, sticky=tk.W) 115 | ttk.Label(buttons_frame, text="Label2").grid(column=1, row=0, sticky=tk.W) 116 | ttk.Label(buttons_frame, text="Label3").grid(column=2, row=0, sticky=tk.W) 117 | 118 | name_entered.focus() # Place cursor into name Entry 119 | #====================== 120 | # Start GUI 121 | #====================== 122 | win.mainloop() -------------------------------------------------------------------------------- /Ch02_Code/GUI_embed_frames.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # We are creating a container frame to hold all other widgets 20 | mighty = ttk.LabelFrame(win, text=' Mighty Python ') 21 | mighty.grid(column=0, row=0, padx=8, pady=4) 22 | 23 | # Modify adding a Label using mighty as the parent instead of win 24 | a_label = ttk.Label(mighty, text="Enter a name:") 25 | a_label.grid(column=0, row=0) 26 | 27 | # Modified Button Click Function 28 | def click_me(): 29 | action.configure(text='Hello ' + name.get() + ' ' + 30 | number_chosen.get()) 31 | 32 | # Adding a Textbox Entry widget 33 | name = tk.StringVar() 34 | name_entered = ttk.Entry(mighty, width=12, textvariable=name) 35 | name_entered.grid(column=0, row=1) 36 | 37 | # Adding a Button 38 | action = ttk.Button(mighty, text="Click Me!", command=click_me) 39 | action.grid(column=2, row=1) # <= change column to 2 40 | 41 | # Creating three checkbuttons 42 | ttk.Label(mighty, text="Choose a number:").grid(column=1, row=0) 43 | number = tk.StringVar() 44 | number_chosen = ttk.Combobox(mighty, width=12, textvariable=number, state='readonly') 45 | number_chosen['values'] = (1, 2, 4, 42, 100) 46 | number_chosen.grid(column=1, row=1) 47 | number_chosen.current(0) 48 | 49 | chVarDis = tk.IntVar() 50 | check1 = tk.Checkbutton(mighty, text="Disabled", variable=chVarDis, state='disabled') 51 | check1.select() 52 | check1.grid(column=0, row=4, sticky=tk.W) 53 | 54 | chVarUn = tk.IntVar() 55 | check2 = tk.Checkbutton(mighty, text="UnChecked", variable=chVarUn) 56 | check2.deselect() 57 | check2.grid(column=1, row=4, sticky=tk.W) 58 | 59 | chVarEn = tk.IntVar() 60 | check3 = tk.Checkbutton(mighty, text="Enabled", variable=chVarEn) 61 | check3.deselect() 62 | check3.grid(column=2, row=4, sticky=tk.W) 63 | 64 | # GUI Callback function 65 | def checkCallback(*ignoredArgs): 66 | # only enable one checkbutton 67 | if chVarUn.get(): check3.configure(state='disabled') 68 | else: check3.configure(state='normal') 69 | if chVarEn.get(): check2.configure(state='disabled') 70 | else: check2.configure(state='normal') 71 | 72 | # trace the state of the two checkbuttons 73 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 75 | 76 | 77 | # Using a scrolled Text control 78 | scrol_w = 30 79 | scrol_h = 3 80 | scr = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) 81 | #### scr.grid(column=0, row=5, sticky='WE', columnspan=3) 82 | scr.grid(column=0, row=5, columnspan=3) # sticky property removed 83 | 84 | 85 | # First, we change our Radiobutton global variables into a list 86 | colors = ["Blue", "Gold", "Red"] 87 | 88 | # We have also changed the callback function to be zero-based, using the list 89 | # instead of module-level global variables 90 | # Radiobutton Callback 91 | def radCall(): 92 | radSel=radVar.get() 93 | if radSel == 0: win.configure(background=colors[0]) # zero-based 94 | elif radSel == 1: win.configure(background=colors[1]) # using list 95 | elif radSel == 2: win.configure(background=colors[2]) 96 | 97 | # create three Radiobuttons using one variable 98 | radVar = tk.IntVar() 99 | 100 | # Next we are selecting a non-existing index value for radVar 101 | radVar.set(99) 102 | 103 | # Now we are creating all three Radiobutton widgets within one loop 104 | for col in range(3): 105 | curRad = tk.Radiobutton(mighty, text=colors[col], variable=radVar, 106 | value=col, command=radCall) 107 | curRad.grid(column=col, row=6, sticky=tk.W) # row=6 108 | 109 | # Create a container to hold labels 110 | buttons_frame = ttk.LabelFrame(mighty, text=' Labels in a Frame ') 111 | buttons_frame.grid(column=1, row=7) # now col 1 112 | 113 | # Place labels into the container element 114 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0, sticky=tk.W) 115 | ttk.Label(buttons_frame, text="Label2").grid(column=1, row=0, sticky=tk.W) 116 | ttk.Label(buttons_frame, text="Label3").grid(column=2, row=0, sticky=tk.W) 117 | 118 | name_entered.focus() # Place cursor into name Entry 119 | #====================== 120 | # Start GUI 121 | #====================== 122 | win.mainloop() -------------------------------------------------------------------------------- /Ch02_Code/GUI_embed_frames_align_west.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # We are creating a container frame to hold all other widgets 20 | mighty = ttk.LabelFrame(win, text=' Mighty Python ') 21 | mighty.grid(column=0, row=0, padx=8, pady=4) 22 | 23 | # Modify adding a Label using mighty as the parent instead of win 24 | a_label = ttk.Label(mighty, text="Enter a name:") 25 | a_label.grid(column=0, row=0, sticky='W') 26 | 27 | # Modified Button Click Function 28 | def click_me(): 29 | action.configure(text='Hello ' + name.get() + ' ' + 30 | number_chosen.get()) 31 | 32 | # Adding a Textbox Entry widget 33 | name = tk.StringVar() 34 | name_entered = ttk.Entry(mighty, width=12, textvariable=name) 35 | name_entered.grid(column=0, row=1) 36 | 37 | # Adding a Button 38 | action = ttk.Button(mighty, text="Click Me!", command=click_me) 39 | action.grid(column=2, row=1) # <= change column to 2 40 | 41 | # Creating three checkbuttons 42 | ttk.Label(mighty, text="Choose a number:").grid(column=1, row=0) 43 | number = tk.StringVar() 44 | number_chosen = ttk.Combobox(mighty, width=12, textvariable=number, state='readonly') 45 | number_chosen['values'] = (1, 2, 4, 42, 100) 46 | number_chosen.grid(column=1, row=1) 47 | number_chosen.current(0) 48 | 49 | chVarDis = tk.IntVar() 50 | check1 = tk.Checkbutton(mighty, text="Disabled", variable=chVarDis, state='disabled') 51 | check1.select() 52 | check1.grid(column=0, row=4, sticky=tk.W) 53 | 54 | chVarUn = tk.IntVar() 55 | check2 = tk.Checkbutton(mighty, text="UnChecked", variable=chVarUn) 56 | check2.deselect() 57 | check2.grid(column=1, row=4, sticky=tk.W) 58 | 59 | chVarEn = tk.IntVar() 60 | check3 = tk.Checkbutton(mighty, text="Enabled", variable=chVarEn) 61 | check3.deselect() 62 | check3.grid(column=2, row=4, sticky=tk.W) 63 | 64 | # GUI Callback function 65 | def checkCallback(*ignoredArgs): 66 | # only enable one checkbutton 67 | if chVarUn.get(): check3.configure(state='disabled') 68 | else: check3.configure(state='normal') 69 | if chVarEn.get(): check2.configure(state='disabled') 70 | else: check2.configure(state='normal') 71 | 72 | # trace the state of the two checkbuttons 73 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 75 | 76 | 77 | # Using a scrolled Text control 78 | scrol_w = 30 79 | scrol_h = 3 80 | scr = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) 81 | #### scr.grid(column=0, row=5, sticky='WE', columnspan=3) 82 | scr.grid(column=0, row=5, columnspan=3) # sticky property removed 83 | 84 | 85 | # First, we change our Radiobutton global variables into a list 86 | colors = ["Blue", "Gold", "Red"] 87 | 88 | # We have also changed the callback function to be zero-based, using the list 89 | # instead of module-level global variables 90 | # Radiobutton Callback 91 | def radCall(): 92 | radSel=radVar.get() 93 | if radSel == 0: win.configure(background=colors[0]) # zero-based 94 | elif radSel == 1: win.configure(background=colors[1]) # using list 95 | elif radSel == 2: win.configure(background=colors[2]) 96 | 97 | # create three Radiobuttons using one variable 98 | radVar = tk.IntVar() 99 | 100 | # Next we are selecting a non-existing index value for radVar 101 | radVar.set(99) 102 | 103 | # Now we are creating all three Radiobutton widgets within one loop 104 | for col in range(3): 105 | curRad = tk.Radiobutton(mighty, text=colors[col], variable=radVar, 106 | value=col, command=radCall) 107 | curRad.grid(column=col, row=6, sticky=tk.W) # row=6 108 | 109 | # Create a container to hold labels 110 | buttons_frame = ttk.LabelFrame(mighty, text=' Labels in a Frame ') 111 | buttons_frame.grid(column=0, row=7) 112 | 113 | # Place labels into the container element 114 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0, sticky=tk.W) 115 | ttk.Label(buttons_frame, text="Label2").grid(column=1, row=0, sticky=tk.W) 116 | ttk.Label(buttons_frame, text="Label3").grid(column=2, row=0, sticky=tk.W) 117 | 118 | name_entered.focus() # Place cursor into name Entry 119 | #====================== 120 | # Start GUI 121 | #====================== 122 | win.mainloop() -------------------------------------------------------------------------------- /Ch02_Code/GUI_LabelFrame_no_name.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # Modify adding a Label 20 | a_label = ttk.Label(win, text="A Label") 21 | a_label.grid(column=0, row=0) 22 | 23 | # Modified Button Click Function 24 | def click_me(): 25 | action.configure(text='Hello ' + name.get() + ' ' + 26 | number_chosen.get()) 27 | 28 | # Changing our Label 29 | ttk.Label(win, text="Enter a name:").grid(column=0, row=0) 30 | 31 | # Adding a Textbox Entry widget 32 | name = tk.StringVar() 33 | name_entered = ttk.Entry(win, width=12, textvariable=name) 34 | name_entered.grid(column=0, row=1) 35 | 36 | # Adding a Button 37 | action = ttk.Button(win, text="Click Me!", command=click_me) 38 | action.grid(column=2, row=1) # <= change column to 2 39 | 40 | # Creating three checkbuttons 41 | ttk.Label(win, text="Choose a number:").grid(column=1, row=0) 42 | number = tk.StringVar() 43 | number_chosen = ttk.Combobox(win, width=12, textvariable=number, state='readonly') 44 | number_chosen['values'] = (1, 2, 4, 42, 100) 45 | number_chosen.grid(column=1, row=1) 46 | number_chosen.current(0) 47 | 48 | chVarDis = tk.IntVar() 49 | check1 = tk.Checkbutton(win, text="Disabled", variable=chVarDis, state='disabled') 50 | check1.select() 51 | check1.grid(column=0, row=4, sticky=tk.W) 52 | 53 | chVarUn = tk.IntVar() 54 | check2 = tk.Checkbutton(win, text="UnChecked", variable=chVarUn) 55 | check2.deselect() 56 | check2.grid(column=1, row=4, sticky=tk.W) 57 | 58 | chVarEn = tk.IntVar() 59 | check3 = tk.Checkbutton(win, text="Enabled", variable=chVarEn) 60 | check3.deselect() 61 | check3.grid(column=2, row=4, sticky=tk.W) 62 | 63 | # GUI Callback function 64 | def checkCallback(*ignoredArgs): 65 | # only enable one checkbutton 66 | if chVarUn.get(): check3.configure(state='disabled') 67 | else: check3.configure(state='normal') 68 | if chVarEn.get(): check2.configure(state='disabled') 69 | else: check2.configure(state='normal') 70 | 71 | # trace the state of the two checkbuttons 72 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 73 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | 75 | 76 | # Using a scrolled Text control 77 | scrol_w = 30 78 | scrol_h = 3 79 | scr = scrolledtext.ScrolledText(win, width=scrol_w, height=scrol_h, wrap=tk.WORD) 80 | scr.grid(column=0, row=5, sticky='WE', columnspan=3) # row=5 81 | 82 | # First, we change our Radiobutton global variables into a list 83 | colors = ["Blue", "Gold", "Red"] 84 | 85 | # We have also changed the callback function to be zero-based, using the list 86 | # instead of module-level global variables 87 | # Radiobutton Callback 88 | def radCall(): 89 | radSel=radVar.get() 90 | if radSel == 0: win.configure(background=colors[0]) # zero-based 91 | elif radSel == 1: win.configure(background=colors[1]) # using list 92 | elif radSel == 2: win.configure(background=colors[2]) 93 | 94 | # create three Radiobuttons using one variable 95 | radVar = tk.IntVar() 96 | 97 | # Next we are selecting a non-existing index value for radVar 98 | radVar.set(99) 99 | 100 | # Now we are creating all three Radiobutton widgets within one loop 101 | for col in range(3): 102 | curRad = tk.Radiobutton(win, text=colors[col], variable=radVar, 103 | value=col, command=radCall) 104 | curRad.grid(column=col, row=6, sticky=tk.W) # row=6 105 | # Create a container to hold labels 106 | # buttons_frame = ttk.LabelFrame(win, text=' Labels in a Frame ') 107 | # buttons_frame.grid(column=0, row=7, padx=20, pady=40) 108 | 109 | buttons_frame = ttk.LabelFrame(win, text='') # no LabelFrame name 110 | buttons_frame.grid(column=0, row=7) 111 | 112 | # buttons_frame.grid(column=1, row=7) # now in col 1 113 | 114 | # Place labels into the container element 115 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0) 116 | ttk.Label(buttons_frame, text="Label2").grid(column=0, row=1) 117 | ttk.Label(buttons_frame, text="Label3").grid(column=0, row=2) 118 | 119 | for child in buttons_frame.winfo_children(): 120 | child.grid_configure(padx=8, pady=4) 121 | 122 | name_entered.focus() # Place cursor into name Entry 123 | #====================== 124 | # Start GUI 125 | #====================== 126 | win.mainloop() 127 | -------------------------------------------------------------------------------- /Ch02_Code/GUI_embed_frames_align_entry_west.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on May 1, 2019 3 | 4 | @author: Burkhard A. Meier 5 | ''' 6 | #====================== 7 | # imports 8 | #====================== 9 | import tkinter as tk 10 | from tkinter import ttk 11 | from tkinter import scrolledtext 12 | 13 | # Create instance 14 | win = tk.Tk() 15 | 16 | # Add a title 17 | win.title("Python GUI") 18 | 19 | # We are creating a container frame to hold all other widgets 20 | mighty = ttk.LabelFrame(win, text=' Mighty Python ') 21 | mighty.grid(column=0, row=0, padx=8, pady=4) 22 | 23 | # Modify adding a Label using mighty as the parent instead of win 24 | a_label = ttk.Label(mighty, text="Enter a name:") 25 | a_label.grid(column=0, row=0, sticky='W') 26 | 27 | # Modified Button Click Function 28 | def click_me(): 29 | action.configure(text='Hello ' + name.get() + ' ' + 30 | number_chosen.get()) 31 | 32 | # Adding a Textbox Entry widget 33 | name = tk.StringVar() 34 | name_entered = ttk.Entry(mighty, width=12, textvariable=name) 35 | name_entered.grid(column=0, row=1, sticky=tk.W) # align left/West 36 | 37 | # Adding a Button 38 | action = ttk.Button(mighty, text="Click Me!", command=click_me) 39 | action.grid(column=2, row=1) 40 | 41 | # Creating three checkbuttons 42 | ttk.Label(mighty, text="Choose a number:").grid(column=1, row=0) 43 | number = tk.StringVar() 44 | number_chosen = ttk.Combobox(mighty, width=12, textvariable=number, state='readonly') 45 | number_chosen['values'] = (1, 2, 4, 42, 100) 46 | number_chosen.grid(column=1, row=1) 47 | number_chosen.current(0) 48 | 49 | chVarDis = tk.IntVar() 50 | check1 = tk.Checkbutton(mighty, text="Disabled", variable=chVarDis, state='disabled') 51 | check1.select() 52 | check1.grid(column=0, row=4, sticky=tk.W) 53 | 54 | chVarUn = tk.IntVar() 55 | check2 = tk.Checkbutton(mighty, text="UnChecked", variable=chVarUn) 56 | check2.deselect() 57 | check2.grid(column=1, row=4, sticky=tk.W) 58 | 59 | chVarEn = tk.IntVar() 60 | check3 = tk.Checkbutton(mighty, text="Enabled", variable=chVarEn) 61 | check3.deselect() 62 | check3.grid(column=2, row=4, sticky=tk.W) 63 | 64 | # GUI Callback function 65 | def checkCallback(*ignoredArgs): 66 | # only enable one checkbutton 67 | if chVarUn.get(): check3.configure(state='disabled') 68 | else: check3.configure(state='normal') 69 | if chVarEn.get(): check2.configure(state='disabled') 70 | else: check2.configure(state='normal') 71 | 72 | # trace the state of the two checkbuttons 73 | chVarUn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 74 | chVarEn.trace('w', lambda unused0, unused1, unused2 : checkCallback()) 75 | 76 | 77 | # Using a scrolled Text control 78 | scrol_w = 30 79 | scrol_h = 3 80 | scr = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) 81 | #### scr.grid(column=0, row=5, sticky='WE', columnspan=3) 82 | scr.grid(column=0, row=5, columnspan=3) # sticky property removed 83 | 84 | 85 | # First, we change our Radiobutton global variables into a list 86 | colors = ["Blue", "Gold", "Red"] 87 | 88 | # We have also changed the callback function to be zero-based, using the list 89 | # instead of module-level global variables 90 | # Radiobutton Callback 91 | def radCall(): 92 | radSel=radVar.get() 93 | if radSel == 0: win.configure(background=colors[0]) # zero-based 94 | elif radSel == 1: win.configure(background=colors[1]) # using list 95 | elif radSel == 2: win.configure(background=colors[2]) 96 | 97 | # create three Radiobuttons using one variable 98 | radVar = tk.IntVar() 99 | 100 | # Next we are selecting a non-existing index value for radVar 101 | radVar.set(99) 102 | 103 | # Now we are creating all three Radiobutton widgets within one loop 104 | for col in range(3): 105 | curRad = tk.Radiobutton(mighty, text=colors[col], variable=radVar, 106 | value=col, command=radCall) 107 | curRad.grid(column=col, row=6, sticky=tk.W) # row=6 108 | 109 | # Create a container to hold labels 110 | buttons_frame = ttk.LabelFrame(mighty, text=' Labels in a Frame ') 111 | buttons_frame.grid(column=0, row=7) 112 | 113 | # Place labels into the container element 114 | ttk.Label(buttons_frame, text="Label1").grid(column=0, row=0, sticky=tk.W) 115 | ttk.Label(buttons_frame, text="Label2").grid(column=1, row=0, sticky=tk.W) 116 | ttk.Label(buttons_frame, text="Label3").grid(column=2, row=0, sticky=tk.W) 117 | 118 | name_entered.focus() # Place cursor into name Entry 119 | #====================== 120 | # Start GUI 121 | #====================== 122 | win.mainloop() -------------------------------------------------------------------------------- /Ch11_Code/GUI_FallDown.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | #====================== 8 | # imports 9 | #====================== 10 | import tkinter as tk 11 | from tkinter import ttk 12 | from tkinter import messagebox 13 | 14 | #----------------------------------------------- 15 | class ToolTip(object): 16 | def __init__(self, widget): 17 | self.widget = widget 18 | self.tipwindow = None 19 | self.id = None 20 | self.x = self.y = 0 21 | 22 | def showtip(self, text): 23 | "Display text in a ToolTip window" 24 | self.text = text 25 | if self.tipwindow or not self.text: return 26 | try: 27 | x, y, _cx, cy = self.widget.bbox("insert") 28 | x = x + self.widget.winfo_rootx() + 25 29 | y = y + cy + self.widget.winfo_rooty() +25 30 | self.tipwindow = tw = tk.Toplevel(self.widget) 31 | tw.wm_overrideredirect(1) 32 | tw.wm_geometry("+%d+%d" % (x, y)) 33 | label = tk.Label(tw, text=self.text, justify=tk.LEFT, 34 | background="#ffffe0", relief=tk.SOLID, borderwidth=1, 35 | font=("tahoma", "8", "normal")) 36 | label.pack(ipadx=1) 37 | except: pass 38 | 39 | def hidetip(self): 40 | tw = self.tipwindow 41 | self.tipwindow = None 42 | if tw: 43 | tw.destroy() 44 | 45 | #=================================================================== 46 | def createToolTip(widget, text): 47 | toolTip = ToolTip(widget) 48 | def enter(event): toolTip.showtip(text) 49 | def leave(event): toolTip.hidetip() 50 | widget.bind('', enter) 51 | widget.bind('', leave) 52 | 53 | 54 | #====================== 55 | # Create instance 56 | #====================== 57 | win = tk.Tk() 58 | 59 | #====================== 60 | # Add a title 61 | #====================== 62 | win.title("Python GUI") 63 | 64 | #========================= 65 | # Disable resizing the GUI 66 | #========================= 67 | win.resizable(0,0) 68 | 69 | #=============================================================================== 70 | # Adding a LabelFrame, Textbox (Entry) and Combobox 71 | #=============================================================================== 72 | lFrame = ttk.LabelFrame(win, text="Python GUI Programming Cookbook") 73 | lFrame.grid(column=0, row=0, sticky='WE', padx=10, pady=10) 74 | 75 | #=============================================================================== 76 | # Labels 77 | #=============================================================================== 78 | ttk.Label(lFrame, text="Enter a name:").grid(column=0, row=0) 79 | ttk.Label(lFrame, text="Choose a number:").grid(column=1, row=0, sticky=tk.W) 80 | 81 | #=============================================================================== 82 | # Buttons click command 83 | #=============================================================================== 84 | def clickMe(name, number): 85 | messagebox.showinfo('Information Message Box', 'Hello ' + name + \ 86 | ', your number is: ' + number) 87 | 88 | #=============================================================================== 89 | # Creating several controls in a loop 90 | #=============================================================================== 91 | names = ['name0', 'name1', 'name2'] 92 | nameEntries = ['nameEntry0', 'nameEntry1', 'nameEntry2'] 93 | 94 | numbers = ['number0', 'number1', 'number2'] 95 | numberEntries = ['numberEntry0', 'numberEntry1', 'numberEntry2'] 96 | 97 | buttons = [] 98 | 99 | for idx in range(3): 100 | names[idx] = tk.StringVar() 101 | nameEntries[idx] = ttk.Entry(lFrame, width=12, textvariable=names[idx]) 102 | nameEntries[idx].grid(column=0, row=idx+1) 103 | nameEntries[idx].delete(0, tk.END) 104 | nameEntries[idx].insert(0, '') 105 | 106 | numbers[idx] = tk.StringVar() 107 | numberEntries[idx] = ttk.Combobox(lFrame, width=14, textvariable=numbers[idx]) 108 | numberEntries[idx]['values'] = (1+idx, 2+idx, 4+idx, 42+idx, 100+idx) 109 | numberEntries[idx].grid(column=1, row=idx+1) 110 | numberEntries[idx].current(0) 111 | 112 | button = ttk.Button(lFrame, text="Click Me "+str(idx+1), command=lambda idx=idx: clickMe(names[idx].get(), numbers[idx].get())) 113 | button.grid(column=2, row=idx+1, sticky=tk.W) 114 | buttons.append(button) 115 | 116 | # Add Tooltips to more widgets 117 | createToolTip(nameEntries[idx], 'This is an Entry widget.') 118 | createToolTip(numberEntries[idx], 'This is a DropDown widget.') 119 | createToolTip(buttons[idx], 'This is a Button widget.') 120 | 121 | #====================== 122 | # Start GUI 123 | #====================== 124 | win.mainloop() -------------------------------------------------------------------------------- /Ch11_Code/GUI_FallDown_Tooltip.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 17, 2019 3 | Chapter 11 4 | @author: Burkhard 5 | ''' 6 | 7 | #====================== 8 | # imports 9 | #====================== 10 | import tkinter as tk 11 | from tkinter import ttk 12 | from tkinter import messagebox 13 | 14 | #=================================================================== 15 | class ToolTip(object): 16 | def __init__(self, widget, tip_text=None): 17 | self.widget = widget 18 | self.tip_text = tip_text 19 | widget.bind('', self.mouse_enter) # bind mouse events 20 | widget.bind('', self.mouse_leave) 21 | 22 | def mouse_enter(self, _event): 23 | self.show_tooltip() 24 | 25 | def mouse_leave(self, _event): 26 | self.hide_tooltip() 27 | 28 | def show_tooltip(self): 29 | if self.tip_text: 30 | x_left = self.widget.winfo_rootx() # get widget top-left coordinates 31 | y_top = self.widget.winfo_rooty() - 18 # place tooltip above widget or it flickers 32 | 33 | self.tip_window = tk.Toplevel(self.widget) # create Toplevel window; parent=widget 34 | self.tip_window.overrideredirect(True) # remove surrounding toolbar window 35 | self.tip_window.geometry("+%d+%d" % (x_left, y_top)) # position tooltip 36 | 37 | label = tk.Label(self.tip_window, text=self.tip_text, justify=tk.LEFT, 38 | background="#ffffe0", relief=tk.SOLID, borderwidth=1, 39 | font=("tahoma", "8", "normal")) 40 | label.pack(ipadx=1) 41 | 42 | def hide_tooltip(self): 43 | if self.tip_window: 44 | self.tip_window.destroy() 45 | 46 | #=================================================================== 47 | 48 | 49 | #====================== 50 | # Create instance 51 | #====================== 52 | win = tk.Tk() 53 | 54 | #====================== 55 | # Add a title 56 | #====================== 57 | win.title("Python GUI") 58 | 59 | #========================= 60 | # Disable resizing the GUI 61 | #========================= 62 | win.resizable(0,0) 63 | 64 | #=============================================================================== 65 | # Adding a LabelFrame, Textbox (Entry) and Combobox 66 | #=============================================================================== 67 | lFrame = ttk.LabelFrame(win, text="Python GUI Programming Cookbook") 68 | lFrame.grid(column=0, row=0, sticky='WE', padx=10, pady=10) 69 | 70 | #=============================================================================== 71 | # Labels 72 | #=============================================================================== 73 | ttk.Label(lFrame, text="Enter a name:").grid(column=0, row=0) 74 | ttk.Label(lFrame, text="Choose a number:").grid(column=1, row=0, sticky=tk.W) 75 | 76 | #=============================================================================== 77 | # Buttons click command 78 | #=============================================================================== 79 | def clickMe(name, number): 80 | messagebox.showinfo('Information Message Box', 'Hello ' + name + \ 81 | ', your number is: ' + number) 82 | 83 | #=============================================================================== 84 | # Creating several controls in a loop 85 | #=============================================================================== 86 | names = ['name0', 'name1', 'name2'] 87 | nameEntries = ['nameEntry0', 'nameEntry1', 'nameEntry2'] 88 | 89 | numbers = ['number0', 'number1', 'number2'] 90 | numberEntries = ['numberEntry0', 'numberEntry1', 'numberEntry2'] 91 | 92 | buttons = [] 93 | 94 | for idx in range(3): 95 | names[idx] = tk.StringVar() 96 | nameEntries[idx] = ttk.Entry(lFrame, width=12, textvariable=names[idx]) 97 | nameEntries[idx].grid(column=0, row=idx+1) 98 | nameEntries[idx].delete(0, tk.END) 99 | nameEntries[idx].insert(0, '') 100 | 101 | numbers[idx] = tk.StringVar() 102 | numberEntries[idx] = ttk.Combobox(lFrame, width=14, textvariable=numbers[idx]) 103 | numberEntries[idx]['values'] = (1+idx, 2+idx, 4+idx, 42+idx, 100+idx) 104 | numberEntries[idx].grid(column=1, row=idx+1) 105 | numberEntries[idx].current(0) 106 | 107 | button = ttk.Button(lFrame, text="Click Me "+str(idx+1), command=lambda idx=idx: clickMe(names[idx].get(), numbers[idx].get())) 108 | button.grid(column=2, row=idx+1, sticky=tk.W) 109 | buttons.append(button) 110 | 111 | # Add Tooltips to more widgets 112 | ToolTip(nameEntries[idx], 'This is an Entry widget.') 113 | ToolTip(numberEntries[idx], 'This is a DropDown widget.') 114 | ToolTip(buttons[idx], 'This is a Button widget.') 115 | 116 | #====================== 117 | # Start GUI 118 | #====================== 119 | win.mainloop() --------------------------------------------------------------------------------