0
votes

Using the code in this answer: Get list of Toplevels on Tkinter:

'''
List all objects in play next song
https://stackguides.com/questions/60978666/get-list-of-toplevels-on-tkinter
'''
LAST_TIME=0.0
THING_COUNT=0

def toplevels(ventana):
    global LAST_TIME, THING_COUNT
    now = time.time()
    if not int(now) == int(LAST_TIME):
        if THING_COUNT > 0:
            print('Number of things:', THING_COUNT)
            THING_COUNT = 0
        print('\n============= toplevels() called at:', t(now),'=============')
        LAST_TIME = now
    for k, v in ventana.children.items():
        if isinstance(v, tk.Toplevel):
            print('Toplevel:', k, v)
        else:
            print('   other:', k, v)
        toplevels(v)
        THING_COUNT += 1

I call it like this:

    toplevels(root)

The output is this:

Number of things: 42

============= toplevels() called at: Dec 24 2020 12:03:27 =============
Toplevel: 140109521792176 .140109521792176
   other: 140109520829184 .140109521792176.140109520829184
   other: 140109520830264 .140109521792176.140109520829184.140109520830264
   other: 140109520859360 .140109521792176.140109520829184.140109520859360
   other: 140109520829472 .140109521792176.140109520829184.140109520829472
   other: 140109521432304 .140109521792176.140109521432304
   other: 140109520827600 .140109521792176.140109521432304.140109520827600
   other: 140109520828032 .140109521792176.140109521432304.140109520827600.140109520828032
   other: 140109520827888 .140109521792176.140109521432304.140109520827600.140109520827888
   other: 140109520828896 .140109521792176.140109521432304.140109520827600.140109520828896
   other: 140109520828176 .140109521792176.140109521432304.140109520827600.140109520828176
   other: 140109520828608 .140109521792176.140109521432304.140109520827600.140109520828608
   other: 140109520828392 .140109521792176.140109521432304.140109520827600.140109520828392
   other: 140109520767024 .140109521792176.140109521432304.140109520767024
   other: 140109520827384 .140109521792176.140109521432304.140109520767024.140109520827384
   other: 140109520767096 .140109521792176.140109521432304.140109520767024.140109520767096
   other: 140109520827096 .140109521792176.140109521432304.140109520767024.140109520827096
Toplevel: 140109520827168 .140109520827168
   other: 140109521621360 .140109520827168.140109521621360
   other: 140109521623016 .140109520827168.140109521621360.140109521623016
   other: 140109521621576 .140109520827168.140109521621360.140109521621576
   other: 140109521623160 .140109520827168.140109521621360.140109521623160
   other: 140109521623376 .140109520827168.140109521621360.140109521623376
   other: 140109521622152 .140109520827168.140109521621360.140109521622152
   other: 140109521622728 .140109520827168.140109521621360.140109521622728
   other: 140109521623232 .140109520827168.140109521621360.140109521623232
   other: 140109521621936 .140109520827168.140109521621360.140109521621936
   other: 140109521622800 .140109520827168.140109521621360.140109521622800
   other: 140109521622944 .140109520827168.140109521621360.140109521622944
   other: 140109521623448 .140109520827168.140109521621360.140109521623448
   other: 140109521623520 .140109520827168.140109521623520
   other: 140109521624888 .140109520827168.140109521623520.140109521624888
   other: 140109521624024 .140109520827168.140109521623520.140109521624024
   other: 140109521623664 .140109520827168.140109521623520.140109521623664
   other: 140109396840528 .140109520827168.140109521623520.140109396840528
   other: 140109521624456 .140109520827168.140109521623520.140109521624456
   other: 140109521624240 .140109520827168.140109521623520.140109521624240
   other: 140109521624672 .140109520827168.140109521623520.140109521624672
   other: 140109396840744 .140109520827168.140109521623520.140109396840744
   other: 140109396840960 .140109520827168.140109396840960
   other: 140109396841176 .140109520827168.140109396840960.140109396841176
   other: 140109396841392 .140109520827168.140109396840960.140109396841392

It's correctly showing two toplevels. First is a music library treeview. Second is currently playing song with four frames:

  • Image of album artwork
  • Details of currently playing song (artist, album, track, etc.)
  • Buttons (close, pause/play, shuffle, next, previous, etc.)
  • Treeview of chronology (recently played, currently playing, up next)

How can I convert the machine language references:

other: 140109521624240 .140109520827168.140109521623520.140109521624240

Into human readable format such as:

  • This is a window x wide, y high, mounted at x,y of Desktop, name="self.play_top"
  • This is a frame at nsew, with groovy relief,name="playfrm"
  • This is a label with default font, size 12 points, containing "this text", text variable="self.current_song_name"
  • This is a button, text="✘ Close", padx=2, pady=2, foreground="#0000000", background="#ffffff", internal name="blah blah"

I need to create a function that will present the information in human readable format and allow changes to colors, font sizes (hDPI monitors), themes, etc. These changes are then applied with another function that uses .configure() methods. I also plan to use a dictionary and store in pickle configuration file for reapplication later.

1
When you use print(v) you are converting the actual object into a reference string. Simply save the v object. - Novel
@Novel When you say "simply save" that implies changing print(v) to print(save(v)) but I don't think you meant that. - WinEunuuchs2Unix
Well I don't know what you want to do with the objects, so by 'save' I mean do whatever it is you want to do. If you want to print out the width, for example, you would print(v.winfo_width()). - Novel
@Novel That works like a charm! Now I have to figure out how to loop through all the attributes an object has bseides winfo_width(). Next I have to start picking attributes to print with if clauses. - WinEunuuchs2Unix
@Novel Thanks to your help, I've posted an answer that achieved desired end result. The answer with intermediate steps (listing all attributes, etc.) would be much longer as diagnostic output is thousands of lines. - WinEunuuchs2Unix

1 Answers

0
votes

To address the issue of configuring. In this application there is a frame with 8 tkinter buttons that do not have names. Every few minutes the background color for artwork changes and it needs to be propagated down to all the buttons.

Here is the function to do that:

def config_all_buttons(level, **kwargs):
    ''' Configure all tk buttons within a frame (doesn't work for toplevel?).

        level = frame name, eg self.play_btn

        **kwargs = tkinter_button.configure(keywords and values). For example:
            fg="#000000", bg="#ffffff", padx=5
    '''
    for k, v in level.children.items():

        if isinstance(v, tk.Button):
            if v["image"] == "":
                # We can't configure image labels that have a value
                v.configure(**kwargs)

        config_all_buttons(v, **kwargs)

Here is how you call the function from your mainline or class:

        self.play_frm_bg = self.play_resized_art.getpixel((3,3))
        hex_background = img.rgb_to_hex(self.play_frm_bg)
        self.play_frm_fg = img.contrasting_rgb_color(self.play_frm_bg)
        hex_foreground = img.rgb_to_hex(self.play_frm_fg)
        self.play_frm.configure(bg=hex_background)
        toolkit.config_all_labels(self.play_frm, fg=hex_foreground, \
                                  bg=hex_background)
        toolkit.config_all_buttons(self.play_btn, fg=hex_foreground, \
                                  bg=hex_background)

Here's what it looks like when artwork has a "dark chocolate" colored background:

mserve confg_all_labels.gif

Here's what it looks like when artwork has a "dark orange" colored background:

mserve confg_all_labels2.gif

Here's what it looks like when artwork has a "yellow" colored background which forces the text to be black:

mserve config_all_labels3.gif