如何在python tkinter中使用多个单选按钮?

2024-03-28 22:05:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我在这里挣扎已经够久了。我需要一些指导

我正在尝试制作一个字节生成器GUI。95%工作正常,但我无法在单击单选按钮后保持其打开/关闭状态

我在循环中创建了64个按钮,为变量赋值,并创建了一个回调函数

在回调函数中,我单击一个按钮,然后调用update_array,它更新一个列表和一个文本字节数组。这些值在0到1之间来回切换。工作正常,但按钮不会保持打开/突出显示。我甚至不确定我是否应该使用另一种按钮类型

最终结果是按钮数组,字节数组应该显示相同的模式

我还尝试获取我单击的按钮的标识。(Btn_XY)我知道当我点击Btn_44时,但我如何从tkinter找到它

在MacBook Pro 10.15.5版上运行python3.8

GUI选项卡1显示按钮和字节映射

回调函数是def btnCall(self)

按钮在第280到293行创建。def btnCall和def update_array的功能似乎工作正常。尽管它们是不完整的,但其中的部分仍在发挥作用。我可以稍后将列表保存到全局列表

在整个显示过程和调试过程中打印语句

请给我一些建议????提前谢谢

import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext
from tkinter import Menu
from tkinter import messagebox as msg


class CHAR_GEN():
def __init__(self):         # Initializer method
    # Create instance
    self.win = tk.Tk()   

    # Add a title       
    self.win.title("Character Generator GUI")      
    self.create_widgets()

    #create the byte array for the byte map
    self.create_byte_array()

# Modified Button Click Function
def click_me(self): 
    self.action.configure(text='Hello ' + self.name.get() + ' ' + 
                     self.number_chosen.get())


# GUI Callback  
def checkCallback(self, *ignored_args):
    # only enable one checkbutton
    if self.chVarUn.get(): self.check3.configure(state='disabled')
    else:                  self.check3.configure(state='normal')
    if self.chVarEn.get(): self.check2.configure(state='disabled')
    else:                  self.check2.configure(state='normal') 

def create_byte_array(self):
    print('Create the array')
    self.byte_array = []
    for row in range(8):
        self.byte_array.append([])
        for col in range(8):
            self.byte_array[row].append(0)

    #############
    self.byte_box.insert(tk.END, '\n\n byte_array = { \n')
    print(self.byte_array)
    for row  in range(8):
        #self.byte_array[row].append(0)
        print(''.join(map(str, self.byte_array[row])))
        msg = ''.join(map(str, self.byte_array[row]))

        #############
        self.byte_box.insert(tk.END, '     ')
        self.byte_box.insert(tk.END, msg)
        self.byte_box.insert(tk.END, '\n')
    self.byte_box.insert(tk.END, '              }\n')

    #############
    #############
    return self.byte_array

########################################################
#   The byte_array is just a structure. We will print a 
#   text representation of it in the text box and 
#   refresh it every time the update or create fuction is called
########################################################

def update_array(self,row,col):
    print('in update array row and col passed == {} {}'.format(row,col))

    print('the variable self.byte_array[row][col] == {}'.format(self.byte_array[row][col]))

    print('in update_array this is where we toggle the bit in the list') 

    if self.byte_array[row][col] == 0:
        self.byte_array[row][col] = 1
    else:
        self.byte_array[row][col] = 0

    #############
    #############
    #############
    print('ready to print to text box')
    print(self.byte_array)
    # delete the text in the box
    self.byte_box.delete('1.0',tk.END)
    #redraw
    self.byte_box.insert(tk.END, '\n\n byte_array = { \n')

    for row  in range(8):
        print(''.join(map(str, self.byte_array[row])))
        msg = ''.join(map(str, self.byte_array[row]))

        #############
        self.byte_box.insert(tk.END, '     ')
        self.byte_box.insert(tk.END, msg)
        self.byte_box.insert(tk.END, '\n')
    self.byte_box.insert(tk.END, '              }\n')
    #############
    #############
    #############
    #############

#####################################
#####################################
#    Build a list for all the radVars
#####################################
# Radiobutton Callback
def btnCall(self):
    print('entered btnCall')
    print('this is where we clicked the button')
    btnVar = self.radVar.get()


    print('in btnCall btnVar == {}'.format(btnVar))
    ###
    s = str(btnVar)
    #print(s)
    if len(s) == 1:
        xpos = str(0)
        ypos = s
    else:
        xpos = s[-2]
        ypos = s[-1]
    print('in btnCall xpos,ypos == {}{}'.format(xpos,ypos))

    print('leaving btnCall() and calling self.update_array')
    self.update_array(int(xpos),int(ypos))

