Open-source News

KDE Plasma 5.27 Released - Better Wayland Support, KWin Tiling, Multi-Monitor Overhaul

Phoronix - Tue, 02/14/2023 - 19:41
The KDE developers have used Valentine's Day to release Plasma 5.27 as the last feature release of the Plasma 5 series with development attention now turning to Plasma 6.0...

FreeBSD 13.2 Beta 1 Released With WireGuard, Bhyve Improvements, ASLR By Default

Phoronix - Tue, 02/14/2023 - 19:23
The first beta of the upcoming FreeBSD 13.2 point release is now available for testing this Valentine's Day with some great features in tow...

Phoronix Premium Valentine's Day Special To Help Support Linux News & Hardware Testing

Phoronix - Tue, 02/14/2023 - 17:29
If you enjoy the daily open-source/Linux every day of the year on Phoronix along with all of the original Linux benchmarking and hardware review content, you can show your support this Valentine's Day with a special offer...

X.Org Drivers Updated For Old Trident & S3 Graphics

Phoronix - Tue, 02/14/2023 - 16:00
New releases of the xf86-video-trident and xf86-video-s3virge X.Org drivers are now available for those still rocking out to old Trident and S3 graphics hardware...

Create a modern user interface with the Tkinter Python library

opensource.com - Tue, 02/14/2023 - 16:00
Create a modern user interface with the Tkinter Python library patrik-dufresne Tue, 02/14/2023 - 03:00

Python's Tkinter library isn't exactly known for its good looks. I've developed a library to help create a modern graphical user interface for Python.

I spent a lot of time searching for a simple but modern GUI toolkit before developing a new library called TKVue that creates graphical interfaces for desktop applications. Through my research, I realized that there were several different libraries to create graphical interfaces. However, most involve adding new dependencies to bind with graphical libraries. For example, there's a library for Qt, another for wxWidgets, and a third for GTK. None are native to Python or entirely coded in Python. That's a problem. If you want to code a GUI with Qt, it's necessary to compile the Qt source code on each platform you want to support. I wanted to target the three leading platforms: Linux, Windows, and Mac.

The big advantage of Tkinter is that it's embedded in Python. There's no need for new dependencies or to compile new libraries. Everything's already done for you.

In short, it is best to use Tkinter to create something portable.

Tkinter with a modern theme

Creating a GUI with Tkinter is easy, but there's no denying that by default, it looks like a GUI from the 1980s. In addition to creating graphical interfaces that aren't very pleasing to the eye, the programming methodology is also from the 1980s: Programming the Tkinter graphical interface is not declarative.

Motivated by Tkinter's portability, I was determined to use it to create a professional and modern graphical interface. My research led me to discover a whole system for modifying Tkinter's appearance using themes. Tkinter themes are similar to the CSS file of a web page. They allow you to configure the appearance of the components that make up the graphical interface by declaring new styles. The creation of these styles requires some work, but the system is flexible enough to allow the creation of a modern-looking graphical interface. This work is similar to customizing a CSS theme in web development. If you create a web page without CSS, the appearance is not modern, and a lot of work is needed to improve it. This is why CSS libraries such as bootstrap are used to speed up the creation of the graphic interface.

In the Tkinter universe, there is no CSS library. Some pre-existing themes exist, but it's preferable for any project to customize the color palette to match your product branding and give it a web look-and-feel.

To achieve that, the most important element in creating a modern interface with Tkinter is changing the background color and the buttons' appearance.

Once properly personalized to your liking, the result is a clean and visually attractive graphical interface.

Here is the "default" theme:

Image by:

(Patrik Dufresne, CC BY-SA 4.0)

The "clam" theme looks like this:

Image by:

(Patrik Dufresne, CC BY-SA 4.0)

Then with my personalization:

Image by:

(Patrik Dufresne, CC BY-SA 4.0)

TKVue:

