Open-source News

Red Hat Begins Cutting "Hundreds Of Jobs"

Phoronix - Mon, 04/24/2023 - 22:45
The tech layoffs have now reached Red Hat with "hundreds of jobs" being cut and the initial round of layoffs being announced today...

3Dfx Voodoo 1 & 2 Glide Linux Driver Retired, Other X.Org Code Officially Retired

Phoronix - Mon, 04/24/2023 - 21:00
In clearing up the state of various X.Org packages that have been effectively unmaintained for years, an attempt is being made to better communicate the status of some "retired" X.Org packages that Linux distributions should work towards removing as they are no longer being maintained...

SELinux In Linux 6.4 Removes Run-Time Disabling Support

Phoronix - Mon, 04/24/2023 - 20:30
After being deprecated for several years, Security Enhanced Linux "SELinux" beginning with the Linux 6.4 kernel can no longer be run-time disabled...

Improved AMD Color Management Being Worked On For The Steam Deck

Phoronix - Mon, 04/24/2023 - 18:43
Open-source Linux graphics driver engineer Melissa Wen with Igalia, Joshua Ashton with Valve, and Harry Wentland with AMD have been working on kernel mode-setting (KMS) color pipeline enhancements for SteamOS and in particular for enhancing the Steam Deck...

Kdenlive 23.04 Open-Source Video Editor Released With Nested Timelines

Phoronix - Mon, 04/24/2023 - 18:28
Kdenlive remains one of the best available fully open-source non-linear video editing solutions available. With today's release of Kdenlive 23.04 they continue enhancing its feature set and improving the UI/UX for those editing videos on the Linux desktop...

Linux 6.4 Kernel Graphics Drivers Include More Meteor Lake Code, Rockchip 4K, QAIC

Phoronix - Mon, 04/24/2023 - 18:06
With Linux 6.3 released that marks the opening of the two-week Linux 6.4 merge window. David Airlie sent in the Direct Rendering Manager (DRM) subsystem updates already for Linux 6.4 with the assortment of kernel graphics/display driver updates...

Learn Tcl/Tk and Wish with this simple game

opensource.com - Mon, 04/24/2023 - 15:00
Learn Tcl/Tk and Wish with this simple game JamesF Mon, 04/24/2023 - 03:00

Explore the basic language constructs of Tcl/Tk, which include user input, output, variables, conditional evaluation, simple functions, and basic event driven programming.

My path to writing this article started with a desire to make advanced use of Expect which is based on Tcl. Those efforts resulted in these two articles: Learn Tcl by writing a simple game and Learn Expect by writing a simple game.

I do a bit of Ansible automation and, over time have collected a number of local scripts. Some of them I use often enough that it becomes annoying to go through the cycle of:

  1. Open terminal
  2. Use cd to get to the right place
  3. Type a long command with options to start the desired automation

I use macOS on a daily basis. What I really wanted was a menu item or an icon to bring up a simple UI to accept parameters and run the thing I wanted to do, like in KDE on Linux.

The classic Tcl books include documentation on the popular Tk extensions. Since I was already deep into researching this topic, I gave programming it (that is wish) a try. 

I've never been a GUI or front-end developer, but I found the Tcl/Tk methods of script writing fairly straight forward. I was pleased to revisit such a venerable stalwart of UNIX history, something still available and useful on modern platforms.

Install Tcl/Tk

On a Linux system, you can use this:

$ sudo dnf install tcl $ which wish /bin/wish

On macOS, use Homebrew to install the latest Tcl/Tk:

$ brew install tcl-tk $ which wish /usr/local/bin/wishProgramming concepts

Most game-writing articles cover the typical programming language constructs such as loops, conditionals, variables, functions and procedures, and so on.

In this article, I introduce event-driven programming. With event-driven programming, your executable enters into a special built-in loop as it waits for something specific to happen. When the specification is reached, the code is triggered to produce a certain outcome.

These events can consist of things like keyboard input, mouse movement, button clicks, timing triggers, or nearly anything your computer hardware can recognize (perhaps even from special-purpose devices). The code in your program sets the stage from what it presents to the end user, what kinds of inputs to listen for, how to behave when these inputs are received, and then invokes the event loop waiting for input.

The concept for this article is not far off from my other Tcl articles. The big difference here is the replacement of looping constructs with GUI setup and an event loop used to process the user input. The other differences are the various aspects of GUI development needed to make a workable user interface. With Tk GUI development, you need to look at two fundamental constructs called widgets and geometry managers.

Widgets are UI elements that make up the visual elements you see and interact with. These include buttons, text areas, labels, and entry fields. Widgets also offer several flavors of option selections like menus, check boxes, radio buttons, and so on. Finally, widgets include other visual elements like borders and line separators.

Geometry managers play a critical role in laying out where your widgets sit in the displayed window. There are a few different kinds of geometry managers you can use. In this article, I mainly use grid geometry to lay widgets out in neat rows. I explain some of the geometry manager differences at the end of this article.

Guess the number using wish

This example game code is different from the examples in my other articles. I've broken it up into chunks to facilitate the explanation.

Start by creating the basic executable script numgame.wish:

$ touch numgame.wish $ chmod 755 numgame.wish

Open the file in your favorite text editor. Enter the first section of the code:

#!/usr/bin/env wish set LOW 1 set HIGH 100 set STATUS "" set GUESS "" set num [expr round(rand()*100)]

The first line defines that the script is executable with wish. Then, several global variables are created. I've decided to use all upper-case variables for globals bound to widgets that watch these values (LOW, HIGH and so on).

The num global is the variable set to the random value you want the game player to guess. This uses Tcl's command execution to derive the value saved to the variable:

proc Validate {var} { if { [string is integer $var] } { return 1 } return 0 }

