<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged gui</title>
<link>https://coderlegion.com/tag/gui</link>
<description>Powered by Question2Answer</description>
<item>
<title>Kavro.Pro Stop writing your UI by hand.</title>
<link>https://coderlegion.com/31729/kavro-pro-stop-writing-your-ui-by-hand</link>
<description>&lt;h3 id=&quot;design-dear-imgui-menus-visually-then-build-a-real-exe&quot;&gt;Design Dear ImGui menus visually, then build a real .exe&lt;/h3&gt;
&lt;p&gt;Kavro is a drag-and-drop designer for &lt;strong&gt;Dear ImGui&lt;/strong&gt; windows, tool menus and launchers. Stop nudging SetCursorPos values and recompiling: drop widgets on a canvas, style them, test the window, and export clean code in C++, C# or Rust.&lt;/p&gt;
&lt;h3 id=&quot;what-you-can-do&quot;&gt;What you can do&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Drag &amp;amp; drop 23 widgets: text, buttons, checkboxes, switches, sliders,&lt;br&gt;
dropdowns, color pickers, hotkeys, tabs, lists, progress bars,&lt;br&gt;
spinners and more &lt;/li&gt;
&lt;li&gt;Themes &amp;amp; styles: one-click presets (Kavro Dark,&lt;br&gt;
Midnight Violet, Ocean, Sakura, Ember…) or per-widget colors, fonts&lt;br&gt;
and rounding &lt;/li&gt;
&lt;li&gt;13 animated backgrounds and 12 built-in actions (switch&lt;br&gt;
pages, toasts, loading screens…) &lt;/li&gt;
&lt;li&gt;Test mode (F6): use your window right inside the editor &lt;/li&gt;
&lt;li&gt;Live code: your UI is plain kv::Button(...) /&lt;br&gt;
kv::Slider(...) calls.  Edit the code and the canvas updates, or the&lt;br&gt;
other way round &lt;/li&gt;
&lt;li&gt;Build &amp;amp; Run (F5): compiles a native Windows .exe in&lt;br&gt;
seconds C++: Dear ImGui + DX11/Vulkan/DX9/DX12/OpenGL (MSVC) Rust: imgui-rs + glium&lt;br&gt;
(Cargo) C#: ImGui.NET + Silk.NET (.NET 8) &lt;/li&gt;
&lt;li&gt;Kavro AI tab: describe a&lt;br&gt;
change and let the AI edit your menu&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;free-and-pro&quot;&gt;Free and Pro&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Free: design and test everything. &lt;/li&gt;
&lt;li&gt;Pro ($10/month or $108/year): Build &amp;amp; Run, source export, all languages, all templates and the AI tab.&lt;/li&gt;
&lt;li&gt;Get Pro at &lt;a rel=&quot;nofollow&quot; href=&quot;https://kavro.pro&quot;&gt;https://kavro.pro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;requirements&quot;&gt;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Windows 10 or 11 (64-bit)&lt;/li&gt;
&lt;li&gt;A free kavro.pro account (you sign in when Kavro starts)&lt;/li&gt;
&lt;li&gt;To build: Visual Studio with the C++ workload (C++), Rust/Cargo (Rust) or the .NET 8 SDK (C#)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;links&quot;&gt;Links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Website: &lt;a rel=&quot;nofollow&quot; href=&quot;https://kavro.pro&quot;&gt;https://kavro.pro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Discord, for help and updates: &lt;a rel=&quot;nofollow&quot; href=&quot;https://discord.gg/GeFa4vdTD&quot;&gt;https://discord.gg/GeFa4vdTD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;YouTube tutorials: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/@kavropro&quot;&gt;https://www.youtube.com/@kavropro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Itch.io link: &lt;a rel=&quot;nofollow&quot; href=&quot;https://kavro-pro.itch.io/kavro&quot;&gt;https://kavro-pro.itch.io/kavro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Kavro updates itself when a new version is out.&lt;/strong&gt;&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/31729/kavro-pro-stop-writing-your-ui-by-hand</guid>
<pubDate>Mon, 19 Oct 2026 21:28:35 +0000</pubDate>
</item>
<item>
<title>I built a desktop client for DeepSeek's coding agent</title>
<link>https://coderlegion.com/26611/i-built-a-desktop-client-for-deepseeks-coding-agent</link>
<description>&lt;p&gt;Built a Windows desktop client for DeepSeek Harness. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/gb6k10zmm9099l1gznzw.png&quot; alt=&quot;Image description&quot;&gt;&lt;/p&gt;
&lt;p&gt;V1 packages the official Web UI into a native app with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One-click installer (bundles its own runtime)&lt;/li&gt;
&lt;li&gt;Built-in browser — watch the agent browse in real Edge&lt;/li&gt;
&lt;li&gt;Built-in terminal for CLI commands&lt;/li&gt;
&lt;li&gt;Sandbox by default — every action needs approval&lt;/li&gt;
&lt;li&gt;Bilingual (Chinese + English)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;V2 with a fully custom workbench is in active development.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/See-Sol-Lab/DeepSeekGUI&quot;&gt;https://github.com/See-Sol-Lab/DeepSeekGUI&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Feedback welcome!&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26611/i-built-a-desktop-client-for-deepseeks-coding-agent</guid>
<pubDate>Wed, 09 Sep 2026 11:33:11 +0000</pubDate>
</item>
<item>
<title>Your Database GUI Shouldn't Need an Account</title>
<link>https://coderlegion.com/20175/your-database-gui-shouldnt-need-an-account</link>
<description>&lt;p&gt;A critique of the trend toward account-required database GUI clients, arguing that tools holding production credentials should never route data through vendor backends. The post makes the case for local-first design using Tabularis as a concrete example: no signup, secrets stored in the OS keychain, all config as plain files on disk, bring-your-own-key AI, and only one network call (a GitHub version check). The tradeoffs — no sync, no team workspaces, no telemetry — are acknowledged openly. The core argument is that database clients are plumbing and should be durable and vendor-independent, not coupled to a company's runway.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/20175/your-database-gui-shouldnt-need-an-account</guid>
<pubDate>Wed, 10 Jun 2026 13:52:44 +0000</pubDate>
</item>
<item>
<title>DevLog 20250507 Bringing Smart Suggestions and Smarter Search to Divooka’s Visual Coding</title>
<link>https://coderlegion.com/3063/devlog-20250507-bringing-smart-suggestions-and-smarter-search-to-divookas-visual-coding</link>
<description>&lt;h3 id=&quot;learning-from-unreal-engine-blueprints&quot;&gt;Learning from Unreal Engine Blueprints&lt;/h3&gt;
&lt;p&gt;I’ve always admired Unreal Engine’s Blueprints - particularly its subtle yet powerful &lt;strong&gt;connection suggestion feature&lt;/strong&gt;. When you drag a wire out from a pin, the system intuitively suggests compatible nodes based on the pin’s data type.&lt;/p&gt;
&lt;p&gt;This kind of context-awareness accelerates creation and keeps workflow fluid by making things &lt;em&gt;just work&lt;/em&gt; - no guesswork needed.&lt;/p&gt;
&lt;h3 id=&quot;the-challenge-missing-type-labels-in-c-instance-methods&quot;&gt;The Challenge: Missing Type Labels in C# Instance Methods&lt;/h3&gt;
&lt;p&gt;Divooka, built atop C#, posed a snag: &lt;strong&gt;instance methods don’t include the object’s type in their signature&lt;/strong&gt;. So if a method like &lt;code&gt;Rotate()&lt;/code&gt; belongs to a &lt;code&gt;Transform&lt;/code&gt; object, the type isn’t explicitly declared in the method signature - making automatic suggestion tricky.&lt;/p&gt;
&lt;p&gt;To match Unreal’s intuitiveness, I needed a way to tell Divooka - not just &quot;Rotate()&quot;, but &lt;em&gt;Rotate() on Transform&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;explicit-type-filter-in-search-syntax&quot;&gt;Explicit Type Filter in Search Syntax&lt;/h3&gt;
&lt;p&gt;The first step is to allow users to filter the toolbox explicitly in their search query.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r0n5z8by0eapb5k7iy4t.png&quot; alt=&quot;Instance Function without Type Parameter&quot;&gt;&lt;/p&gt;
&lt;p&gt;For example: &lt;code&gt;[Pixel Image] Save&lt;/code&gt; would filter for methods in the &lt;code&gt;Pixel Image&lt;/code&gt; toolbox (category). The symmetry of this syntax remains intuitive even in localized languages like Chinese - because only the type would be translated, not the syntax design itself.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1girqglhmc2hx0itcuo.png&quot; alt=&quot;Type Parameter Syntax&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;building-the-pipeline-filtering-and-highlighting&quot;&gt;Building the Pipeline: Filtering and Highlighting&lt;/h3&gt;
&lt;p&gt;Next, I leveled up the search experience by crafting a multi-stage pipeline:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Category names&lt;/strong&gt; (like &lt;code&gt;[AI Service]&lt;/code&gt;, &lt;code&gt;[Pixel Image]&lt;/code&gt;) now at the front, so users can scope their search by purpose.&lt;/li&gt;
&lt;li&gt;Then we optionally parse &lt;code&gt;&amp;lt;TypeName&amp;gt;&lt;/code&gt; syntax, which is used to filter input parameters.&lt;/li&gt;
&lt;li&gt;Finally, full-text search for other keywords.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So a query might look like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Pixel Image] &amp;lt;String&amp;gt; Save
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In which case we will search only for functions containing the word &quot;Save&quot; and expects a &lt;code&gt;String&lt;/code&gt; parameter. Visually, I emphasized that first category tag with syntax highlighting to help the eye quickly scan.&lt;/p&gt;
&lt;h3 id=&quot;the-result-it-just-works-mostly-&quot;&gt;The Result: It Just Works (Mostly)&lt;/h3&gt;
&lt;p&gt;Here’s how it currently looks:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kw31ux4qf0ajmc7oneq9.gif&quot; alt=&quot;Working Result&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Type &lt;code&gt;[Pixel Image] Save&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The search autocomplete suggests all instance methods named &lt;code&gt;Save...()&lt;/code&gt; defined in &lt;code&gt;Pixel Image&lt;/code&gt; toolbox (mostly operating on the &lt;code&gt;PixelImage&lt;/code&gt; object type) (e.g., &lt;code&gt;PixelImage.Save&lt;/code&gt;, &lt;code&gt;PixelImage.Load&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;Everything lights up in palette instantly - &lt;em&gt;users can find what they need fast&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;what-s-missing-auto-connecting-suggestions&quot;&gt;What’s Missing: Auto-Connecting Suggestions&lt;/h3&gt;
&lt;p&gt;This solves the &lt;strong&gt;searching&lt;/strong&gt; half of the problem beautifully - but it doesn’t yet auto-connect. In Unreal, dragging from a &lt;code&gt;Vector&lt;/code&gt; pin might instantly suggest &lt;code&gt;Normalize()&lt;/code&gt; - and connect it for you if you click that suggestion.&lt;/p&gt;
&lt;p&gt;Right now, Divooka still requires a manual drag-and-click - our intention was only searching and filtering, not full drag-and-drop automation.&lt;/p&gt;
&lt;h3 id=&quot;next-steps-toward-full-contextual-suggestions&quot;&gt;Next Steps: Toward Full Contextual Suggestions&lt;/h3&gt;
&lt;p&gt;I’m plotting the future:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pin-aware suggestion&lt;/strong&gt;: When dragging a wire from a pin, immediately filter down to matching methods—and optionally even pre-wire the node when hitting “Enter” or double-clicking.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type inference&lt;/strong&gt;: Avoid requiring &lt;code&gt;&amp;lt;Type&amp;gt;&lt;/code&gt; if the context is obvious - since the system already knows the pin’s type.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better localization&lt;/strong&gt;: Make sure category tags and type filters localize cleanly, without mangling grammar in languages like Chinese, Japanese, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced UX hints&lt;/strong&gt;: Perhaps grey-out non-matching nodes live, or provide quick tooltips (e.g. “only shows methods on Transform”, like Unreal Blueprint's node search interface).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;Previously, instance-based methods don’t expose their object type; this hampers auto-suggestion. We solved this by introducing explicit &lt;code&gt;&amp;lt;Type&amp;gt;&lt;/code&gt; filters and category tags in our search syntax. The result is now the users can quickly locate relevant methods with filtered search - instant clarity. Up next, we want to add full context-aware, auto-connecting suggestion - move from “search” to “smart connection.”&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Unreal Blueprints’ delightful node suggestions inspired us to refine Divooka’s search. By introducing syntax like &lt;code&gt;[Category] &amp;lt;Type&amp;gt; Keywords...&lt;/code&gt;, Divooka now lets you filter instance-based methods explicitly - greatly improving discoverability. Coming up: auto-connection and smarter, context-aware wiring.&lt;/p&gt;
&lt;p&gt;Let me know if you are interesting in learning more specific implementation details - like the regex matching, indexing logic, or localization strategy!&lt;/p&gt;
&lt;p&gt;Happy visual coding!&lt;/p&gt;
</description>
<category>Other</category>
<guid isPermaLink="true">https://coderlegion.com/3063/devlog-20250507-bringing-smart-suggestions-and-smarter-search-to-divookas-visual-coding</guid>
<pubDate>Sun, 07 Sep 2025 23:39:02 +0000</pubDate>
</item>
<item>
<title>Some Ranting on Dev.to and Opinion on UI Design</title>
<link>https://coderlegion.com/4418/some-ranting-on-dev-to-and-opinion-on-ui-design</link>
<description>&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;
&lt;p&gt;Each platform strives to provide its best and each has its pros and cons. Some are simple technical issues - like the Markdown editor of CoderLegion, some are serious design flaws (like there is no way to manage brushes in Affinity Photo).&lt;/p&gt;
&lt;p&gt;Today I was going to comb my thoughts and write something on Dev.to and was shocked so see this.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfpe796dwxkwuqik1l3d.png&quot; alt=&quot;Side Bar&quot;&gt;&lt;/p&gt;
&lt;p&gt;This ugly new feature is driving me mad.&lt;/p&gt;
&lt;h3 id=&quot;distracting-side-bar&quot;&gt;Distracting Side Bar&lt;/h3&gt;
&lt;p&gt;It's one of the things I don't like about Discord/Slack. The interface is so clustered with irrelevant things or buttons that I rarely click on or need. And &lt;strong&gt;there are too many colors&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now Dev.to is completely ruining the used-to-be quiet and focused writing experience. Just look at the screenshot below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mu85wvs6nio0ouccjun0.png&quot; alt=&quot;Heavy Distraction&quot;&gt;&lt;/p&gt;
&lt;p&gt;It's honestly so annoying I can't bear staying on this site any second longer. What's worse, because of this total distraction, I almost forgot what I was about to write.&lt;/p&gt;
&lt;h3 id=&quot;alternatives&quot;&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;I would love to officially moving to CoderLegion for canonical Dev Logs, but the image uploading experience is also not smooth. So that's a dilemma.&lt;/p&gt;
&lt;p&gt;We have the official Methodox Blog on WordPress. For those who aren't familiar with its content management system - it requires uploading images to the blog server for every single thing you display (or else use plugins) and is really inconvenient if one just want to share quick screenshots.&lt;/p&gt;
&lt;p&gt;Medium is actually great writing experience, but its design feels more suited for literature work than for tech.&lt;/p&gt;
&lt;h3 id=&quot;ideal-scenario&quot;&gt;Ideal Scenario&lt;/h3&gt;
&lt;p&gt;Here I propose a concept &quot;QuietSpace&quot; for distraction-free blogging.&lt;/p&gt;
&lt;p&gt;Key ideas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Medium style editing interface&lt;/li&gt;
&lt;li&gt;Dev.to style Markdown and easy image uploading through dropping and pasting, single button Preview&lt;/li&gt;
&lt;li&gt;CDN for blog contents&lt;/li&gt;
&lt;li&gt;GitHub style support for video and YouTube embedding.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Key formatting elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fully support tables (a issue in both CoderLegion and Medium)&lt;/li&gt;
&lt;li&gt;Fully support images gifs and videos (through CDN link) (an issue in Dev.to)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Web editor, optional desktop editor. No dedicated subdomain: url path for user. No ads, central explore and save articles. May even be paid writing experience at $5 per month. Easy sharing, simple commenting.&lt;/p&gt;
&lt;p&gt;Used for: DevLog.&lt;/p&gt;
&lt;p&gt;Derivation: dedicated blog-style web hosting, like the simplest form of Word Press.&lt;/p&gt;
&lt;h3 id=&quot;summary-1&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;There are many blogging and posting platforms and each has distinct features. As a developer we seek a balance between publicity, platform friendliness and technical satisfaction. I think the best platform has to be customized for custom needs. While generic customizable frameworks exist, the customization process right now still take too much tweaking. Will AI solve this problem? I doubt it, as I see missing pieces in basic infrastructure that's not easily addressed with smart agents.&lt;/p&gt;
&lt;h3 id=&quot;follow-up&quot;&gt;Follow Up&lt;/h3&gt;
&lt;p&gt;I was writing this post bearing in mind I have to suffer the new UI update of Dev.to - life felt truly like a compromise. &lt;/p&gt;
&lt;p&gt;However, the dev team addressed the issue within an hour! I didn't even expect them to notice my post. Salute To Dev.To Dev Team! See discussion on &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/methodoxdivooka/whats-going-on-5en4&quot;&gt;the post on Dev.to&lt;/a&gt;.&lt;/p&gt;
</description>
<category>IDEs &amp; Code Editors</category>
<guid isPermaLink="true">https://coderlegion.com/4418/some-ranting-on-dev-to-and-opinion-on-ui-design</guid>
<pubDate>Mon, 04 Aug 2025 19:43:11 +0000</pubDate>
</item>
<item>
<title>Exploring More in Tkinter</title>
<link>https://coderlegion.com/253/exploring-more-in-tkinter</link>
<description>&lt;p&gt;In this article, we'll delve into some of the more intricate aspects of &lt;strong&gt;Tkinter&lt;/strong&gt;, exploring advanced techniques that will empower you to create even more powerful and polished GUI applications. Throughout our exploration, we'll uncover invaluable tools such as the &lt;strong&gt;&lt;code&gt;ttk&lt;/code&gt; module&lt;/strong&gt; for enhanced widget styling, the &lt;strong&gt;Canvas&lt;/strong&gt; widget for versatile graphics rendering, and the &lt;strong&gt;Grid&lt;/strong&gt; geometry manager for precise layout control.  From &lt;strong&gt;custom themes&lt;/strong&gt; to &lt;strong&gt;file handling strategies&lt;/strong&gt;, gear up to elevate your Tkinter expertise to the next level.&lt;/p&gt;
&lt;p&gt;If you are new to Tkinter, I highly recommend you to thoroughly review &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/190/tkinter-library-in-python&quot;&gt;this article&lt;/a&gt; or the &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/tkinter.html&quot;&gt;official documentation&lt;/a&gt;. Familiarizing yourself with its contents will provide a solid foundation for understanding and effectively utilizing Tkinter.&lt;/p&gt;
&lt;p&gt;In the code snippets provided, add these lines in the beginning:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.geometry(&quot;457x335&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and this line at the end:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;custom-styles-and-themes&quot;&gt;Custom Styles and Themes&lt;/h2&gt;
&lt;p&gt;Tkinter enables customized visual presentation through custom styles and themes, using the &lt;code&gt;ttk&lt;/code&gt; module for personalized widget designs, ensuring consistency across platforms.&lt;/p&gt;
&lt;p&gt;To deepen our understanding, let's personalize our textbox, button, and label by customizing their appearance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import tkinter as tk
from tkinter import ttk

def submit_text():
    text = text_entry.get()
    text_label.config(text=text, font=(&quot;Times New Roman&quot;, 12, &quot;bold&quot;), foreground=&quot;green&quot;)     #customize label

window = tk.Tk()
window.geometry(&quot;457x335&quot;)
window.title(&quot;Custom Styles&quot;)

style = ttk.Style()     #to define custom styles
style.configure(&quot;Custom.TEntry&quot;, foreground=&quot;blue&quot;, fieldbackground=&quot;lightblue&quot;)     #customize textbox
style.configure(&quot;Custom.TButton&quot;, foreground=&quot;red&quot;, background=&quot;red&quot;)     #customize button

text_entry = ttk.Entry(window, width=30, style=&quot;Custom.TEntry&quot;)
text_entry.pack(padx=10, pady=10)
submit_button = ttk.Button(window, text=&quot;Submit&quot;, command=submit_text, style=&quot;Custom.TButton&quot;)     #sends entered text to the submit_text() function
submit_button.pack(padx=10, pady=5)
text_label = ttk.Label(window)
text_label.pack(padx=10, pady=10)
window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=2820964779047794875&quot; alt=&quot;Tkinter_custom&quot;&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;submit_text&lt;/code&gt; function retrieves your text from the &lt;code&gt;text_entry&lt;/code&gt; textbox and updates the &lt;code&gt;text_label&lt;/code&gt; with it. The label's appearance is customized using Times New Roman font, size 12, bold, and green color. Custom styles (&lt;code&gt;Custom.TEntry&lt;/code&gt; for the textbox and &lt;code&gt;Custom.TButton&lt;/code&gt; for the button) are defined and configured using the &lt;code&gt;ttk.Style()&lt;/code&gt; method to set properties like &lt;code&gt;foreground&lt;/code&gt; and &lt;code&gt;background&lt;/code&gt; colors.&lt;/p&gt;
&lt;h2 id=&quot;integration-with-python-libraries&quot;&gt;Integration with Python Libraries&lt;/h2&gt;
&lt;p&gt; Tkinter can be integrated with other Python libraries and tools to enhance its functionality:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with Matplotlib&lt;/strong&gt;: You can make your Tkinter app more informative by adding interactive charts to display data trends or visualizations. By integrating Matplotlib, a popular Python library for creating charts and graphs, you can easily embed dynamic plots directly into your Tkinter windows.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with Scikit-learn&lt;/strong&gt;: You can combine Tkinter with Scikit-learn to develop GUI applications for machine learning tasks such as classification, regression, and clustering. This integration enables us to build interactive interfaces for training models, evaluating performance, and making predictions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;div-blue&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Note:&lt;/span&gt;&lt;span class=&quot;alert-body&quot;&gt; In order to install sklearn library locally, run the command: `pip install scikit-learn`&lt;/span&gt; &lt;/div&gt;
&lt;div class=&quot;div-red&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Caution:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt;Ensure local compatibility by installing `matplotlib` and `matplotlib.backends.backend_tkagg` before running this code.&lt;/span&gt; &lt;/div&gt;
&lt;p&gt;Let's delve into the concept using an example of Linear Regression applied to predict outcomes for the Diabetes dataset:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import tkinter as tk
from tkinter import ttk     #for themed widgets
import matplotlib.pyplot as plt
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

diabetes = load_diabetes()     #Load the dataset
X_train, X_test, y_train, y_test = train_test_split(diabetes.data, diabetes.target, test_size=0.2, random_state=42)

window = tk.Tk()
window.geometry(&quot;650x500&quot;)
window.title(&quot;Diabetes Linear Regression&quot;)

def train_and_plot():
    model = LinearRegression()
    model.fit(X_train, y_train)     #train
    y_pred_train = model.predict(X_train)     #predict
    y_pred_test = model.predict(X_test)
    mse_train = mean_squared_error(y_train, y_pred_train)     #calculate mean squared error
    mse_test = mean_squared_error(y_test, y_pred_test)
    
    plt.figure(figsize=(8, 6))     #create the plot
    plt.scatter(y_test, y_pred_test, color='blue')
    plt.plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], color='red', linestyle='--')
    plt.xlabel(&quot;Actual&quot;)
    plt.ylabel(&quot;Predicted&quot;)
    plt.title(&quot;Linear Regression Graph&quot;)
    plt.grid(True)
    plt.tight_layout()     #ensures the plot fits within the Tkinter window
    result_label.config(text=f&quot;Train MSE: {mse_train:.2f}\tTest MSE: {mse_test:.2f}&quot;)
    canvas = FigureCanvasTkAgg(plt.gcf(), master=window)     #converts the plot into a format that can be displayed in the Tkinter window
    canvas.draw()
    canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)     #adds the canvas widget to the Tkinter window.

