Python - GUI Programming - Standard Attributes - Cursors, Bitmaps & Relief Styles

Graphical user interfaces (GUIs) are essential components of modern software applications. They allow users to interact with the software using graphical elements such as buttons, textboxes, and menus. GUIs are usually designed to be visually appealing and intuitive to use. Python provides several libraries to develop GUI applications, such as Tkinter, wxPython, PyQt, and PySide.

When designing a GUI, you might want to consider the visual appearance of your widgets beyond their basic functionality. This is where attributes like relief styles and bitmaps come into play. Let's take a closer look at these attributes and how they can be used in Python GUI programming.

Relief Styles

Relief styles are used to add a 3D effect to a widget. They define the border and shading around the widget. There are four relief styles available in Tkinter:

  • FLAT: This is the default style with no 3D effect.
  • RAISED: This style gives a raised 3D effect, making the widget appear to be popping out of the screen.
  • SUNKEN: This style gives a sunken 3D effect, making the widget appear to be pushed into the screen.
  • GROOVE: This style gives a 3D groove effect, with a shaded border around the widget.
from tkinter import *
root = Tk()
frame = Frame(root, bd=10, relief=SUNKEN)
frame.pack(side=LEFT, padx=10, pady=10)
label = Label(frame, text="Hello World!", font=("Arial", 20))
label.pack(padx=10, pady=10)
button = Button(frame, text="Click Me!", font=("Arial", 14))
button.pack(padx=10, pady=10)
root.mainloop()

In this example, we create a Frame widget with a SUNKEN relief style and a border width of 10 pixels. The Label and Button widgets are added to the Frame. The padx and pady parameters are used to add padding around the widgets.

Bitmaps

Bitmaps are small images used to represent different states of a widget, such as the on/off state of a checkbox or radio button. They are also used to indicate the status of an application, such as a busy or idle state. Tkinter provides several built-in bitmaps that can be used in your applications.

from tkinter import *
root = Tk()
frame = Frame(root)
frame.pack(padx=10, pady=10)
button1 = Button(frame, text="OK", bitmap="info", compound="left")
button1.pack(padx=10, pady=10)
button2 = Button(frame, text="Cancel", bitmap="error", compound="left")
button2.pack(padx=10, pady=10)
root.mainloop()

In this example, we create two Button widgets with different bitmaps. The info bitmap is used for the OK button, while the error bitmap is used for the Cancel button. The compound parameter is set to "left", which places the bitmap on the left side of the button text.

Cursors 

There are several built-in cursors available in Python. Some of the common ones are:

  • arrow: The default cursor style
  • circle: A circular cursor
  • cross: A cross-shaped cursor
  • fleur: A fleur-shaped cursor
  • heart: A heart-shaped cursor
  • plus: A plus-shaped cursor
  • question_arrow: A question mark-shaped cursor
  • right_ptr: A right arrow-shaped cursor
  • sb_down_arrow: A downward-pointing arrow-shaped cursor
  • sb_h_double_arrow: A horizontal double arrow-shaped cursor
  • sb_left_arrow: A left arrow-shaped cursor
  • sb_right_arrow: A right arrow-shaped cursor
  • sb_up_arrow: An upward-pointing arrow-shaped cursor
  • sb_v_double_arrow: A vertical double arrow-shaped cursor
  • watch: A watch-shaped cursor
  • To change the cursor style in a Tkinter application, we can use the configure method of the widget and set the cursor attribute to the desired cursor style. Here's an example:
import tkinter as tk
root = tk.Tk()
# create a button widget
button = tk.Button(root, text="Click me!")
# configure the cursor style of the button
button.configure(cursor="heart")
# pack the button in the root window
button.pack()
root.mainloop()

In this example, we create a button widget and set its cursor attribute to heart using the configure method. When we run the program, the cursor will change to a heart shape when it is over the button.

We can also set the cursor style for the entire application using the Tk class's configure method. Here's an example:

import tkinter as tk
root = tk.Tk()
# set the cursor style for the entire application
root.configure(cursor="watch")
# create a button widget
button = tk.Button(root, text="Click me!")
# pack the button in the root window
button.pack()
root.mainloop()

In this example, we set the cursor attribute of the Tk class to watch, which will change the cursor style for the entire application. When we run the program, the cursor will change to a watch shape when it is over the root window or any other widget in the application.

In addition to the built-in cursors, we can also create custom cursors using image files. To create a custom cursor, we need to load an image file and pass it to the ImageTk.PhotoImage constructor. Here's an example:

import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
root = tk.Tk()
# load the image file and create a PhotoImage object
image = Image.open("custom_cursor.png")
cursor_image = ImageTk.PhotoImage(image)
# create a label widget
label = ttk.Label(root, text="Hover over me!")
# configure the cursor style of the label
label.configure(cursor=cursor_image)
# pack the label in the root window
label.pack()
root.mainloop()

In this example, we load an image file custom_cursor.png and create a PhotoImage object cursor_image using the ImageTk.PhotoImage constructor. We then create a label widget and set its cursor attribute to cursor_image. When we run the program, the cursor will change to