4

I am developing an app to select and play a mp3 clip from a list. It will be run on a Pi4 with 7" touch display and piAMP+ hat. The GUI is in tkinter with pygame for the sound plus a pair of GPIO pins for volume up/down. The user uses the arrow up/down buttons on the GUI to select the clip; play starts the selected clip and stop halts playing.

The full script (up/down, start/stop and pygame functionality) works on a PC with PyCharm for debugging. For the PC I commented-out the GPIO related commands.

When ported to the Pi with Thonny for debug, the GUI will load but the GUI and GPIO buttons are unresponsive. A copy of the minimal script with 1 button and no GPIO or pygame references is attached. I’ve added debug print statements just before root.run() and inside the button logic to denote when reached.

I’ve observed:

  • Executing from Thonny or command line, the GUI is displayed but the buttons are unresponsive.

  • From Thonny debug, if I insert a break-point at root.run(), the script will stop at the break-point and, when resumed, the previous/next, play/stop buttons and corresponding code will function.

  • Adding a timer.sleep(5) between root.update() and root.mainloop() doesn’t make a difference. I also tried root.after(2500).

I’ve added the next 3 items to explain my code decisions.

  • My original design called for a list box to display the songs but I couldn’t find a way to highlight the currently selected item from the list. The result is the "locate songs on grid" code block with label_list and current variables.

  • label_list is a dict containing the grid location and tkinter.ttk.label object. When passed to previous, the foreground and background colors are changed and current (selected song) value updated.

  • When playing the selected song (code not shown), I get the mp3 filename from songs, not label_list. Even if label_list is the culprit, I can’t activate play without the breakpoint.

I don’t understand why the Pi "needs" a breakpoint to make the buttons operational.

# Import tkinter (GUI), pygame (Audio) and csv (to parse file into a list of dict
import tkinter as tk # Display library, using grid placement
from tkinter import ttk # This includes newer methods for labels
# Variable declarations and defaults
label_list = {} # Initialize the list of song labels (in grid)
set_volume = 0.1 # Default volume, 10%
current = 0 # Index corresponding the current (highlighted) song
songs = [{'Index': 0, 'Program': "Song1", 'File': 'song1.mp3'},
{'Index': 1, 'Program': 'Song2', 'File': 'song2.mp3'},
{'Index': 2, 'Program': 'Song3', 'File': 'song3.mp3'},
{'Index': 3, 'Program': 'Song4', 'File': 'song4.mp3'},
{'Index': 4, 'Program': 'Song5', 'File': 'song5.mp3'}]
def previous():
 # Decrement the current index (song), restore the old, highlight the new
 global label_list # This is a list of dictionaries
 global current # This is the index corresponding to the current song
 # Revert the current song to default colors
 print("Got to previous")
 label_list[(0, current)].config(background='White', foreground='Black')
 if current == 0:
 current = 4 # Last song in the queue, ie wrap-around
 else:
 current -= 1 # Decrement by 1
 # Reverse-video the new current song
 label_list[(0, current)].config(background='Black', foreground='White')
def main():
 # Create the root window
 global songs
 root = tk.Tk()
 root.title("Help Me")
 root.geometry('600x400')
 root.config(bg='White') # Default to using white, not system background
 # Create the GUI as a 6 row x 3 column Grid
 for grid_row in range(6):
 root.rowconfigure(grid_row, weight=1)
 root.columnconfigure(0, weight=3) # The intent was to make this column wider
 root.columnconfigure(1, weight=1) # This is actually a spacer between song and arrow
 root.columnconfigure(2, weight=1) # These are the arrow buttons
 # Locate songs on grid, column 1
 for song_row in songs:
 if song_row['Index'] == 0:
 # Start with making this row reverse-video
 song_label = ttk.Label(root, text=song_row['Program'], background='Black', foreground='White')
 else:
 song_label = ttk.Label(root, text=song_row['Program'], background='White', foreground='Black')
 # Assign the song_label to a list which can later be manipulated
 label_list[(0, song_row['Index'])] = song_label
 # Assign the song_row contents to the grid at the row/column
 song_label.grid(column=0, row=song_row['Index'], sticky=tk.EW, padx=5, pady=5)
 # locate arrow up/down buttons on column 2 - spanning 2 rows down, u2191 is ascii up arrow
 song_prev = ttk.Button(root, text='\u2191', command=previous)
 song_prev.grid(column=2, row=1, columnspan=2, sticky=tk.EW, padx=5, pady=5)
 # This sets the program to run continuously
 root.update()
 print("Got to mainloop")
 root.mainloop()
 
if __name__ == '__main__':
 main()
President Jam
1,3141 gold badge6 silver badges22 bronze badges
asked Oct 13, 2025 at 17:47
7
  • Thonny is created with tkinter and maybe this can make some conflict with your code also created with tkinter Commented Oct 13, 2025 at 18:56
  • did you test this code without Thonny? Commented Oct 13, 2025 at 18:58
  • if problem exists only on PI then you may have to add more details about system - system version, Python version, etc. And put this in question, not in comments. More people may see it. But problem is that this need to run code on PI to test what can makes problem. Commented Oct 13, 2025 at 19:02
  • Yes, I've tested the code from a command prompt, no Thonny, same result. System configuration: Pi4 running Bookworm, updated regularly Python 3.11.2 From pip list: types-ttkthemes 3.2. Commented Oct 14, 2025 at 1:13
  • read my previous comment: And put this in question, not in comments. More people may see it. Commented Oct 14, 2025 at 11:06

1 Answer 1

1

I was able to get the program to work, at least via command line. The comments were helpful, especially stripping the program down to the minimum needed to show the issue. An explanation is below.

Root cause: I believe the culprit was a missing tk-tools library. Tk, included by default, allowed the GUI to be built and loaded but not executed. You don't have to import tk-tools and I never received an error message that the functionality was missing. The "local" or default Python instance does not include tk-tools.

Method: Retracing my steps using the history command I noticed while I entered the python -m venv command, I didn’t follow up with source activate. This meant I was still using the "local" Python instance, and libraries. It became apparent when I added-back some code deleted for this question but received an error that the referenced library was missing. The original script was created inside the venv and included tk-tools and other libraries but most of my subsequent development didn't activate the environment. Some libraries were installed on both.

Thonny: Like the command line, Thonny defaulted to the "local" python instance. Dummy me, I assumed since I had a venv structure, Thonny would have used it to execute the script. There are internet pages providing instruction to configure Thonny to use a venv but those instructions didn’t match the screens of my version. Given I had the command line working I didn’t pursue further.

answered Oct 16, 2025 at 20:27
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.