train_button = ttk.Button(window, text=&quot;Train and Plot&quot;, command=train_and_plot)
train_button.pack(pady=10)
result_label = ttk.Label(window, text=&quot;&quot;)
result_label.pack()
window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=10740781036814253574&quot; alt=&quot;Tkinter_interface&quot;&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;train_and_plot&lt;/code&gt; function trains a linear regression model on the dataset, predicts the target values, calculates the mean squared error for both training and testing sets, and then plots the predicted values against the actual values using matplotlib. It also displays the calculated mean squared errors on your GUI window.&lt;/p&gt;
&lt;h2 id=&quot;advanced-widgets&quot;&gt;Advanced Widgets&lt;/h2&gt;
&lt;p&gt;Tkinter provides a wide range of widgets beyond the basic ones like labels and buttons. You can explore and utilize widgets like treeview, notebook, progressbar, etc. to create sophisticated user interfaces.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;treeview&lt;/strong&gt; to display hierarchical data, like a file explorer.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; import tkinter as tk
 from tkinter import ttk     #for themed widgets
 window = tk.Tk()
 window.geometry(&quot;640x300&quot;)
 tree = ttk.Treeview(window)
 tree[&quot;columns&quot;] = (&quot;Fruits&quot;, &quot;Quantity&quot;)
 tree.heading(&quot;#0&quot;, text=&quot;Sr. No.&quot;)     #First column (index=0) will be Sr. No.
 tree.heading(&quot;Fruits&quot;, text=&quot;Fruits&quot;)
 tree.heading(&quot;Quantity&quot;, text=&quot;Quantity (kg)&quot;)
 tree.insert(&quot;&quot;, tk.END, text=&quot;1&quot;, values=(&quot;Apple&quot;, 30))
 tree.insert(&quot;&quot;, tk.END, text=&quot;2&quot;, values=(&quot;Orange&quot;, 25))
 tree.insert(&quot;&quot;, tk.END, text=&quot;3&quot;, values=(&quot;Mango&quot;, 29))
 tree.pack()
 window.mainloop()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=17024339317789079325&quot; alt=&quot;treeview&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Treeview widget &lt;code&gt;tree&lt;/code&gt; consists of two columns: &quot;Fruits&quot; and &quot;Quantity (kg)&quot;. The &lt;code&gt;heading&lt;/code&gt; method sets headings for each column, and the &lt;code&gt;insert&lt;/code&gt; method adds items to the Treeview. Each item is inserted with a unique identifier &quot;Sr. No.&quot; and its corresponding values for &quot;Fruits&quot; and &quot;Quantity&quot; are entered.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;notebook&lt;/strong&gt; to organize your app into different tabs, like in a web browser.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; import tkinter as tk
 from tkinter import ttk     #for themed widgets
 window = tk.Tk()
 window.geometry(&quot;457x335&quot;)
 notebook = ttk.Notebook(window)
 tab1 = ttk.Frame(notebook)
 tab2 = ttk.Frame(notebook)
 tab3 = ttk.Frame(notebook)
 label1 = tk.Label(tab1, text=&quot;This is Tab 1&quot;)     #for tab 1
 label1.pack()
 entry2 = tk.Entry(tab2)     #for tab 2
 entry2.pack()
 check_var = tk.BooleanVar()
 check_button3 = tk.Checkbutton(tab3, text=&quot;This is Tab 3&quot;, variable=check_var)     #for tab 3
 check_button3.pack()
 notebook.add(tab1, text=&quot;Tab 1&quot;)
 notebook.add(tab2, text=&quot;Tab 2&quot;)
 notebook.add(tab3, text=&quot;Tab 3&quot;)
 notebook.pack()
 window.mainloop()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=14879740221736993260&quot; alt=&quot;Tab1&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=14632322578103106639&quot; alt=&quot;Tab2&quot;&gt;&lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=16524913512561924585&quot; alt=&quot;Tab3&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It creates a Notebook widget &lt;code&gt;notebook&lt;/code&gt;, which allows 3 tabs to be displayed, namely &lt;code&gt;Tab 1&lt;/code&gt;, &lt;code&gt;Tab 2&lt;/code&gt;, and &lt;code&gt;Tab 3&lt;/code&gt;, ceated using &lt;code&gt;ttk.Frame&lt;/code&gt;. &lt;code&gt;Tab 1&lt;/code&gt; contains a Label widget with the text &quot;This is Tab 1&quot;. &lt;code&gt;Tab 2&lt;/code&gt; contains an Entry widget for user input. &lt;code&gt;Tab 3&lt;/code&gt; contains a Checkbutton widget with the text &quot;This is Tab 3&quot;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;progressbar&lt;/strong&gt; to show how far along a task is, like when you're downloading a file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; import tkinter as tk
 from tkinter import ttk
 import time
    
 def start_task():
     progress_bar.start(10)     #start the progressbar (animation is updated every 10 milliseconds)
     window.after(3000, stop_task)     #simulate task completion after 3 seconds
    
 def stop_task():
     progress_bar.stop()      #stop the progressbar
    
 window = tk.Tk()
 window.geometry(&quot;457x335&quot;)
 progress_bar = ttk.Progressbar(window, orient=&quot;horizontal&quot;, length=200, mode=&quot;indeterminate&quot;)
 progress_bar.pack()
 start_button = tk.Button(window, text=&quot;Start Task&quot;, command=start_task)
 start_button.pack(pady=20)
 window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=17085322627996677804&quot; alt=&quot;Tkinter_progressbar&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When the &quot;Start Task&quot; button is clicked, it triggers the &lt;code&gt;start_task&lt;/code&gt; function, which starts the progress bar animation using the &lt;code&gt;start&lt;/code&gt; method. The &lt;code&gt;after&lt;/code&gt; method is used to schedule the &lt;code&gt;stop_task&lt;/code&gt; function to run after 3 seconds. The &lt;code&gt;stop_task&lt;/code&gt; function stops the progress bar animation using the &lt;code&gt;stop&lt;/code&gt; method.&lt;/p&gt;
&lt;h2 id=&quot;advanced-layout-management&quot;&gt;Advanced Layout Management&lt;/h2&gt;
&lt;p&gt;Advanced Layout Management can be used to make your Tkinter app look polished. Layout management helps you move widgets around and make your app look just the way you want using  &lt;code&gt;grid&lt;/code&gt;, &lt;code&gt;place&lt;/code&gt;, and &lt;code&gt;pack&lt;/code&gt; managers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Grid&lt;/strong&gt;&lt;br&gt;
You can place widgets in rows and columns, and they will organize neatly into place.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  import tkinter as tk
  window = tk.Tk()
  window.geometry(&quot;457x335&quot;)
  label1 = tk.Label(window, text=&quot;Subject&quot;)
  label2 = tk.Label(window, text=&quot;Marks&quot;)
  entry1 = tk.Entry(window)     #Widgets
  entry2 = tk.Entry(window)
  entry3 = tk.Entry(window)
  entry4 = tk.Entry(window)
  label1.grid(row=0, column=0)     #Layout
  label2.grid(row=0, column=1)
  entry1.grid(row=1, column=0)
  entry2.grid(row=1, column=1)
  entry3.grid(row=2, column=0)
  entry4.grid(row=2, column=1)
  window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=6534270145641510254&quot; alt=&quot;Tkinter_grid&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This code sets up 2 labels &lt;code&gt;Subject&lt;/code&gt; and &lt;code&gt;Marks&lt;/code&gt; and 4 entry widgets for data input. The layout is organized with &lt;code&gt;Subject&lt;/code&gt; in row 0, column 0, &lt;code&gt;Marks&lt;/code&gt; in row 0, column 1. Entry widgets &lt;code&gt;entry1&lt;/code&gt; and &lt;code&gt;entry2&lt;/code&gt; occupy row 1, columns 0 and 1 respectively, while &lt;code&gt;entry3&lt;/code&gt; and &lt;code&gt;entry4&lt;/code&gt; are in row 2, columns 0 and 1.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pack&lt;/strong&gt;&lt;br&gt;
You can stack widgets on top of each other or arrange them side by side, and Tkinter will figure out how to fit them all in.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  import tkinter as tk
  window = tk.Tk()
  window.geometry(&quot;457x335&quot;)
  button1 = tk.Button(window, text=&quot;Left&quot;)     #Widgets
  button2 = tk.Button(window, text=&quot;Top&quot;)
  button3 = tk.Button(window, text=&quot;Right&quot;)
  button4 = tk.Button(window, text=&quot;Bottom&quot;)
  button1.pack(side=tk.LEFT)     #Layout
  button2.pack(side=tk.TOP)
  button3.pack(side=tk.RIGHT)
  button4.pack(side=tk.BOTTOM)
  window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=15178167496495803908&quot; alt=&quot;Tkinter_pack&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The buttons &lt;code&gt;button1&lt;/code&gt;, &lt;code&gt;button2&lt;/code&gt;, &lt;code&gt;button3&lt;/code&gt; and &lt;code&gt;button4&lt;/code&gt; are positioned by providing the &lt;code&gt;side&lt;/code&gt; parameter with values &lt;code&gt;tk.LEFT&lt;/code&gt;, &lt;code&gt;tk.TOP&lt;/code&gt;, &lt;code&gt;tk.RIGHT&lt;/code&gt;, or &lt;code&gt;tk.BOTTOM&lt;/code&gt; respectively.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Place&lt;/strong&gt;&lt;br&gt;
You can specify exactly where you want each widget to go by giving it coordinates, like x and y coordinates on a graph.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  import tkinter as tk
  window = tk.Tk()
  window.geometry(&quot;457x335&quot;)
  label1 = tk.Label(window, text=&quot;x_50_y_50&quot;)     #Widgets
  label2 = tk.Label(window, text=&quot;x_200_y_200&quot;)
  label1.place(x=50, y=50)     #Layout
  label2.place(x=200, y=200)
  window.mainloop()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=11723976143771039796&quot; alt=&quot;Tkinter_place&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;place&lt;/code&gt; method is used to position label widgets. &lt;code&gt;label1&lt;/code&gt; is placed at coordinates (50, 50), and &lt;code&gt;label2&lt;/code&gt; is placed at coordinates (200, 200).&lt;/p&gt;
&lt;h2 id=&quot;file-handling&quot;&gt;File Handling&lt;/h2&gt;
&lt;p&gt;Tkinter facilitates file handling through the &lt;code&gt;filedialog&lt;/code&gt; tool, enabling users to interactively select files on their computer. With this feature, your application can support tasks like creating, opening, saving, and editing various file types such as documents, images, or spreadsheets.&lt;/p&gt;
&lt;p&gt;Let's understand this using an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import tkinter as tk
from tkinter import filedialog

def open_file():
    file_path = filedialog.askopenfilename()     #opens a dialog window to select an existing file or create a new one
    if not file_path:
        return
    with open(file_path, 'a+') as file:     #'a+' to append the text to the file
        file.write(&quot;January\n&quot;)
        file.write(&quot;February\n&quot;)
        file.write(&quot;March\n&quot;)
        file.write(&quot;April\n&quot;)
        file.write(&quot;May\n&quot;)
    status_label.config(text=f&quot;File '{file_path}' has been written and closed.&quot;)

window = tk.Tk()
window.geometry(&quot;457x335&quot;)
window.title(&quot;File Writer&quot;)
open_button = tk.Button(window, text=&quot;Open a File&quot;, command=open_file)
open_button.pack(pady=20)
status_label = tk.Label(window, text=&quot;&quot;)
status_label.pack()
root.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=16945057073417130965&quot; alt=&quot;file&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=2325960918843338371&quot; alt=&quot;file_open_1&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=15519562952456146282&quot; alt=&quot;file_open_2&quot;&gt;&lt;/p&gt;
&lt;p&gt;When clicked, the button &quot;Open a File&quot; triggers the &lt;code&gt;open_file&lt;/code&gt; function, which opens a dialog window allowing you to select an existing file or create a new one. If a file is selected, the code appends the strings &quot;January&quot;, &quot;February&quot;...&quot;May&quot; to the file and the file is closed. The &lt;code&gt;status_label&lt;/code&gt; is then updated to display a message confirming the file write operation.&lt;/p&gt;
&lt;div class=&quot;div-blue&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Note:&lt;/span&gt;  &lt;span class=&quot;alert-body&quot;&gt; The file will automatically be closed when the `with` block is exited. However, you may explicitly close the file by calling `file.close()`.&lt;/span&gt; &lt;/div&gt;
&lt;h2 id=&quot;modal-and-modeless-dialogs&quot;&gt;Modal and Modeless Dialogs&lt;/h2&gt;
&lt;p&gt;Tkinter offers both modal and modeless dialogs, ideal for user input, confirmation messages, or notifications. The &lt;code&gt;tkinter.messagebox&lt;/code&gt; module provides standard message boxes, while custom dialog windows can be created using &lt;code&gt;Toplevel&lt;/code&gt; widgets.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modal dialogs&lt;/strong&gt; are windows that require the user to interact with them before returning to the main application window. They typically block interaction with other windows in the application until they are closed.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  import tkinter as tk
  from tkinter import messagebox

  def show_modal_dialog():
      messagebox.showinfo(&quot;Modal Dialog&quot;, &quot;Pay attention to this dialog box!&quot;)     #does not let you proceed until you click the &quot;OK&quot; button

  window = tk.Tk()
  window.geometry(&quot;457x335&quot;)
  window.title(&quot;Modal Dialog Example&quot;)
  modal_button = tk.Button(window, text=&quot;Click me&quot;, command=show_modal_dialog)
  modal_button.pack(padx=20, pady=10)
  window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=5781727160550960337&quot; alt=&quot;Tkinter_modal_dialog&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modeless dialogs&lt;/strong&gt; are windows that allow the user to interact with both the dialog and the main application window simultaneously. They do not block interaction with other windows in the application, allowing the user to switch between them freely.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  import tkinter as tk

  def show_modeless_dialog():
      modeless_dialog = tk.Toplevel(window)     #allows you to interact with other open windows
      modeless_dialog.title(&quot;Modeless Dialog&quot;)
      modeless_dialog.geometry(&quot;250x100&quot;)
      label = tk.Label(modeless_dialog, text=&quot;Have a nice day!&quot;)
      label.pack(padx=20, pady=10)

  window = tk.Tk()
  window.geometry(&quot;457x335&quot;)
  window.title(&quot;Modeless Dialog Example&quot;)
  modeless_button = tk.Button(window, text=&quot;Click me&quot;, command=show_modeless_dialog)
  modeless_button.pack(padx=20, pady=10)
  window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=1548469847260034179&quot; alt=&quot;Tkinter_modaless_dialog&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When clicked, the button &quot;Click me&quot; triggers the &lt;code&gt;show_modeless_dialog&lt;/code&gt; function, which creates a modeless dialog box using the &lt;code&gt;Toplevel&lt;/code&gt; widget. It will not hinder your interaction with the other windows.&lt;/p&gt;
&lt;div class=&quot;div-green&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Tip:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt; Using a class for modeless dialogs can organize and encapsulate dialog functionality, particularly for more intricate dialogs with multiple components and interactions.&lt;/span&gt; &lt;/div&gt;
&lt;h2 id=&quot;conclusion-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Tkinter&lt;/strong&gt; is a versatile Python &lt;strong&gt;GUI&lt;/strong&gt; framework that enhances user interaction and functionality. With features like &lt;strong&gt;custom themes&lt;/strong&gt;, &lt;strong&gt;threading&lt;/strong&gt;, &lt;strong&gt;file handling&lt;/strong&gt;, &lt;strong&gt;dialogs&lt;/strong&gt;, &lt;strong&gt;layout management&lt;/strong&gt;, &lt;strong&gt;advanced widgets&lt;/strong&gt;, and integration with libraries like Matplotlib and scikit-learn, Tkinter empowers developers to create dynamic desktop applications. By leveraging these capabilities, developers can craft unique GUIs that elevate user experience, making Tkinter a top choice for Python GUI projects.&lt;/p&gt;
</description>
<category>Project Dev</category>
<guid isPermaLink="true">https://coderlegion.com/253/exploring-more-in-tkinter</guid>
<pubDate>Tue, 23 Apr 2024 21:35:28 +0000</pubDate>
</item>
<item>
<title>Building a Calculator using tkinter</title>
<link>https://coderlegion.com/210/building-a-calculator-using-tkinter</link>
<description>&lt;p&gt;When working on a basic calculator with &lt;strong&gt;Tkinter&lt;/strong&gt;, a widely-used GUI toolkit for &lt;strong&gt;Python&lt;/strong&gt;, Tkinter streamlines the incorporation of user-friendly elements such as buttons, entries, grids, and custom styles that are necessary for crafting graphical user interfaces, making it particularly well-suited for applications. Its simplicity and efficiency in managing user interactions make it an ideal choice for projects of this nature.&lt;/p&gt;
&lt;h2 id=&quot;creating-the-calculator&quot;&gt;Creating the Calculator&lt;/h2&gt;
&lt;p&gt;Now let us actually dive into the process of building the calculator, one step at a time. All the required steps are given below; follow them one by one, and you will be able to develop an efficient and interactive calculator.&lt;/p&gt;
&lt;h3 id=&quot;step-1-setting-up-environment&quot;&gt;Step 1: Setting Up Environment&lt;/h3&gt;
&lt;p&gt;Before we start building our calculator, ensure that you have Python installed on your system. To do so, the following section gives a short guide on the steps to be followed for different platforms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For Windows:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download and install Python from the &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.python.org/downloads/&quot;&gt;official website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify by running the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; python --version
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;For Linux:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open terminal and copy and paste the code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; sudo apt-get update
 sudo apt-get install python3
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once installed verify by running the following command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; python --version
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;For MacOs:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download and install Python from the &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.python.org/downloads/macos/&quot;&gt;official website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;For reference &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/using/mac.html&quot;&gt;Steps to install python on MacOs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Next, we need to install Tkinter, which is included with Python by default. So, there's no need to install it separately&lt;/p&gt;
&lt;h3 id=&quot;step-2-importing-libraries&quot;&gt;Step 2: Importing Libraries&lt;/h3&gt;
&lt;p&gt;In Python, the tkinter module is used for creating GUI applications. &lt;br&gt;
Now let's import these required libraries along with other required modules:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import tkinter as tk
from tkinter import messagebox
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;tkinter&lt;/strong&gt;: This module provides classes and functions for creating GUI applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;messagebox&lt;/strong&gt;: This submodule allows us to display message boxes for showing information or prompting the user for confirmation.&lt;/p&gt;
&lt;h3 id=&quot;step-3-creating-the-calculator-class&quot;&gt;Step 3: Creating the Calculator Class&lt;/h3&gt;
&lt;p&gt;Create a class called  &lt;code&gt;class Calculator&lt;/code&gt; that will represent our calculator application:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Calculator:
    def __init__(self, master):
        self.master = master
        self.master.title(&quot;Simple Calculator&quot;)
        self.master.geometry(&quot;300x400&quot;)
        self.master.resizable(False, False)
        self.create_widgets()

    def create_widgets(self):
        # Create entry widget for displaying input and results
        self.entry = tk.Entry(self.master, width=20, font=('Arial', 14), bd=5, justify=&quot;right&quot;)
        self.entry.grid(row=0, column=0, columnspan=4, padx=10, pady=10)

        # Define buttons
        buttons = [
            ('7', 1, 0), ('8', 1, 1), ('9', 1, 2), ('/', 1, 3),
            ('4', 2, 0), ('5', 2, 1), ('6', 2, 2), ('*', 2, 3),
            ('1', 3, 0), ('2', 3, 1), ('3', 3, 2), ('-', 3, 3),
            ('0', 4, 0), ('.', 4, 1), ('=', 4, 2), ('+', 4, 3)
        ]

        # Create buttons using a loop
        for (text, row, col) in buttons:
            button = tk.Button(self.master, text=text, width=5, height=2, 
            font=('Arial', 14), command=lambda t=text: self.on_button_click(t))
            button.grid(row=row, column=col, padx=5, pady=5)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Initialization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;init&lt;/code&gt; method in the Calculator class sets up the basic features of the calculator when it's first created. It's like laying out the blueprint for how the calculator will look and work. The &lt;code&gt;master&lt;/code&gt; part helps position the calculator in the right place on the screen. &lt;code&gt;self.master.title(&quot;Simple Calculator&quot;)&lt;/code&gt; gives the calculator window a name, like &quot;Simple Calculator&quot;. The &lt;code&gt;self.master.geometry(&quot;300x400&quot;)&lt;/code&gt; part determines how big the calculator window will be, making sure it's neither too small nor too big. The line&lt;code&gt;self.master.resizable(False, False)&lt;/code&gt; prevents users from changing the size of the calculator window, keeping it neat and tidy. Finally, &lt;code&gt;self.create_widgets()&lt;/code&gt; starts the process of actually creating all the buttons and numbers you see on the calculator screen. It's like setting up the stage before the show begins. So, with all these steps, the calculator is ready to go when you open it up!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Widget Creation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;create_widgets&lt;/code&gt; method orchestrates the construction of the calculator's user interface, beginning with the establishment of an entry widget named &lt;code&gt;self.entry&lt;/code&gt; for displaying input and results, meticulously configured with specific attributes such as width, font size, border width, and text alignment. Positioned within the window using the grid method, this entry widget ensures clarity and organization of numerical data. Subsequently, utilizing a list named &lt;code&gt;buttons&lt;/code&gt; containing tuples of button details, the method dynamically generates button widgets for each entry within the list. These buttons, equipped with attributes such as text labels and dimensions, are seamlessly integrated into the window using the grid method, with each button assigned a command to execute the &lt;code&gt;on_button_click&lt;/code&gt; method upon interaction, passing the corresponding button text as an argument. Through meticulous placement and configuration, the &lt;code&gt;create_widgets&lt;/code&gt; method establishes a coherent and functional user interface, essential for intuitive interaction and efficient calculation.&lt;/p&gt;
&lt;h3 id=&quot;step-4-implementing-button-click-functionality&quot;&gt;Step 4: Implementing Button Click Functionality&lt;/h3&gt;
&lt;p&gt;Next, we define the &lt;code&gt;on_button_click()&lt;/code&gt; method to handle button clicks:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def on_button_click(self, text):
     if text == '=':
          try:
              result = eval(self.entry.get())
              self.entry.delete(0, tk.END)
              self.entry.insert(tk.END, str(result))
          except Exception as e:
              messagebox.showerror(&quot;Error&quot;, &quot;Invalid Input&quot;)

          elif text == 'C':
              self.entry.delete(0, tk.END)

          else:
              self.entry.insert(tk.END, text)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In this block of code, several conditional statements and actions are executed based on the text of the clicked button within the calculator interface. First, there's a check to see if the button text is equal to '=' (the equal sign). If so, the mathematical expression entered in the entry widget (self.entry) is evaluated using the &lt;code&gt;eval()&lt;/code&gt; function, and the result is stored in the &lt;code&gt;result&lt;/code&gt; variable. The contents of the entry widget are then cleared using &lt;code&gt;self.entry.delete(0, tk.END)&lt;/code&gt;, and the calculated result is inserted into the entry widget using &lt;code&gt;self.entry.insert(tk.END, str(result))&lt;/code&gt;. In case an exception occurs during evaluation, it's caught using a try-except block, and an error message box is displayed using &lt;code&gt;messagebox.showerror(&quot;Error&quot;, &quot;Invalid Input&quot;)&lt;/code&gt;. Lastly, the text of the clicked button is inserted into the entry widget at the end (tk.END) using &lt;code&gt;self.entry.insert(tk.END, text)&lt;/code&gt;, allowing users to append their input string. These actions ensure proper functionality and user feedback within the calculator interface, facilitating smooth interaction and accurate computation.&lt;/p&gt;
&lt;h3 id=&quot;step-5-driver-function&quot;&gt;Step 5: Driver Function&lt;/h3&gt;
&lt;p&gt;Lastly, we need to create an instance of the Calculator class and run the &lt;code&gt;main&lt;/code&gt; event loop:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; if __name__ == &quot;__main__&quot;:
     root = tk.Tk()
     app = Calculator(root)
     root.mainloop()   
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The line &lt;code&gt; if __name__ == &quot;__main__&quot;&lt;/code&gt; serves as a conditional statement that ensures that the subsequent code block is executed only if the Python script is directly run by the interpreter, rather than being imported as a module into another script. Following this condition, &lt;code&gt;root = tk.Tk()&lt;/code&gt; initializes a new instance of the Tkinter Tk class, establishing the main window or root window for the graphical user interface (GUI) application. This window acts as a container for all other GUI elements to be displayed. Subsequently, &lt;code&gt;app = Calculator(root)&lt;/code&gt; creates an instance of the Calculator class, utilizing the root window as an argument, thereby initializing the calculator application within this main window. Lastly, &lt;code&gt;root.mainloop()&lt;/code&gt; initiates the Tkinter event loop, a critical component that continuously listens for user interactions, such as button clicks and window resizing, effectively maintaining the responsiveness of the GUI. This function call essentially blocks further script execution until the main window is closed by the user, ensuring the seamless functioning of the GUI application.&lt;/p&gt;
&lt;h3 id=&quot;step-6-outcome-of-implementation&quot;&gt;Step 6: Outcome of Implementation&lt;/h3&gt;
&lt;p&gt;  &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=7603950783710353489&quot; alt=&quot;Outcome&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;code-snippet&quot;&gt;Code snippet&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;import tkinter as tk
from tkinter import messagebox

class Calculator:
    def __init__(self, master):
        self.master = master
        self.master.title(&quot;Simple Calculator&quot;)
        self.master.geometry(&quot;300x400&quot;)
        self.master.resizable(False, False)
        self.create_widgets()

    # creating the widgets
    
    def create_widgets(self):
        # Create entry widget for displaying input and results
        self.entry = tk.Entry(
            self.master, width=20, font=(&quot;Arial&quot;, 14), bd=5, justify=&quot;right&quot;
        )
        self.entry.grid(row=0, column=0, columnspan=4, padx=10, pady=10)

        # Define buttons
        buttons = [
            (&quot;7&quot;, 1, 0),
            (&quot;8&quot;, 1, 1),
            (&quot;9&quot;, 1, 2),
            (&quot;/&quot;, 1, 3),
            (&quot;4&quot;, 2, 0),
            (&quot;5&quot;, 2, 1),
            (&quot;6&quot;, 2, 2),
            (&quot;*&quot;, 2, 3),
            (&quot;1&quot;, 3, 0),
            (&quot;2&quot;, 3, 1),
            (&quot;3&quot;, 3, 2),
            (&quot;-&quot;, 3, 3),
            (&quot;0&quot;, 4, 0),
            (&quot;.&quot;, 4, 1),
            (&quot;=&quot;, 4, 2),
            (&quot;+&quot;, 4, 3),
        ]

        # Create buttons using a loop
        for text, row, col in buttons:
            button = tk.Button(
                self.master,
                text=text,
                width=5,
                height=2,
                font=(&quot;Arial&quot;, 14),
                command=lambda t=text: self.on_button_click(t),
            )
            button.grid(row=row, column=col, padx=5, pady=5)

    # funtion creation for on click feature
    def on_button_click(self, text):
        if text == &quot;=&quot;:
            try:
                result = eval(self.entry.get())
                self.entry.delete(0, tk.END)
                self.entry.insert(tk.END, str(result))
            except Exception as e:
                messagebox.showerror(&quot;Error&quot;, &quot;Invalid Input&quot;)

        elif text == &quot;C&quot;:
            self.entry.delete(0, tk.END)

        else:
            self.entry.insert(tk.END, text)

    # main funtion is defined                
    if __name__ == &quot;__main__&quot;:
        root = tk.Tk()
        app = Calculator(root)
        root.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;understanding-code-functionality&quot;&gt;Understanding Code Functionality&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When the calculator starts, it creates a window with an entry widget. This widget is where you can input numbers and view the results.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The calculator has buttons for digits from 0 to 9, the decimal point '.', and arithmetic operations like addition '+', subtraction '-', multiplication '*', and division '/'. These buttons are arranged in a grid layout.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;div-green&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Tip:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt;Implement input validation to avoid potential security vulnerabilities or crashes. &lt;/span&gt; &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When a button is clicked, it triggers the &lt;code&gt;on_button_click&lt;/code&gt; function. If the button is an arithmetic operation or a digit, it adds that value to the entry widget. If the button is '=' (equal sign), it evaluates the expression in the entry widget and displays the result. If it's 'C' (clear), it clears the entry widget.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When '=' is pressed, it tries to evaluate the expression entered in the entry widget using Python's &lt;code&gt;eval()&lt;/code&gt; function. If the expression is valid, it computes the result and displays it in the entry widget. If there's an error, such as invalid input or division by zero, it shows an error message.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;div-red&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Warning:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt;Avoid using the eval() function with untrusted input to prevent code injection vulnerabilities.&lt;/span&gt;  &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The program keeps running in a loop, waiting for user interactions, until the window is closed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users can input numbers and perform arithmetic operations by clicking the respective buttons. They can clear the input by clicking 'C' and get the result by clicking '='.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;calculator-functionality-flowchart&quot;&gt;Calculator Functionality Flowchart&lt;/h2&gt;
&lt;p&gt;Following is an illustration of the functionality of a simple calculator program through a clear and logical flowchart.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=14107652295060674798&quot; alt=&quot;Flowchart&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;testing-result&quot;&gt;Testing Result&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=250390329310505356&quot; alt=&quot;Testing 1&quot;&gt;        &lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=4300637587976812647&quot; alt=&quot;Testing 2&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;possible-errors-that-might-occur&quot;&gt;Possible Errors that might occur&lt;/h2&gt;
&lt;p&gt;In building a calculator using Tkinter, potential errors include syntax mistakes, input validation issues, and challenges with complex operations. Effective debugging is crucial for ensuring the calculator functions reliably. Have a look at some of the problems along with their solutions that are listed below.&lt;/p&gt;
&lt;h3 id=&quot;division-by-zero-error-&quot;&gt;Division by zero error:&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: If the user divides by zero, Python will raise a ZeroDivisionError.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=5214973538443658959&quot; alt=&quot;Invalid Input&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Handle division by zero within the try-except block.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;try:
    result = eval(self.entry.get())
    if result == float('inf'):
         messagebox.showerror(&quot;Error&quot;, &quot;Division by zero&quot;)
    else:
        self.entry.delete(0, tk.END)
        self.entry.insert(tk.END, str(result))
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;syntax-error-in-evaluation-&quot;&gt;Syntax error in evaluation:&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: If the user enters an invalid expression that can't be evaluated, it will raise a SyntaxError.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=11542053887820982095&quot; alt=&quot;Invalid Input 2&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Catch SyntaxError and display an appropriate error message.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;except SyntaxError:
messagebox.showerror(&quot;Error&quot;, &quot;Invalid Expression&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;nameerror-due-to-undefined-variable-&quot;&gt;NameError due to undefined variable:&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: The code checks for the '=' and 'C' buttons, but they're not defined in the button list.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Add the '=' and 'C' buttons to the list with their respective positions.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;buttons = [
   ...
   ('=', 4, 2), ('C', 4, 0)
]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;missing-import-statement-&quot;&gt;Missing import statement:&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: The code uses messagebox without importing it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Import messagebox from tkinter.&lt;/p&gt;
&lt;p&gt;from tkinter import messagebox&lt;/p&gt;
&lt;h3 id=&quot;unsupported-operations-&quot;&gt;Unsupported operations:&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: The calculator allows arbitrary evaluation of expressions &lt;code&gt;using eval()&lt;/code&gt;, which can lead to unintended consequences.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Restrict the input to a certain format or implement a safer method for evaluation, such as parsing the expression manually.&lt;br&gt;
Here's a safer approach to evaluate expressions using &lt;code&gt;ast.literal_eval()&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import ast
def evaluate_expression(self, expression):
    try:
        return ast.literal_eval(expression)
    except (SyntaxError, ValueError):
        raise ValueError(&quot;Invalid expression&quot;)
  
def on_button_click(self, text):
    if text == '=':
        try:
            result = self.evaluate_expression(self.entry.get())
            self.entry.delete(0, tk.END)
            self.entry.insert(tk.END, str(result))
        except ValueError as e:
            messagebox.showerror(&quot;Error&quot;, str(e))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion-&quot;&gt;Conclusion:&lt;/h2&gt;
&lt;p&gt;In conclusion, developing a simple calculator using &lt;strong&gt;Tkinter&lt;/strong&gt; in Python, offers a practical introduction to GUI application development. Tkinter's intuitive design, coupled with its &lt;strong&gt;cross-platform compatibility&lt;/strong&gt;, empowers developers to create interactive interfaces effortlessly. By leveraging Tkinter's event-driven model, we constructed a calculator with &lt;strong&gt;basic arithmetic operations&lt;/strong&gt;, &lt;strong&gt;error handling&lt;/strong&gt;, and &lt;strong&gt;clear functionality&lt;/strong&gt;. Utilizing widgets like &lt;strong&gt;Entry&lt;/strong&gt; and &lt;strong&gt;Button&lt;/strong&gt;, we orchestrated a user-friendly interface, enhancing accessibility and the user experience.&lt;/p&gt;
&lt;p&gt;Throughout the process, we capitalized on &lt;strong&gt;object-oriented programming&lt;/strong&gt; principles, encapsulating functionality within the Calculator class. This modular approach facilitates code organization and maintenance, promoting scalability and extensibility. Moreover, the integration of error handling mechanisms, such as &lt;strong&gt;try-except blocks&lt;/strong&gt; and &lt;strong&gt;message boxes&lt;/strong&gt;, underscores the importance of robustness in software design. These measures ensure graceful handling of unexpected inputs, enhancing the calculator's reliability and user confidence.&lt;/p&gt;
&lt;p&gt;By adhering to best practices and leveraging Tkinter's capabilities, we've crafted a functional calculator application that demonstrates the synergy between Python's versatility and Tkinter's simplicity. This endeavor serves as a springboard for aspiring developers to delve deeper into GUI programming and explore the myriad possibilities of Python's ecosystem.&lt;/p&gt;
</description>
<category>Project Dev</category>
<guid isPermaLink="true">https://coderlegion.com/210/building-a-calculator-using-tkinter</guid>
<pubDate>Tue, 02 Apr 2024 20:46:16 +0000</pubDate>
</item>
<item>
<title>Tkinter ToDo GUI Application (Step by Step Guide)</title>
<link>https://coderlegion.com/208/tkinter-todo-gui-application-step-by-step-guide</link>
<description>&lt;p&gt;In this article, we'll dive into the world of &lt;strong&gt;Tkinter&lt;/strong&gt;, a popular GUI (Graphical User Interface) toolkit for Python, and harness its capabilities to build a robust &lt;strong&gt;to-do list application&lt;/strong&gt; from scratch. I'll walk you through each step, from designing a &lt;strong&gt;user-friendly interface&lt;/strong&gt; to adding crucial functions like &lt;strong&gt;task creation&lt;/strong&gt;, &lt;strong&gt;deletion&lt;/strong&gt; and &lt;strong&gt;prioritization&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;project-prerequisites&quot;&gt;Project Prerequisites&lt;/h2&gt;
&lt;p&gt;Before starting to build a to-do list app with Tkinter, make sure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Python Installed: Have Python installed on your computer. Tkinter comes included with Python, so no separate installation is needed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For Windows&lt;/strong&gt;: Download and install Python from the &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.python.org/downloads/&quot;&gt;official website&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For Ubuntu&lt;/strong&gt;: You can download Python using the terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     sudo apt update
     sudo apt install python3
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For MacOS&lt;/strong&gt;: You can download Python using Homebrew:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     brew install python3
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;div-blue&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Note:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt; To confirm the installation, enter `python3 --version` in the terminal.&lt;/span&gt; &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Text Editor or IDE: Select a preferred text editor or IDE, such as Visual Studio Code or PyCharm, to write and execute Python code.&lt;/li&gt;
&lt;li&gt;Basic Python Skills: Learn core Python concepts: variables, data types, functions, and control flow.&lt;/li&gt;
&lt;li&gt;Tkinter Basics: Basic familiarity with Tkinter, including widgets and event handling, can be useful. You can learn through &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/tkinter.html&quot;&gt;Tkinter documentation&lt;/a&gt; or &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/190/introduction-to-tkinter-library-in-python&quot;&gt;this article&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;designing-the-user-interface&quot;&gt;Designing the User Interface&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Importing necessary Libraries&lt;/strong&gt;&lt;br&gt;
Tkinter (&lt;code&gt;tk&lt;/code&gt;) is the go-to module for GUI applications, complemented by &lt;code&gt;ttk&lt;/code&gt; for themed widgets, offering a modern appearance. Utilizing the &lt;code&gt;messagebox&lt;/code&gt; module enables the display of user interaction messages. Additionally, SQLite3, a lightweight database engine, handles local data storage and management for our tasks.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Creating the Main Window&lt;/strong&gt;&lt;br&gt;
We create the main window using Tkinter, set its size, and instantiate the &lt;code&gt;TodoListApp&lt;/code&gt; class (discussed later) to integrate its functionalities. Finally, we start the event loop for user interaction.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;window = tk.Tk()
window.geometry(&quot;457x335&quot;)
app = TodoListApp(window)
window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Adding a Title and necessary Frames and Labels&lt;/strong&gt;&lt;br&gt;
You can add a catchy title to your To-Do app. I have named it &quot;Todo List App&quot;. The app features two frames: one for entering new tasks and another for displaying existing ones. The new task frame includes labels for &quot;Task Name,&quot; &quot;Priority,&quot; and &quot;Deadline.&quot;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;self.window = window
window.title(&quot;Todo List App&quot;)
entry_frame = ttk.Frame(self.window)
entry_frame.pack(padx=10, pady=10, fill=tk.X)
ttk.Label(entry_frame, text=&quot;Task name:&quot;).grid(row=0, column=0, padx=5, pady=5)
ttk.Label(entry_frame, text=&quot;Priority:&quot;).grid(row=1, column=0, padx=5, pady=5)
ttk.Label(entry_frame, text=&quot;Deadline:&quot;).grid(row=2, column=0, padx=5, pady=5)
self.task_list_frame = ttk.Frame(self.window)
self.task_list_frame.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Adding Widgets for Task Entry&lt;/strong&gt;&lt;br&gt;
To add a new task, provide the task name, priority, and deadline. All tasks require a name and set priority. For urgent tasks, a deadline is mandatory.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;self.task_text = tk.StringVar()
self.task_entry = ttk.Entry(entry_frame, textvariable=self.task_text)
self.task_entry.grid(row=0, column=1, padx=5, pady=5)
ttk.Radiobutton(entry_frame, text=&quot;Urgent&quot;, variable=self.priority_selection, value=&quot;Urgent&quot;).grid(row=1, column=1, padx=5, pady=5)
ttk.Radiobutton(entry_frame, text=&quot;General&quot;, variable=self.priority_selection, value=&quot;General&quot;).grid(row=1, column=2, padx=5, pady=5)
self.task_deadline = tk.StringVar()
self.deadline_entry = ttk.Entry(entry_frame, textvariable=self.task_deadline)
self.deadline_entry.grid(row=2, column=1, padx=5, pady=5)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code snippet sets up the entry interface for users to input task details. It includes entry fields for users to specify the task name, radio buttons to specify the priority level (either &quot;Urgent&quot; or &quot;General&quot;), and another entry field for the deadline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adding Buttons&lt;/strong&gt;&lt;br&gt;
You will need 2 buttons to be included: one for adding a new task and another for deleting an existing task.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;add_button = ttk.Button(entry_frame, text=&quot;Add Task&quot;, command=self.add_task)
add_button.grid(row=3, column=0, columnspan=3, padx=5, pady=5)
delete_button = ttk.Button(self.window, text=&quot;Delete Tasks&quot;, command=self.delete_tasks)
delete_button.pack(pady=5)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, the first button, &quot;Add Task,&quot; triggers the &lt;code&gt;add_task&lt;/code&gt; method when clicked. The second button, &quot;Delete Tasks,&quot; triggers the &lt;code&gt;delete_tasks&lt;/code&gt; method upon activation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Displaying the List of Entered Tasks&lt;/strong&gt;&lt;br&gt;
Every task entered into the database table is retrieved and processed. A separate frame is generated for each task, within which labels are utilized to showcase the task details. Furthermore, a checkbutton is included for every task, enabling users to mark tasks as complete once they are fulfilled.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for task in tasks:
        task_id = task[0]
        task_text = task[1]
        task_priority = task[2]
        task_deadline = task[4]
        task_frame = ttk.Frame(self.task_list_frame)
        task_frame.pack(fill=tk.X, padx=5, pady=2)
        task_checkbutton = ttk.Checkbutton(task_frame, command=lambda id=task_id: self.select_task(id))
        task_checkbutton.grid(row=0, column=0)
        if task_priority == &quot;Urgent&quot; or (task_priority == &quot;General&quot; and task_deadline):
            task_label = ttk.Label(task_frame, text=(task_text+&quot;    (&quot;+task_deadline+&quot;)&quot;))
        else:
            task_label = ttk.Label(task_frame, text=task_text)
        task_label.grid(row=0, column=1, padx=5)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For each task, relevant details like &lt;code&gt;ID&lt;/code&gt;, &lt;code&gt;task&lt;/code&gt;, &lt;code&gt;priority&lt;/code&gt;, and &lt;code&gt;deadline&lt;/code&gt; are extracted. Frames are created to organize task information neatly. &lt;code&gt;task_checkbutton&lt;/code&gt; enable task completion marking, while task names are displayed as Labels. If urgent or with a deadline, task names include this information.&lt;/p&gt;
&lt;p&gt;This represents the expected appearance of the GUI:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=4674483976126799680&quot; alt=&quot;todo_gui&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;div-green&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Tip:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt; Customize labels with different colors based on task priorities. See code at the end.&lt;/span&gt; &lt;/div&gt;
&lt;h2 id=&quot;implementing-functionality&quot;&gt;Implementing Functionality&lt;/h2&gt;
&lt;p&gt;The following functions are defined in the &lt;code&gt;TodoListApp&lt;/code&gt; class.&lt;/p&gt;
&lt;div class=&quot;div-green&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Tip:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt; It is best to encapsulate multiple functions in a class.&lt;/span&gt; &lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Create a Table in the SQLite Database&lt;/strong&gt;&lt;br&gt;
To store your tasks effectively, a database is necessary. We will proceed by creating a table within an SQLite database for this purpose.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;self.c.execute('''CREATE TABLE IF NOT EXISTS tasks (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    task TEXT NOT NULL,
                    priority TEXT,
                    initial_priority TEXT,
                    deadline TEXT
                )''')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;self.conn.commit()&lt;br&gt;
The &lt;code&gt;create_table&lt;/code&gt; function sets up a table named &lt;code&gt;tasks&lt;/code&gt; in the SQLite database. It includes columns for task details such as &lt;code&gt;ID&lt;/code&gt;, &lt;code&gt;task&lt;/code&gt; (name), &lt;code&gt;priority&lt;/code&gt;, &lt;code&gt;initial priority&lt;/code&gt;, and &lt;code&gt;deadline&lt;/code&gt;. This function ensures that the necessary table structure exists for storing task information and commits the changes to the database.&lt;/p&gt;
&lt;div class=&quot;div-red&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Caution:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt; Ensure that there is no existing table named `tasks` in the database as it may lead to data loss or corruption if the existing table structure is overwritten or altered unintentionally.&lt;/span&gt; &lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Function to Add Tasks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To add a new task, provide the task name, priority, and deadline. All tasks require a name and set priority. For urgent tasks, a deadline is mandatory.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;task_text = self.task_text.get().strip()
task_priority = self.priority_selection.get()
task_deadline = self.task_deadline.get().strip()
if task_text and (task_priority == &quot;General&quot; or (task_priority == &quot;Urgent&quot; and task_deadline)):
    self.c.execute(&quot;INSERT INTO tasks (task, priority, initial_priority, deadline) VALUES (?, ?, ?, ?)&quot;, (task_text, task_priority, task_priority, task_deadline))
    self.conn.commit()
    self.load_tasks()
    self.task_text.set(&quot;&quot;)
    self.priority_selection.set(&quot;&quot;)
    self.task_deadline.set(&quot;&quot;)
else:
    messagebox.showwarning(&quot;Warning&quot;, &quot;Task or Priority cannot be empty, and Urgent task must have a deadline.&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It collects task details from input fields. If the name isn't empty and the priority is valid, the task is added to the database. After insertion, the task list refreshes, and input fields reset. If inputs are invalid, a warning message appears.&lt;/p&gt;
&lt;p&gt;If task name or priority or deadline for an urgent task is not entered:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=9225277434351519448&quot; alt=&quot;todo_error_insert&quot;&gt;&lt;/p&gt;
&lt;p&gt;After successfully entering a task:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=5445632491705201640&quot; alt=&quot;todo_insert&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Function to Delete Tasks&lt;/strong&gt;&lt;br&gt;
To delete tasks, you click the &quot;Delete Tasks&quot; button, opening a window where you select tasks for removal. At least one task must be chosen before clicking &quot;Delete.&quot; After confirmation, the selected tasks are deleted from the SQLite table.&lt;/p&gt;
&lt;p&gt;This opens a Toplevel window:  &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;delete_window = tk.Toplevel(self.window)
delete_window.geometry(&quot;457x335&quot;)
delete_window.title(&quot;Delete Tasks&quot;)
task_list_frame = ttk.Frame(delete_window)     #to contain the list of tasks
task_list_frame.pack(padx=10, pady=10)
self.c.execute(&quot;SELECT id, task FROM tasks&quot;)      #retrieve tasks from database
tasks = self.c.fetchall()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This displays the retrieved tasks with checkboxes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for task_id, task_text in tasks:
    task_checkbutton = ttk.Checkbutton(task_list_frame, text=task_text, command=lambda id=task_id: update_selected_tasks(id))
    task_checkbutton.pack(anchor=&quot;w&quot;, padx=5, pady=2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=13763355634516336338&quot; alt=&quot;todo_del_window1&quot;&gt;&lt;/p&gt;
&lt;p&gt;This function removes the selected tasks from the table after verifying that at least one task has been chosen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if not selected_task_ids:
     messagebox.showwarning(&quot;Warning&quot;, &quot;No tasks selected for deletion.&quot;)
     return
for task_id in selected_task_ids:
     self.c.execute(&quot;DELETE FROM tasks WHERE id=?&quot;, (task_id,))
     self.conn.commit()
     self.load_tasks()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If no task is selected:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=11183326691308680232&quot; alt=&quot;todo_del_window2&quot;&gt;&lt;/p&gt;
&lt;p&gt;Marking tasks 1 and 3 for deletion:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=4465095155001701158&quot; alt=&quot;todo_del_window3&quot;&gt;&lt;/p&gt;
&lt;p&gt;After successful deletion:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=11348943072900279369&quot; alt=&quot;todo_del_window4&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Function to Mark Tasks as Complete&lt;/strong&gt;&lt;br&gt;
When a task is marked as complete, it needs to be updated in the table as well.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;self.c.execute(&quot;SELECT priority, initial_priority FROM tasks WHERE id=?&quot;, (task_id,))
row = self.c.fetchone()
if row:
    current_priority, initial_priority = row
    if current_priority == 'Completed':
        new_priority = initial_priority
    else:
        new_priority = 'Completed'
    self.c.execute(&quot;UPDATE tasks SET priority=? WHERE id=?&quot;, (new_priority, task_id))
        self.conn.commit()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It fetches the task's &lt;code&gt;priority&lt;/code&gt; and &lt;code&gt;initial_priority&lt;/code&gt; from the database. If the task is marked as completed, it resets the priority to its initial state; otherwise, it marks the task as completed and updates its priority in the database.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=4704063977214190218&quot; alt=&quot;todo_complete&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;code-sample&quot;&gt;Code Sample&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3

class TodoListApp:
    def __init__(self, window):
        self.window = window
        self.window.title(&quot;Todo List App&quot;)
        self.conn = sqlite3.connect(&quot;todo.db&quot;)
        self.c = self.conn.cursor()
        self.create_table()
        self.selected_tasks = []
        self.priority_selection = tk.StringVar()
        self.create_widgets()
    
    def create_table(self):
        self.c.execute('''CREATE TABLE IF NOT EXISTS tasks (
                            id INTEGER PRIMARY KEY AUTOINCREMENT,
                            task TEXT NOT NULL,
                            priority TEXT,
                            initial_priority TEXT,
                            deadline TEXT
                        )''')
        self.conn.commit()
    
    def create_widgets(self):
        entry_frame = ttk.Frame(self.window)
        entry_frame.pack(padx=10, pady=10, fill=tk.X)
        ttk.Label(entry_frame, text=&quot;Task name:&quot;).grid(row=0, column=0, padx=5, pady=5)
        self.task_text = tk.StringVar()
        self.task_entry = ttk.Entry(entry_frame, textvariable=self.task_text)
        self.task_entry.grid(row=0, column=1, padx=5, pady=5)
        ttk.Label(entry_frame, text=&quot;Priority:&quot;).grid(row=1, column=0, padx=5, pady=5)
        ttk.Radiobutton(entry_frame, text=&quot;Urgent&quot;, variable=self.priority_selection, value=&quot;Urgent&quot;).grid(row=1, column=1, padx=5, pady=5)
        ttk.Radiobutton(entry_frame, text=&quot;General&quot;, variable=self.priority_selection, value=&quot;General&quot;).grid(row=1, column=2, padx=5, pady=5)
        ttk.Label(entry_frame, text=&quot;Deadline:&quot;).grid(row=2, column=0, padx=5, pady=5)
        self.task_deadline = tk.StringVar()
        self.deadline_entry = ttk.Entry(entry_frame, textvariable=self.task_deadline)
        self.deadline_entry.grid(row=2, column=1, padx=5, pady=5)
        add_button = ttk.Button(entry_frame, text=&quot;Add Task&quot;, command=self.add_task)
        add_button.grid(row=3, column=0, columnspan=3, padx=5, pady=5)
        self.task_list_frame = ttk.Frame(self.window)
        self.task_list_frame.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
        self.load_tasks()
        delete_button = ttk.Button(self.window, text=&quot;Delete Tasks&quot;, command=self.delete_tasks)
        delete_button.pack(pady=5)
        
    def load_tasks(self):
        for widget in self.task_list_frame.winfo_children():
            widget.destroy()
        self.c.execute(&quot;SELECT * FROM tasks&quot;)
        tasks = self.c.fetchall()
        for task in tasks:
            task_id = task[0]
            task_text = task[1]
            task_priority = task[2]
            task_deadline = task[4]
            task_frame = ttk.Frame(self.task_list_frame)
            task_frame.pack(fill=tk.X, padx=5, pady=2)
            task_checkbutton = ttk.Checkbutton(task_frame, command=lambda id=task_id: self.select_task(id))
            task_checkbutton.grid(row=0, column=0)
            if task_priority == &quot;Urgent&quot; or (task_priority == &quot;General&quot; and task_deadline):
                task_label = ttk.Label(task_frame, text=(task_text+&quot;    (&quot;+task_deadline+&quot;)&quot;))
            else:
                task_label = ttk.Label(task_frame, text=task_text)
            task_label.grid(row=0, column=1, padx=5)
            
            if task_priority == &quot;Urgent&quot;:
                task_label.config(foreground=&quot;red&quot;)
            else:
                task_label.config(foreground=&quot;blue&quot;)
            if task_priority == &quot;Completed&quot;:
                task_label.config(foreground=&quot;green&quot;)
                task_checkbutton.state(['selected'])
    
    def add_task(self):
        task_text = self.task_text.get().strip()
        task_priority = self.priority_selection.get()
        task_deadline = self.task_deadline.get().strip()
        if task_text and (task_priority == &quot;General&quot; or (task_priority == &quot;Urgent&quot; and task_deadline)):
            self.c.execute(&quot;INSERT INTO tasks (task, priority, initial_priority, deadline) VALUES (?, ?, ?, ?)&quot;, (task_text, task_priority, task_priority, task_deadline))
            self.conn.commit()
            self.load_tasks()
            self.task_text.set(&quot;&quot;)
            self.priority_selection.set(&quot;&quot;)
            self.task_deadline.set(&quot;&quot;)
        else:
            messagebox.showwarning(&quot;Warning&quot;, &quot;Task or Priority cannot be empty, and Urgent task must have a deadline.&quot;)
    
    def select_task(self, task_id):
        self.c.execute(&quot;SELECT priority, initial_priority FROM tasks WHERE id=?&quot;, (task_id,))
        row = self.c.fetchone()
        if row:
            current_priority, initial_priority = row
            if current_priority == 'Completed':
                new_priority = initial_priority
            else:
                new_priority = 'Completed'
            self.c.execute(&quot;UPDATE tasks SET priority=? WHERE id=?&quot;, (new_priority, task_id))
            self.conn.commit()
            self.load_tasks()

    def delete_tasks(self):
        delete_window = tk.Toplevel(self.window)
        delete_window.geometry(&quot;457x335&quot;)
        delete_window.title(&quot;Delete Tasks&quot;)
        task_list_frame = ttk.Frame(delete_window)
        task_list_frame.pack(padx=10, pady=10)
        self.c.execute(&quot;SELECT id, task FROM tasks&quot;)
        tasks = self.c.fetchall()
        selected_task_ids = []

        def update_selected_tasks(task_id):
            if task_id in selected_task_ids:
                selected_task_ids.remove(task_id)
            else:
                selected_task_ids.append(task_id)

        def delete_selected_tasks():
            if not selected_task_ids:
                messagebox.showwarning(&quot;Warning&quot;, &quot;No tasks selected for deletion.&quot;)
                return
            for task_id in selected_task_ids:
                self.c.execute(&quot;DELETE FROM tasks WHERE id=?&quot;, (task_id,))
            self.conn.commit()
            self.load_tasks()
            delete_window.destroy()

        for task_id, task_text in tasks:
            task_checkbutton = ttk.Checkbutton(task_list_frame, text=task_text, command=lambda id=task_id: update_selected_tasks(id))
            task_checkbutton.pack(anchor=&quot;w&quot;, padx=5, pady=2)

        delete_button = ttk.Button(delete_window, text=&quot;Delete&quot;, command=delete_selected_tasks)
        delete_button.pack(side=&quot;left&quot;, padx=5, pady=5)
        cancel_button = ttk.Button(delete_window, text=&quot;Cancel&quot;, command=delete_window.destroy)
        cancel_button.pack(side=&quot;right&quot;, padx=5, pady=5)

window = tk.Tk()
window.geometry(&quot;457x335&quot;)
app = TodoListApp(window)
window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion-2&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In summary, crafting a Todo List App with Tkinter provides a practical introduction to Python GUI development. You've built an intuitive interface for a &lt;strong&gt;To-Do list app&lt;/strong&gt; with &lt;strong&gt;addition&lt;/strong&gt;, &lt;strong&gt;deletion&lt;/strong&gt;, and &lt;strong&gt;task completion&lt;/strong&gt; features. Using &lt;strong&gt;SQLite&lt;/strong&gt; for &lt;strong&gt;data storage&lt;/strong&gt;, you've showcased Python's &lt;strong&gt;versatility&lt;/strong&gt;. This project offers insights into &lt;strong&gt;user experience design&lt;/strong&gt;, beneficial for aspiring developers.&lt;/p&gt;
</description>
<category>Project Dev</category>
<guid isPermaLink="true">https://coderlegion.com/208/tkinter-todo-gui-application-step-by-step-guide</guid>
<pubDate>Wed, 27 Mar 2024 23:10:38 +0000</pubDate>
</item>
<item>
<title>Tkinter library in Python</title>
<link>https://coderlegion.com/190/tkinter-library-in-python</link>
<description>&lt;p&gt;In this article, we'll dive into the world of &lt;strong&gt;Graphical User Interface (GUI)&lt;/strong&gt; development using Python's &lt;strong&gt;Tkinter&lt;/strong&gt; library. Tkinter stands as a versatile and user-friendly tool for beginners and advanced programmers alike, simplifying the creation of &lt;strong&gt;GUI applications&lt;/strong&gt;. We aim to demystify the process of working with Tkinter, from understanding its core widgets to leveraging its strengths and navigating its limitations. By the end, you'll be equipped with the essentials of Tkinter to enhance your Python GUI development projects.&lt;/p&gt;
&lt;h2 id=&quot;understanding-tkinter&quot;&gt;Understanding Tkinter&lt;/h2&gt;
&lt;p&gt;Tkinter, short for &lt;strong&gt;Tk interface&lt;/strong&gt;, is a built-in Python library designed for creating interactive GUI applications. Tkinter, built on the Tk GUI toolkit, streamlines the creation of windows, buttons, menus, and other graphical elements. As an integral part of the Python standard library, Tkinter smoothly integrates with Python projects, requiring no extra installations, for a seamless GUI development experience. The official python tkinter documentation offers in-depth explanations of Tkinter modules, classes, and methods. &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/tkinter.html&quot;&gt;Visit Documentation&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;div-green&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Tip:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt;As you embark on your GUI development journey, start by sketching out the design and functionality of your application before jumping into the code. This can save time and streamline your development process.&lt;/span&gt; &lt;/div&gt;
&lt;h2 id=&quot;exploring-basic-widgets&quot;&gt;Exploring Basic Widgets&lt;/h2&gt;
&lt;p&gt;We'll begin by exploring some fundamental components you can construct using Tkinter. The following snippets must be preceeded by:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import tkinter as tk
window = tk.Tk()
window.geometry(&quot;457x335&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and followed by:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;window.mainloop()
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;div-red&quot;&gt; &lt;span class=&quot;alert-header&quot;&gt;Caution:&lt;/span&gt; &lt;span class=&quot;alert-body&quot;&gt;When working with widgets, remember to assign a unique name to each widget variable to avoid confusion, especially when your application starts to grow.&lt;/span&gt; &lt;/div&gt;
&lt;h3 id=&quot;label&quot;&gt;&lt;strong&gt;Label&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Presents either text or an image, lacking interactive features for users. For more information on &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/tkinter.html#label-widget&quot;&gt;label&lt;/a&gt; refer official documentation of python.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;label = tk.Label(window, text=&quot;This is a Label&quot;)
label.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=15447304320421249354&quot; alt=&quot;Label&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;button&quot;&gt;&lt;strong&gt;Button&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;An interactive component that executes a specific operation upon being clicked, like dispatching form data or activating a particular function.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def button_click():
    print(&quot;Button clicked&quot;)

button = tk.Button(window, text=&quot;Click here!&quot;, command=button_click)
button.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=17225166072514634203&quot; alt=&quot;button&quot;&gt;&lt;/p&gt;
&lt;p&gt;After clicking the button:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=13782699684249808265&quot; alt=&quot;ButtonClicked&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;entry&quot;&gt;&lt;strong&gt;Entry&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A text field where users can input text or numbers. This component is frequently utilized for entering information or executing search operations.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;entry = tk.Entry(window)
entry.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=17774851110350440973&quot; alt=&quot;Entry&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;text&quot;&gt;&lt;strong&gt;Text&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A text field that provides a multi-line text editing area for users to input or display text.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;text = tk.Text(window, height=5, width=30)
text.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=8046130723076572707&quot; alt=&quot;text&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;scale&quot;&gt;&lt;strong&gt;Scale&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Enables users to choose a value from a spectrum by moving a slider control. It is useful for selecting values like volume, brightness, etc.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def update_value(value):
    label.config(text=f&quot;Volume Level: {value}&quot;)

scale = tk.Scale(window, from_=0, to=100, orient=tk.HORIZONTAL, command=update_value) #create a scale to select values from 0 to 100

scale.pack()
label = tk.Label(window, text=&quot;Volume Level: &quot;)
label.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=18163681093508975768&quot; alt=&quot;Scale&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;spinbox&quot;&gt;&lt;strong&gt;Spinbox&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A numerical input field with up and down arrow buttons for incrementing or decrementing the value.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;spinbox = tk.Spinbox(window, from_=0, to=10)
spinbox.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=6830706622157727616&quot; alt=&quot;Spinbox&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;separator&quot;&gt;&lt;strong&gt;Separator&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A horizontal or vertical line to visually separate sections or groups of widgets.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from tkinter import ttk #for themed widgets

label_1 = tk.Label(window, text=&quot;This is above the separator.&quot;)
label_1.pack()

separator = ttk.Separator(window, orient=tk.HORIZONTAL)
separator.pack(fill=tk.X)

label_2 = tk.Label(window, text=&quot;This is below the separator.&quot;)
label_2.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=16298979966054953561&quot; alt=&quot;Separator&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;checkbutton&quot;&gt;&lt;strong&gt;Checkbutton&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A checkbox enabling users to toggle between selecting and deselecting an option.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;check_var = tk.BooleanVar() #To keep track of the checkbox's state (checked or unchecked)
check_button = tk.Checkbutton(window, text=&quot;Checkbox&quot;, variable=check_var)
check_button.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=9114035529065436677&quot; alt=&quot;Checkbutton&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;radiobutton&quot;&gt;&lt;strong&gt;Radiobutton&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A group of radio buttons, ensuring that users can select only one option from a list of choices.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;radio_var = tk.StringVar() #To track which radio button is selected
radio_1 = tk.Radiobutton(window, text=&quot;Option 1&quot;, variable=radio_var, value=&quot;Option 1&quot;)
radio_2 = tk.Radiobutton(window, text=&quot;Option 2&quot;, variable=radio_var, value=&quot;Option 2&quot;)
radio_1.pack()
radio_2.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=2612228386099183090&quot; alt=&quot;Radiobutton&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;listbox&quot;&gt;&lt;strong&gt;Listbox&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A widget presenting a list of items, allowing users to select one or more options from the list.&lt;/p&gt;
&lt;h3 id=&quot;scrollbar&quot;&gt;&lt;strong&gt;Scrollbar&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Permits users to navigate through content surpassing the widget's visible boundaries, like in a text field or list.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;listbox = tk.Listbox(window)
scrollbar = tk.Scrollbar(window)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y) #scrollbar will be at the right side of the window and expands vertically
listbox.pack(side=tk.LEFT, fill=tk.BOTH) #listbox will be at the left side of the window and expands horizontally and vertically
listbox.config(yscrollcommand=scrollbar.set) #Attach scrollbar to listbox
scrollbar.config(command=listbox.yview)

for i in range(30):
    listbox.insert(tk.END, f&quot;Item {i+1}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=13063392361028412068&quot; alt=&quot;Listbox&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=489762057271802018&quot; alt=&quot;Scrollbar&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;colorchooser&quot;&gt;&lt;strong&gt;ColorChooser&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A dialog for users to select a color. It provides a graphical interface for choosing colors using a palette or entering RGB values.&lt;/p&gt;
&lt;p&gt;from tkinter import colorchooser&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def choose_color():
    color = colorchooser.askcolor()
    print(&quot;Selected color:&quot;, color)

button = tk.Button(window, text=&quot;Choose Color&quot;, command=choose_color)
button.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=8330473602676781386&quot; alt=&quot;ColorChooser&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;frame&quot;&gt;&lt;strong&gt;Frame&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A container used to group and organize other widgets. It is frequently used for layout purposes, creating sections or divisions within a window.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;frame = tk.Frame(window, bg=&quot;lightblue&quot;, bd=5)
frame.pack()

label = tk.Label(frame, text=&quot;Inside the Frame&quot;, bg=&quot;lightblue&quot;)
label.pack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=9882681441102070094&quot; alt=&quot;Frame&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;canvas&quot;&gt;&lt;strong&gt;Canvas&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Provides a drawing area for creating graphics, shapes, and custom elements. It is used for creating diagrams, charts, and interactive visualizations.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;canvas = tk.Canvas(window, width=200, height=100, bg=&quot;white&quot;)
canvas.pack()
canvas.create_rectangle(50, 25, 150, 75, fill=&quot;red&quot;) #draw a red-coloured rectangle
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=3077622398634848951&quot; alt=&quot;Canvas&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;panedwindow&quot;&gt;&lt;strong&gt;PanedWindow&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A container for arranging multiple panes or frames with adjustable sizes. It allows users to resize panes by dragging the divider between them.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;paned_window = tk.PanedWindow(window, orient=tk.HORIZONTAL)
paned_window.pack(fill=tk.BOTH, expand=True) #will expand both horizontally and vertically
frame1 = tk.Frame(paned_window, width=228, height=200, background=&quot;red&quot;)
frame2 = tk.Frame(paned_window, width=228, height=200, background=&quot;blue&quot;)
paned_window.add(frame1)
paned_window.add(frame2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=11535792397148202103&quot; alt=&quot;PanedWindow1&quot;&gt;&lt;/p&gt;
&lt;p&gt;After dragging the divider to the left:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=11391496175646540405&quot; alt=&quot;PanedWindow2&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;menu&quot;&gt;&lt;strong&gt;Menu&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Creates a menu bar or dropdown menu with options and commands. It is commonly used to include navigation, settings and additional functionalities into the application's interface.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def print_something():
    print(&quot;You chose the first option&quot;)

menu_bar = tk.Menu(window)

file_menu = tk.Menu(menu_bar, tearoff=0)
file_menu.add_command(label=&quot;Print Something&quot;, command=print_something)
file_menu.add_separator()
file_menu.add_command(label=&quot;Exit&quot;, command=window.quit)
menu_bar.add_cascade(label=&quot;Click to see options&quot;, menu=file_menu)
window.config(menu=menu_bar)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=1591595257121153453&quot; alt=&quot;Menu&quot;&gt;&lt;/p&gt;
&lt;p&gt;After selecting &quot;Print Something&quot;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=5942132127197068255&quot; alt=&quot;MenuOutput&quot;&gt;&lt;/p&gt;
&lt;p&gt;These elements serve as fundamental components for Tkinter GUI applications, frequently employed across diverse projects to develop intuitive interfaces.&lt;/p&gt;
&lt;p&gt;To delve deeper into Tkinter and explore its capabilities, you can start with the following sections of the Python documentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tkinter — Python interface to Tcl/Tk&lt;/strong&gt;: This section provides the foundational knowledge required to create GUI applications with Tkinter, including widget classes, event handling, and more &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/tkinter.html&quot;&gt;Python Tkinter Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Graphical User Interfaces with Tk&lt;/strong&gt;: This part of the documentation discusses the integration of Tk/Tcl with Python, offering insights into the architecture of Tkinter applications, the Tkinter module, and thematic widget extensions &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/tk.html&quot;&gt;Python GUI with Tk&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tkinter.ttk — Tk themed widgets&lt;/strong&gt;: For those interested in using themed widgets for a more modern GUI look, this section details the thematic widget set provided by Tk 8.5 and integrated into Tkinter &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/tkinter.ttk.html&quot;&gt;Themed Widgets&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion-3&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Tkinter&lt;/strong&gt; is a versatile and user-friendly toolkit for &lt;strong&gt;Python GUI development&lt;/strong&gt;, offering a &lt;strong&gt;rich set of widgets&lt;/strong&gt;, &lt;strong&gt;cross-platform compatibility&lt;/strong&gt;, and &lt;strong&gt;seamless integration&lt;/strong&gt; with Python code. Despite its limitations, Tkinter remains a popular choice for developers looking for efficient creation of simple to moderately complex GUI applications.&lt;/p&gt;
</description>
<category>Project Dev</category>
<guid isPermaLink="true">https://coderlegion.com/190/tkinter-library-in-python</guid>
<pubDate>Tue, 12 Mar 2024 14:34:38 +0000</pubDate>
</item>
</channel>
</rss>