#####################################
#####################################
#####################################
# reset the pixel map
def reset_map(self):
    #delete map
    #turn off all the radio buttons
    #create map
    pass

def invert_map(self):
    #delete map
    #toggle the bits in the map
    #create map
    pass



# Exit GUI cleanly
def _quit(self):
    self.win.quit()
    self.win.destroy()
    exit() 

#####################################################################################       
def create_widgets(self):    
    tabControl = ttk.Notebook(self.win)          # Create Tab Control

    tab1 = ttk.Frame(tabControl)            # Add a second tab
    tabControl.add(tab1, text='Tab 1')      # Make second tab visible
    tab2 = ttk.Frame(tabControl)            # Create a tab 
    tabControl.add(tab2, text='Tab 2')      # Add the tab

    tabControl.pack(expand=1, fill="both")  # Pack to make visible



    # Top of Tab Control 2 -------------------------------------------

    # We are creating a container frame to hold all other widgets -- Tab2
    self.pixmap = ttk.LabelFrame(tab1, text=' Pixels')
    self.pixmap.grid(column=0, row=0, padx=8, pady=4)


    self.map_frame = ttk.LabelFrame(self.pixmap, text=' Pixel Map ')
    self.map_frame.grid(column=0, row=2, sticky='W', columnspan=2)        

    ## Add a textbox frame to hold the character array
    self.byte_frame = ttk.LabelFrame(tab1, text=' Bytes  ')
    self.byte_frame.grid(column=1, row=0, sticky='W', columnspan=2)        

    # Creating three checkbuttons
    self.chVarDis = tk.IntVar()
    self.check1 = tk.Checkbutton(self.pixmap, text="Disabled", variable=self.chVarDis, state='disabled')
    self.check1.select()
    self.check1.grid(column=0, row=0, sticky=tk.W)                   
   # 
    self.chVarUn = tk.IntVar()
    self.check2 = tk.Checkbutton(self.pixmap, text="Junk", variable=self.chVarUn)
    self.check2.deselect()
    self.check2.grid(column=1, row=0, sticky=tk.W)                   
   # 
    self.chVarEn = tk.IntVar()
    self.check3 = tk.Checkbutton(self.pixmap, text="Save", variable=self.chVarEn)
    self.check3.deselect()
    self.check3.grid(column=2, row=0, sticky=tk.W)                     

    # trace the state of the two checkbuttons
    self.chVarUn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback())    
    print('self.chVarUn == {}'.format(self.chVarUn))
    self.chVarEn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback())   
    #print('self.chVarEn == {}'.format(self.chVarEn))

    #####################################################################
    #
    #         create a text box to hold the bytes
    #
    #####################################################################

    self. byte_box = tk.Text(self.byte_frame, height=12, width=20)
    self.byte_box.grid(column=0, row=0, sticky=tk.E)
    #self.byte_box.insert(tk.END, "Just a text Widget\nin two lines\n")
    #self.byte_box.insert(tk.END, '\n\n byte_array = { \n')

    # First, we change our Radiobutton global variables into a list

    # create three Radiobuttons using one variable
    self.radVar = tk.IntVar()

    # Next we are selecting a non-existing index value for radVar
    self.radVar.set(99)                                 

    # Now we are creating all three Radiobutton widgets within one loop
    # create a temp dictionary to build the radio buttones ????????



    ##########################
    #          build a function to create 64 of these radio buttons.
    #          later !!!
    ##########################

    #####################################################################
    #
    #         create a text box to hold the bytes
    #
    #####################################################################

    self. byte_box = tk.Text(self.byte_frame, height=12, width=20)
    self.byte_box.grid(column=0, row=0, sticky=tk.E)
    #self.byte_box.insert(tk.END, "Just a text Widget\nin two lines\n")
    #self.byte_box.insert(tk.END, '\n\n byte_array = { \n')



    # create 64 Radiobuttons using one variable
    self.radVar = tk.IntVar()

    # Next we are selecting a non-existing index value for radVar
    self.radVar.set(99)                                 

    # Now we are creating all three Radiobutton widgets within one loop
    # create a temp dictionary to build the radio buttones



    ##########################
    #          build a function to create 64 of these radio buttons.
    #          later !!!
    ##########################
    ##########################
    # here are all the radio buttons
    ##########################
    ##########################
    ##########################
    '''
         Here we will use a double loop to greate the radio buttons
         and later the variables. The numbers in the loop will
         be appended to Btn_XY where XY is the row and column.

         Also use the numbers for naming radVar for each button
         Also use the numbers for naming row and column
    '''
    ##########################
    ##########################
    bname = "Btn_"
    for x in range(8):
        for y in range(8):
            #print(x,y)
            #print(bname + str(x) + str(y))
            cr_name = bname + str(x) + str(y)

            print('in creation loop cr_name == {}'.format(cr_name))
            ######
            # need to create a simple SMALL box above eache of these 
            # to toggle on and off

            self.cr_name = tk.Radiobutton(self.map_frame, variable=self.radVar, val = int(str(x)+str(y)), command=self.btnCall)
            self.cr_name.grid(column=y+1, row=x+1, sticky=tk.W)
    ##########################

   #  create another frame container
    ###############################################################
    ###############################################################


    # Create a container to hold misc buttons
    misc_buttons_frame = ttk.LabelFrame(self.pixmap, text=' Modify ')
    misc_buttons_frame.grid(column=0, row=3, sticky='W', columnspan=2)        

    # create another frame container
    ###############################################################
    ###############################################################
    ###############################################################
    # Add Buttons for reset and invert commands
    ttk.Button(misc_buttons_frame, text=" Reset Map", command=self.reset_map).grid(column=0, row=0, sticky='W')  
    ttk.Button(misc_buttons_frame, text=" Invert Map  ", command=self.invert_map).grid(column=1, row=0, sticky='W')  
    # 
    for child in misc_buttons_frame.winfo_children():  
        child.grid_configure(padx=2, pady=2) 
    # 
    for child in self.pixmap.winfo_children():  
        child.grid_configure(padx=8, pady=2) 


    # Creating a Menu Bar
    menu_bar = Menu(self.win)
    self.win.config(menu=menu_bar)

    # Add menu items
    file_menu = Menu(menu_bar, tearoff=0)
    file_menu.add_command(label="New")
    file_menu.add_separator()
    file_menu.add_command(label="Exit", command=self._quit)
    menu_bar.add_cascade(label="File", menu=file_menu)

    # Display a Message Box

    # Add another Menu to the Menu Bar and an item
    help_menu = Menu(menu_bar, tearoff=0)
    menu_bar.add_cascade(label="Help", menu=help_menu)

    # Change the main windows icon
    # self.win.iconbitmap('pyc.ico')


    self.check3.focus()     