This is a special function to validate data entered by the user. It accepts integer numbers and rejects everything else:

proc check_guess {guess num} { global STATUS LOW HIGH GUESS if { $guess < $LOW } { set STATUS "What?" } elseif { $guess > $HIGH } { set STATUS "Huh?" } elseif { $guess < $num } { set STATUS "Too low!" set LOW $guess } elseif { $guess > $num } { set STATUS "Too high!" set HIGH $guess } else { set LOW $guess set HIGH $guess set STATUS "That's Right!" destroy .guess .entry bind all {.quit invoke} } set GUESS "" }

This is the main loop of the value guessing logic. The global statement allows you to modify the global variables created at the beginning of the file (more on this topic later). The conditional looks for input that is out of bounds of 1 through 100 and also outside of values the user has already guessed. Valid guesses are compared against the random value. The LOW and HIGH guesses are tracked as global variables reported in the UI. At each stage, the global STATUS variable is updated. This status message is automatically reported in the UI.

In the case of a correct guess, the destroy statement removes the "Guess" button and the entry widget, and re-binds the Return (or Enter) key to invoke the Quit button.

The last statement set GUESS "" is used to clear the entry widget for the next guess:

label .inst -text "Enter a number between: " label .low -textvariable LOW label .dash -text "-" label .high -textvariable HIGH label .status -text "Status:" label .result -textvariable STATUS button .guess -text "Guess" -command { check_guess $GUESS $num } entry .entry -width 3 -relief sunken -bd 2 -textvariable GUESS -validate all \ -validatecommand { Validate %P } focus .entry button .quit -text "Quit" -command { exit } bind all {.guess invoke}

Programming and development Red Hat Developers Blog Programming cheat sheets Try for free: Red Hat Learning Subscription eBook: An introduction to programming with Bash Bash shell scripting cheat sheet eBook: Modernizing Enterprise Java An open source developer's guide to building applications Register for your free Red Hat account

This is the section where the user interface is set up.  The first six label statements create various bits of text that display on your UI. The option -textvariable watches the given variable and updates the label's value automatically. This displays the bindings to global variables LOW, HIGH, and STATUS.

The button lines set up the Guess and Quit buttons, with the -command option specifying what to do when the button is pressed. The Guess button invokes the check_guess procedure logic above to check the users entered value.

The entry widget gets more interesting. It sets up a three-character wide input field, and binds its input to GUESS global. It also configures validation with the -validatecommand option. This prevents the entry widget from accepting anything other than numbers.

The focus command is a UI polish that starts the program with the entry widget active for input. Without this, you need to click into the entry widget before you can type.

The bind command is an additional UI polish that automatically clicks the Guess button when the Return key is pressed. If you remember from above in check_guess, guessing the correct value re-binds Return to the "Quit" button.

Finally, this section defines the GUI layout:

grid .inst grid .low .dash .high grid .status .result grid .guess .entry grid .quit

The grid geometry manager is called in a series of steps to incrementally build up the desired user experience. It essentially sets up five rows of widgets. The first three are labels displaying various values, the fourth is the Guess button and entry widget, then finally, the Quit button.

At this point, the program is initialized and the wish shell enters into the event loop. It waits for the user to enter integer values and press buttons. It updates labels based on changes it finds in watched global variables.

Notice that the input cursor starts in the entry field and that pressing Return invokes the appropriate and available button.

This was a simple and basic example. Tcl/Tk has a number of options that can make the spacing, fonts, colors, and other UI aspects much more pleasing than the simple UI demonstrated in this article.

When you launch the application, you may notice that the widgets aren't very fancy or modern. That is because I'm using the original classic widget set, reminiscent of the X Windows Motif days. There are default widget extensions, called themed widgets, which can give your application a more modern and polished look and feel.

Play the game!

After saving the file, run it in the terminal:

$ ./numgame.wish

In this case, I can't give console output, so here's an animated GIF to demonstrate how the game is played:

Image by:

(James Farrell, CC BY-SA 4.0)

More about Tcl

Tcl supports the notion of namespaces, so the variables used here need not be global. You can organize your bound widget variables into alternate namespaces. For simple programs like this, it's probably not worth it. For much larger projects, you might want to consider this approach.

The proc check_guess body contains a global line I didn't explain. All variables in Tcl are passed by value, and variables referenced within the body are in a local scope. In this case, I wanted to modify the global variable, not a local scoped version. Tcl has a number of ways of referencing variables and executing code in execution stacks higher in the call chain. In some ways, it makes for complexities (and mistakes) for a simple reference like this. But the call stack manipulation is very powerful and allows for Tcl to implement new forms of conditional and loop constructs that would be cumbersome in other languages.

Finally, in this article, I skipped the topic of geometry managers which are used to take widgets and place them in a specific order. Nothing can be displayed to the screen unless it is managed by some kind of geometry manager. The grid manager is fairly simple. It places widgets in a line, from left to right. I used five grid definitions to create five rows. There are two other geometry managers: place and pack. The pack manager arranges widgets around the edges of the window, and the place manager allows for fixed placement. In addition to these geometry managers, there are special widgets called canvas, text, and panedwindow that can hold and manage other widgets. A full description of all these can be found in the classic Tcl/Tk reference guides, and on the Tk commands documentation page.

Keep learning programming

Tcl and Tk provide a straightforward and effective approach to building graphical user interfaces and event-driven applications. This simple guessing game is just the beginning when it comes to what you can accomplish with these tools. By continuing to learn and explore Tcl and Tk, you can unlock a world of possibilities for building powerful, user-friendly applications. Keep experimenting, keep learning, and see where your newfound Tcl and Tk skills can take you.

Here's an easy coding project to get you started with Tcl/Tk.

Image by:

Opensource.com

Programming What to read next This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License. Register or Login to post a comment.

Pages