import tkvue import tkinter.ttk as ttk tkvue.configure_tk(theme="clam") class RootDialog(tkvue.Component): template = """ """ def __init__(self, master=None): super().__init__(master) s = ttk.Style(master=self.root) s.configure('H1.TLabel', font=['Lato', '-60'], background='#ffffff') s.configure('default.TFrame', background='#ffffff') s.configure( default.TButton', foreground='#0E2933', background='#B6DDE2', bordercolor='#ACD1D6', darkcolor='#B6DDE2', lightcolor='#B6DDE2', focuscolor='#0E2933', ) s.map( default.TButton', background=[('disabled', '#E9F4F6'), ('hover !disabled', '#9ABBC0'), ('pressed !disabled', '#88A5A9')], ) if __name__ == "__main__": dlg = RootDialog() dlg.mainloop()Use a declarative language

After discovering the Tkinter style system, another problem to solve is using a declarative language. For a person who develops web interfaces every day, creating a GUI using Python code doesn't make sense. It requires too much code and too many variables, and poorly structured code. Creating a simple button requires many lines of code intertwined through the creation of many other components.

Modifying the GUI is tedious because it requires many variables that are all tangled up.

In comparison, creating a graphical interface using HTML tags is much more declarative and allows the creation of complex graphical interfaces while remaining structured. That's why I decided to use the Markup Language to create a graphical interface easily from the components available in Tkinter.

The initial idea was quite simple; a tag corresponds to a component. If I want to create a button component with the text Hello, I just have to make a tag named button with an attribute with the value Hello.

TKVue:

Python:

b = Button(parent, text ="Hello") b.pack()

I extrapolated the concept to all the components and functionalities in the Tkinter library from this starting idea. So, to create a more complex graphical interface with different elements, just nest them inside each other by creating a parent-child structure and defining the attributes for each component.

TKVue:

Python:

import tkinter from tkinter.ttk import Frame, Label, Combobox top = tkinter.Tk() top.title = "TKVue Test frame = tkinter.Frame(top) frame.pack(fill='both', expand=1, padx=10, pady=10) l = Label(frame, text="Available values: ", width=20) l.pack(side='left') c = Combobox(frame, values=['zero', 'one', 'two', 'three']) c.pack(side='left', expand=1) top.mainloop()

Result:

Image by:

(Patrik Dufresne, CC BY-SA 4.0)

Using a hierarchical design similar to HTML simplifies the creation of the graphical interface and significantly simplifies the presentation of the parent-child structure created between each component.

Create a dynamic interface

The other problem I encountered using Tkinter was the non-dynamic side of the interface. Having coded Web GUIs with Jinja2 templates, which allow you to reuse variables and create loops easily, I wanted similar functionality when creating desktop GUIs.

I must admit that the dynamic side of TKVue gave me some problems. My initial plan was to update the GUI dynamically when a variable was changed by the code. So it should be possible to use variables in the markup language. Suppose I select a value from a drop-down list. I want to be able to associate the specified value with a variable and allow that variable to be reused in another component for display. See the code sample below:

TKVue:

import tkvue class RootDialog(tkvue.Component): template = """ """ data = tkvue.Context({"myvalues": ["zero", "one", "two", "three"], "var1": ""}) dlg = RootDialog() dlg.mainloop()

Python:

import tkinter from tkinter.ttk import Frame, Label, Combobox top = tkinter.Tk() top.title = "TKVue Test frame = tkinter.Frame(top) frame.pack(fill='both', expand=1, padx=10, pady=10) l = Label(frame, text="Available values: ", width=20) l.pack(side='left') var1 = tkinter.StringVar() c = Combobox(frame, values=['zero', 'one', 'two', 'three'], textvariable=var1) c.pack(side='left', expand=1) frame2 = tkinter.Frame(top) frame2.pack(fill='both', expand=1, padx=10, pady=10) s = Label(frame2, text='Value selected:') s.pack(side='bottom') var1.trace_add("write", lambda *args: s.configure(text='Value selected: ' + var1.get())) top.mainloop()

Result:

Image by:

(Patrik Dufresne, CC BY-SA 4.0)

With this in place, it is possible to create a graphical interface that reacts to the user's actions in a simple and declarative way.

Use loops and conditions

To make the model as dynamic as possible, it was necessary to support the use of loops and conditions to show or hide components depending on variables. TKVue introduces two special attributes to fill this need, the for attribute for loop creation and the visible attribute.

The following example allows the user to select the number of items to be displayed in the loop from a drop-down list. The following example demonstrates the dynamic side of a loop reacting to the user's actions:

TKVue:

import tkvue class RootDialog(tkvue.Component): template = """ """ data = tkvue.Context({'count': 5}) if __name__ == "__main__": dlg = RootDialog() dlg.mainloop()

Result:

Image by:

(Patrik Dufresne, CC BY-SA 4.0)

The condition declaration is even simpler. You must define an expression in the visible attribute as follows:

TkVue:

import tkvue class RootDialog(tkvue.Component): template = """ """ data = tkvue.Context({'show': True}) if __name__ == "__main__": dlg = RootDialog() dlg.mainloop()

Result:

Image by:

(Patrik Dufresne, CC BY-SA 4.0)

More Python resources What is an IDE? Cheat sheet: Python 3.7 for beginners Top Python GUI frameworks Download: 7 essential PyPI libraries Red Hat Developers Latest Python articles Use localization

Another important aspect of the development of my application is to allow the translation of the graphical interface quickly by using technologies that are already known and widely used in Python: gettext.

To do this, the library provides an adapter for Babel, which allows extracting the strings to be translated. You can then find these strings in a translation catalog (.po file).

Here is an example of a configuration file for Babel that allows you to extract strings for translation purposes:

Place the following in Babel.cfg:

[python: **.py] [tkvue: **/templates/**.html]

I'm using Tkinter and my theming library for my data backup software, Minarca.

The final result is elegant and simple at the same time. The style matches the color palette of the Minarca project.

Image by:

(Patrik Dufresne, CC BY-SA 4.0)

Try TKVue today

The objective of all this work is to bring familiar advantages in web development to traditional development. TKVue saves time while developing the graphical interface and makes it easier to maintain and modify the code afterward.

The work I have done so far in the library is quite rudimentary and needs further modification before being used more widely in projects. I hope that the publication of this article allows someone else to take over the development of a similar library or to continue to develop directly in TKVue to improve its functionality. TKVue's code is available on GitLab.

TKVue saves time while developing the graphical interface and makes it easier to maintain and modify the code afterward.

Image by:

Opensource.com

Python Web development 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.

Lua loops: how to use while and repeat until

opensource.com - Tue, 02/14/2023 - 16:00
Lua loops: how to use while and repeat until sethkenlon Tue, 02/14/2023 - 03:00

Control structures are an important feature of programming languages because they enable you to direct the flow of the program based on conditions that are often established dynamically as the program is running. Different languages provide different controls, and in Lua there's the while loop, for loop, and repeat until loop. This article covers the while and repeat until loops. Because of their flexibility, I cover for loops in a separate article.

A condition is defined by an expression using an operator, which is a fancy term for symbols you may recognize from math classes. Valid operators in Lua are:

  • == equal to

  • ~= not equal to

  • < less than

  • > greater than

  • ⇐ less than or equal to

  • >= greater than or equal to

Those are known as relational operators because they prompt an investigation of how two values relate to one another. There are also logical operators, which mean the same as they mean in English and can be incorporated into conditions to further describe the state you want to check for:

  • and

  • or

Here are some example conditions:

  • foo > 3: Is the variable foo is greater than 3? The foo must be 4 or more to satisfy this condition.

  • foo >= 3: Is foo greater than or equal to 3? The foo must be 3 or more to satisfy this condition.

  • foo > 3 and bar < 1: Is foo greater than 3 while bar is less than 1? For this condition to be true, the foo variable must be 4 or more at the same moment that bar is 0.

  • foo > 3 or bar < 1: Is foo greater than 3? Alternately, is bar less than 1? If foo is 4 or more, or bar is 0, then this condition is true. What happens if foo is 4 or more while bar is 0? The answer appears later in this article.

While loop

A while loop executes instructions for as long as some condition is satisfied. For example, suppose you're developing an application to monitor an ongoing zombie apocalypse. When there are no zombies remaining, then there is no more zombie apocalypse:

zombie = 1024 while (zombie > 0) do print(zombie) zombie = zombie-1 end if zombie == 0 then print("No more zombie apocalypse!") end

Run the code to watch the zombies vanish:

$ lua ./while.lua 1024 1023 [...] 3 2 1 No more zombie apocalypse!Until loop

Lua also has a repeat until loop construct that's essentially a while loop with a "catch" statement. Suppose you've taken up gardening and you want to track what's left to harvest:

mytable = { "tomato", "lettuce", "brains" } bc = 3 repeat print(mytable[bc]) bc = bc - 1 until( bc == 0 )

Run the code:

$ lua ./until.lua brains lettuce tomato

That's helpful!

Infinite loops

An infinite loop has a condition that can never be satisfied, so it runs infinitely. This is often a bug caused by bad logic or an unexpected state in your program. For instance, at the start of this article, I posed a logic puzzle. If a loop is set to run until foo > 3 or bar < 1, then what happens when foo is 4 or more while bar is 0?

Here's the code to solve this puzzle, with a safety catch using the break statement just in case:

foo = 9 bar = 0 while ( foo > 3 or bar < 1 ) do print(foo) foo = foo-1 -- safety catch if foo < -800000 then break end end

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

You can safely run this code, but it does mimic an accidental infinite loop. The flawed logic is the or operator, which permits this loop to continue both when foo is greater than 3 and when bar is less than 1. The and operator has a different effect, but I leave that to you to explore.

Infinite loops actually do have their uses. Graphical applications use what are technically infinite loops to keep the application window open. There's no way of knowing how long your user intends to use the application, so the program runs infinitely until the user selects Quit. The simple condition used in these cases is one that is obviously always satisfied. Here's an example infinite loop, again with a safety catch built in for convenience:

n = 0 while true do print(n) n = n+1 if n > 100 then break end end

The condition while true is always satisfied because true is always true. It's the terse way of writing while 1 == 1 or something similarly eternally true.

Loops in Lua

As you can tell from the sample code, although there are different implementations, loops all basically work toward the same goal. Choose the one that makes sense to you and that works best with the processing you need to perform. And just in case you need it: The keyboard shortcut to terminate a runaway loop is Ctrl+C.

Learn how and when to use while and repeat until loops in Lua.

Image by:

WOCinTech Chat. Modified by Opensource.com. CC BY-SA 4.0

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