# Start GUI

oop = CHAR_GEN()
oop.win.mainloop(

)


Tags: thetotextinselfboxmapfor
2条回答

Radiobutton的目的是在一个组中只选择一个。 您应该为您的程序使用Checkbutton

在您的程序中,您从不使用包含X/Y的cr_name来标识按钮

有关如何保存复选按钮并稍后访问其值的示例:

from tkinter import *

root = Tk()

bits = [] 
btn = [] 

for i in range(10): #Populates a list as a replacement for your actual inputs
    bits.append("btn"+str(i))

for i in range(len(bits)):
    #print text by referencing itself from the list where buttons are stored
    btn.append(Checkbutton(root, text=bits[i], command=lambda c=i: print(btn[c].cget("text"))))
    btn[i].pack() #pack the buttons

root.mainloop()

最后,我为列表中的每个检查按钮创建了变量,就像检查按钮一样。太多的代码无法显示,但上面Nico提出的建议让我走上了正确的道路

感谢所有帮忙的人

如果下面的缩进失败,那么很抱歉。我不怎么发帖

===========================================================================

    for i in range(len(blst)):
        print(i)
        self.vars.append(tk.IntVar())
        #print text by referencing itself from the list where buttons are stored
               self.btn.append(tk.Checkbutton(self.map_frame,text=blst[i],variable=lambda c=i:self.vars[i],command=lambda c=i: self.press(self.btn[c].cget("text"),self.vars[i])))
        self.btn[i].grid(column=int(blst[i][1]), row =int(blst[i][0]),sticky=tk.W)

相关问题 更多 >