Preface....19
Who this book is for....20
What this book covers....21
To get the most out of this book....22
Get in touch....26
Introduction to Tkinter....28
Introducing Tkinter and Tk....29
Choosing Tkinter....29
Installing Tkinter....31
Installing Python 3.9 on Windows....31
Installing Python 3 on macOS....32
Installing Python 3 and Tkinter on Linux....32
Introducing IDLE....32
Using the shell mode of IDLE....33
Using the editor mode of IDLE....33
IDLE as a Tkinter example....34
Creating a Tkinter Hello World....36
An overview of basic Tkinter....39
Building a GUI with Tkinter widgets....39
Arranging our widgets with geometry managers....45
Making the form actually do something....50
Handling data with Tkinter control variables....53
Using control variables in a callback function....58
The importance of control variables....60
Summary....61
Designing GUI Applications....62
Analyzing a problem at ABQ AgriLabs....63
Assessing the problem....63
Gathering information about the problem....64
Interviewing the interested parties....65
Analyzing what we've found out....67
Information from the data originators....68
Information from the users of the application....70
Information from technical support....71
Information from the data consumer....72
Documenting specification requirements....73
Contents of a simple specification....73
Writing the ABQ data entry program specification....75
Designing the application....78
Deciding on input widgets....78
Grouping our fields....81
Laying out the form....82
Laying out the application....84
Evaluating technology options....86
Summary....88
Creating Basic Forms with Tkinter and Ttk Widgets....90
The Ttk widget set....90
The Label widget....92
The Entry widget....93
The Spinbox widget....94
The Checkbutton widget....95
The Radiobutton widget....97
The Combobox widget....98
The Text widget....99
Text widget indices....101
The Button widget....102
The LabelFrame widget....103
Implementing the application....105
First steps....106
Building the data record form....108
The Record Information section....108
The Environment Data section....111
The Plant Data section....112
Finishing the GUI....114
Writing the callback functions....115
The Reset function....115
The Save callback....116
Finishing up and testing....120
Summary....121
Organizing Our Code with Classes....123
A primer on Python classes....123
The advantages of using classes....124
Classes are an integral part of Python....124
Classes make relationships between data and functions explicit....125
Classes help create reusable code....125
Syntax of class creation....125
Attributes and methods....126
Magic attributes and methods....129
Public, private, and protected members....131
Inheritance and subclasses....133
Using classes with Tkinter....134
Improving Tkinter classes....135
Creating compound widgets....137
Building encapsulated components....139
Subclassing Tk....142
Rewriting our application using classes....145
Adding a StringVar to the Text widget....145
Passing in a variable....146
Synchronizing the widget to the variable....147
Synchronizing the variable to the widget....147
Creating a more advanced LabelInput()....149
Creating a form class....152
Creating an application class....158
Summary....161
Reducing User Error with Validation and Automation....163
Validating user input....163
Strategies to prevent data errors....164
Validation in Tkinter....165
The validate argument....166
The validatecommand argument....166
The invalidcommand argument....169
Creating validated widget classes....170
Creating a Date field....172
Implementing validated widgets in our GUI....176
Introducing the power of multiple inheritance....177
Building a validating mixin class....180
Building validating input widgets with ValidatedMixin....183
Requiring data....184
Creating a Date widget....184
A better Combobox widget....185
A range-limited Spinbox widget....188
Validating Radiobutton widgets....192
Updating our form with validated widgets....195
Implementing validation interaction between form widgets....197
Dynamically updating the Spinbox range....198
Dynamic disabling of fields....204
Displaying errors....206
Preventing form submission on error....207
Automating input....210
Date automation....211
Automating Plot, Lab, Time, and Technician....212
Summary....214
Planning for the Expansion of Our Application....215
Separating concerns....216
The MVC pattern....216
What is a model?....217
What is a view?....217
What is a controller?....218
Why complicate our design?....219
Structuring our application directory....220
Basic directory structure....220
The abq_data_entry.py file....221
The README.rst file....222
Populating the docs folder....223
Making a Python package....224
Splitting our application into multiple files....226
Creating the models module....226
Moving the widgets....233
Moving the views....234
Removing redundancy in our view logic....236
Using custom events to remove tight coupling....239
Creating the application file....241
Running the application....243
Using version control software....244
A super-quick guide to using Git....245
Initializing and configuring a Git repository....246
Adding and committing code....246
Viewing and using our commits....248
Summary....249
Creating Menus with Menu and Tkinter Dialogs....250
Solving problems in our application....251
Planning solutions to the issues....251
Implementing Tkinter dialogs....253
Error dialogs with the Tkinter messagebox....253
Showing error dialogs in ABQ Data Entry....256
Using filedialog....258
Using simpledialog and creating a custom dialog....262
Creating a Login dialog using simpledialog....263
Incorporating the LoginDialog in our class....266
Designing the application menu....269
The Tkinter Menu widget....270
Using Checkbutton and Radiobutton items....272
Implementing the ABQ application menu....275
Adding a Help menu....276
Adding a File menu....277
Adding a settings menu....280
Finishing the menu....283
Persisting settings....283
Building a model for settings persistence....285
Using the settings model in our application....289
Summary....291
Navigating Records with Treeview and Notebook....293
Implementing read and update in the model....293
Adding read and update to the CSVModel class....294
Implementing get_all_records()....295
Implementing get_record()....298
Adding update capability to save_record()....298
The Ttk Treeview....300
Anatomy of a Treeview....301
Building a file browser....302
Creating and configuring a Treeview....303
Populating a Treeview with data....305
Sorting Treeview records....308
Using Treeview virtual events....312
Implementing a record list with Treeview....313
Creating the RecordList class....314
Configuring a Treeview widget....315
Adding a scrollbar for the Treeview....317
Populating the Treeview....319
Adding the record list to the application....320
Modifying the record form for read and update....321
Adding a current record property....321
Adding a label to show what is being edited....322
Adding a load_record() method....322
Updating the application layout....324
The Ttk Notebook widget....325
Adding a notebook to our application....328
Adding and updating application callbacks....329
The _show_recordlist() method....329
The _populate_recordlist() method....330
The _new_record() method....332
The _open_record() method....333
The _on_save() method....334
Main menu changes....334
Testing our program....335
Summary....336
Improving the Look with Styles and Themes....338
Working with images in Tkinter....339
Tkinter PhotoImage....339
PhotoImage and variable scope....340
Using Pillow for extended image support....341
Adding the company logo to ABQ Data Entry....345
Dealing with the image path problem....346
Setting a window icon....349
Adding icons to buttons and menus....350
Using BitmapImage....354
Styling Tkinter widgets....356
Widget color properties....357
Using widget properties on the MainMenu....357
Styling widget content with tags....360
Styling our record list with tags....363
Working with fonts in Tkinter....367
Configuring Tkinter fonts....367
Configuring fonts with strings and tuples....367
The font module....368
Giving users font options in ABQ Data Entry....373
Styling Ttk widgets....376
TTk styling breakdown....376
Exploring a Ttk widget....377
Using themes....383
Adding some color to ABQ Data Entry....384
Adding styles to individual form widgets....386
Fixing the error colors....389
Styling input widgets on error....390
Setting themes....393
Building a theme selector....393
Summary....396
Maintaining Cross-Platform Compatibility....398
Writing cross-platform Python....398
Filenames and file paths across platforms....399
Path separators and drives....399
Case sensitivity....403
Symbolic links....404
Path variables....405
Inconsistent library and feature support....407
Python's platform-limited libraries....407
Checking low-level function compatibility....408
The dangers of the subprocess module....409
Text file encodings and formats....410
Graphical and console modes....411
Writing code that changes according to the platform....413
Writing cross-platform Tkinter....416
Tkinter version differences across platforms....416
Application menus across platforms....417
Menu widget capabilities....417
Menu guidelines and standards....421
Menus and accelerator keys....423
Cross-platform fonts....423
Cross-platform theme support....424
Window zoomed state....424
Improving our application's cross-platform compatibility....425
Storing preferences correctly....425
Specifying an encoding for our CSV file....427
Making platform-appropriate menus....428
Preparing our MainMenu class....428
Adding accelerators....432
Building the Windows menu....434
Building the Linux menu....436
Building the macOS menu....437
Creating and using our selector function....441
Summary....443
Creating Automated Tests with unittest....444
Automated testing basics....444
A simple unit test....445
The unittest module....447
Writing a test case....448
TestCase assertion methods....450
Fixtures....452
Using Mock and patch....453
Running multiple unit tests....455
Testing Tkinter code....456
Managing asynchronous code....456
Simulating user actions....457
Specifying an event sequence....457
Managing focus and grab....459
Getting widget information....460
Writing tests for our application....461
Testing the data model....461
Testing file reading in get_all_records()....463
Testing file saving in save_record()....465
More tests on the models....468
Testing our Application object....468
Testing our widgets....473
Unit testing the ValidatedSpinbox widget....474
Integration testing the ValidatedSpinbox widget....476
Testing our mixin class....482
Summary....484
Improving Data Storage with SQL....485
PostgreSQL....486
Installing and configuring PostgreSQL....486
Configuring PostgreSQL using the GUI utility....487
Configuring PostgreSQL using the command line....488
Modeling relational data....489
Primary keys....489
Using surrogate primary keys....490
Normalization....492
First normal form....492
Second normal form....494
Third normal form....495
More normalization forms....496
Entity-relationship diagrams....496
Assigning data types....498
Creating the ABQ database....500
Creating our tables....500
Creating the lookup tables....500
The lab_checks table....502
The plot_checks table....503
Creating a view....504
Populating the lookup tables....506
Connecting to PostgreSQL with psycopg2....506
psycopg2 basics....507
Parameterized queries....509
Special cursor classes....512
Integrating SQL into our application....513
Creating a new model....513
Saving data....518
Getting the current seed sample for the plot....521
Adjusting the Application class for the SQL backend....522
Implementing SQL logins....523
Updating the Application._on_save() method....524
Removing file-based code....525
Adjusting the DataRecordForm for SQL data....526
Reordering fields....526
Fixing the load_record() method....527
Improving auto-fill....527
Updating the RecordList for the SQLModel....529
We're done!....532
Summary....533
Connecting to the Cloud....534
HTTP using urllib....534
HTTP transaction fundamentals....535
HTTP status codes....536
Basic downloading with urllib.request....536
Generating POST requests....538
Downloading weather data to ABQ Data Entry....539
Creating a weather data model....539
Parsing the XML weather data....541
Implementing weather data storage....544
Adding the GUI elements for weather download....547
RESTful HTTP using requests....550
Understanding RESTful web services....550
The Python requests library....552
Installing and using requests....552
Interacting with authenticated sites using Session....554
The requests.Response object....555
Implementing a REST backend....556
The authenticate() method....559
The upload_file() method....561
The check_file() method....561
The get_file() method....562
Integrating REST upload into the application....563
Creating a CSV extract....563
Creating the upload callback....564
Finishing up....568
SFTP using paramiko....570
Setting up SSH services for testing....570
Installing and using paramiko....571
Using paramiko....571
Inspecting our connection....574
Using SFTP....574
Implementing an SFTP model....576
Uploading files....578
Checking a file's existence....580
Using SFTPModel in our application....581
Finishing up....584
Summary....585
Asynchronous Programming with Thread and Queue....587
Tkinter's event queue....588
Event queue control....588
The update() methods....588
The after() methods....589
Common uses of event queue control....591
Smoothing out display changes....591
Mitigating GUI freezes....592
Running code in the background with threads....595
The threading module....596
Tkinter and thread safety....597
Converting our network functions to threaded execution....598
Using the threaded uploader....600
Passing messages using a queue....601
The Queue object....602
Using queues to communicate between threads....603
Adding a communication queue to our threaded uploader....606
Creating a communications protocol....607
Sending messages from the uploader....609
Handling queue messages....610
Using locks to protect shared resources....612
Understanding the Lock object....613
Using a Lock object to prevent concurrent uploads....615
Threading and the GIL....616
Summary....617
Visualizing Data Using the Canvas Widget....618
Drawing and animation with Tkinter's Canvas....618
Drawing on the Canvas....619
Rectangles and squares....619
Ovals, circles, and arcs....621
Lines....622
Polygons....623
Text....624
Images....624
Tkinter widgets....625
Canvas items and state....626
Canvas object methods....626
Scrolling the Canvas....628
Animating Canvas objects....631
Setting up the playing field....632
Setting our players....633
Animating the racers....634
Running the game loop and detecting a win condition....639
Creating simple graphs using Canvas....642
Creating the model method....643
Creating the chart view....644
Updating the application....650
Advanced graphs using Matplotlib....652
Data model method....652
Creating the bubble chart view....654
Updating the Application class....657
Summary....659
Packaging with setuptools and cxFreeze....661
Creating distributable packages with setuptools....661
Preparing our package for distribution....662
Creating a requirements.txt file....662
Creating a pyproject.toml file....664
Adding a license file....665
Making our package executable....665
Configuring a setup.py script....666
Basic metadata arguments....667
Packages and dependencies....668
Adding extra files....669
Defining commands....670
Testing the configuration....671
Creating and using source distributions....672
Testing our source distribution....672
Building a wheel distribution....673
Creating executables with cx_Freeze....675
First steps with cx_Freeze....676
The build_exe options....677
Including external files....678
Building executables....679
Cleaning up the build....680
Building Windows executables with cx_Freeze....681
Building a Windows installer file....682
Building macOS executables with cx_Freeze....685
Building macOS application bundles....685
Building macOS .dmg files....686
Summary....687
Appendices....688
A: A Quick Primer on reStructuredText....689
The reStructuredText markup language....690
Document structure....690
Lists....692
Character styles....693
Blocks and quotes....694
Tables....695
Converting RST to other formats....696
Other ways to render RST....699
B: A Quick SQL Tutorial....701
SQL concepts....701
Syntax differences from Python....702
SQL operations and syntax....703
Defining tables and inserting data....703
Retrieving data from tables....706
Updating rows, deleting rows, and more WHERE clauses....708
Subqueries....710
Joining tables....711
Managing transactions....715
Learning more....717
Other Books You May Enjoy....719
Index....768
Tkinter is widely used to build GUIs in Python due to its simplicity. In this book, you'll discover Tkinter's strengths and overcome its challenges as you learn to develop fully featured GUI applications.
Python GUI Programming with Tkinter, Second Edition, will not only provide you with a working knowledge of the Tkinter GUI library, but also a valuable set of skills that will enable you to plan, implement, and maintain larger applications. You'll build a full-blown data entry application from scratch, learning how to grow and improve your code in response to continually changing user and business needs.
You'll develop a practical understanding of tools and techniques used to manage this evolving codebase and go beyond the default Tkinter widget capabilities. You'll implement version control and unit testing, separation of concerns through the MVC design pattern, and object-oriented programming to organize your code more cleanly.
You'll also gain experience with technologies often used in workplace applications, such as SQL databases, network services, and data visualization libraries. Finally, you'll package your application for wider distribution and tackle the challenge of maintaining cross-platform compatibility.
This book is for programmers who understand the syntax of Python, but do not yet have the skills, techniques, and knowledge to design and implement a complete software application. A fair grasp of basic Python syntax is required.