Как ссылаться на атрибут кнопки tkinter, который находится внутри списка?(Python) - PullRequest
0 голосов
/ 27 августа 2018

Я создаю программу калькулятора и создаю кнопки для перехода в интерфейс калькулятора.Сначала я создаю все кнопки, используя одну для цикла, а затем хочу перенастроить определенные кнопки, чтобы изменить их цвет и команду.Есть ли способ ссылаться на такой атрибут, как атрибут «текст» кнопки внутри списка?Например, если индекс кнопки имеет текстовый атрибут «+», или «-», или «/», или «*», измените цвет на красный.

Текущий код, который я должен сделать, очень неэффективен, так кактребует, чтобы каждая кнопка была указана индексом индивидуально.Если возможно, я бы хотел ссылаться по атрибуту, а не только по номеру индекса.Рассматриваемый алгоритм можно найти ниже.

#Method that creates calculator buttons, appends them to a list and packs them into the grid.
    def create_number_buttons(self):
        button_characters = "789*456/123-0.=+"
        i = 0
        self.button_list = []
        for row_counter in range(2,6):
            for column_counter in range(4):
                self.button_list.append(Button(root, bg="#11708e", fg="white", activebackground="#11708e", pady=25, padx=35, text=button_characters[i], font=("Helvetica", 16, 'bold')))
                self.button_list[i].grid(row=row_counter, column=column_counter, sticky="NSEW")
                self.button_list[i].configure(command = lambda c=button_characters[i]: self.num_press(c))
                i += 1
        #Reconfigures the specific buttons.
        self.button_list[3].configure(bg="#d14302", activebackground="#d14302")
        self.button_list[7].configure(bg="#d14302", activebackground="#d14302")
        self.button_list[11].configure(bg="#d14302", activebackground="#d14302")
        self.button_list[13].configure(bg="#d14302", activebackground="#d14302")
        self.button_list[14].configure(command=lambda: self.calculate_answer(), bg="#d14302", activebackground="#d14302")
        self.button_list[15].configure(bg="#d14302", activebackground="#d14302")

Спасибо за вашу помощь!

Полный код ниже:)

from tkinter import *
from tkinter import messagebox
#Import so that I'm able to use regex to remove leading zeroes from the equation string when performing the calcultion.
import re

#Class to support logic of calculator, used for functionality and math operations.
class CalculatorFunctions:

    def __init__(self, root):
        self.root = root
        self.answer = 0

   #Command called if a number button is pressed.
    def num_press(self, num):
        new_input = num
        self.text_box.insert(self.value_position, new_input)
        self.value_position += 1

    #Command that clears everything in the calculator's entrybox.
    def clear_screen(self):
        self.text_box.delete(0, END)

    #Creates a message-box popup to display relevant author information.
    def show_author_button(self):
        messagebox.showinfo("Author", "Devin, August 2018")

    #If the eval function returns a syntaxerror or a zerodivision error this command is called.
    #Makes an error message popup box.
    def error_popup(self):
        messagebox.showwarning("Error", "Please edit your code and calculate again.  Common errors include dividing by 0 and including too many decimal points in one number.")

    #Uses the eval function to calculate entered string in calculator.
    def calculate_answer(self):
        errormessage = "SyntaxError"
        try:
            #Removes leading zeroes from the start of digits but not after a decimal point. 
            self.answer = eval(re.sub(r"((?<=^)|(?<=[^\.\d]))0+(\d+)", r"\1\2", self.equation.get()))
        except (SyntaxError, ZeroDivisionError):
            self.error_popup()

        self.answer = eval(re.sub(r"((?<=^)|(?<=[^\.\d]))0+(\d+)", r"\1\2", self.equation.get()))
        #Appends answer to list of values able to be inserted into calculator entry.
        self.accepted_values.append(str(self.answer))
        self.text_box.delete(0, END)
        self.update_entry_with_answer()

    def update_entry_with_answer(self):
        self.text_box.insert(0, self.answer)

    #Removes the last character in the entry field.
    def backspace(self):
        current = str(self.text_box.get())
        new_input = current[:-1]
        self.accepted_values.append(new_input)
        self.text_box.delete(0, END)
        self.text_box.insert(0, new_input)


    #Checks for valid input
    def testVal(self, entered_value, modifytype):

        #Checks if text wanting to be inserted into the entryfield is valid.
        if modifytype == '1': #insert

            operators_and_d_point = "/*+-"
            current_string = str(self.equation.get())

            if entered_value == ".":
                if current_string[-1] == ".":
                    return False

            #If the last character entered was an operator, don't allow another operator or decimal point to be added to the entry box.
            if entered_value in operators_and_d_point:
                if current_string == "":
                    if entered_value == "-" or entered_value == "+":
                        return True
                    else:
                        return False

                if current_string[-1] in operators_and_d_point:
                    if entered_value == "+" or entered_value == "-":
                        return True
                    else:
                        return False


            if entered_value in self.accepted_values:
                return True


        #Accepts all attempts to remove text from the entryfield.
        elif modifytype == "0":#delete
            return True

        return False

#Class to create widgets for the calculator GUI.
class CalculatorGUI(CalculatorFunctions):

    def __init__(self, root):
        self.root = root
        self.value_position = 0
        self.create_calculator_widgets()
        root.bind("=", lambda event: self.calculate_answer())
        self.accepted_values = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", "*", "/", "."]

    #Method called to create widgets associated with the calculator.
    def create_calculator_widgets(self):
        self.create_text_box()
        self.create_number_buttons()
        self.create_clear_button()
        self.create_author_button()
        self.create_backspace_button()

    #Creates entry field, contents of the entry field stored as textvariable.
    def create_text_box(self):
        self.equation = StringVar()
        self.text_box = Entry(root, justify=RIGHT, validate="key", textvariable=self.equation, font=("Helveitca", 16), borderwidth=15)
        #Uses the tkinter entry box's "validatecommand" to check for valid input, method found in above class.
        self.text_box['validatecommand'] = (self.text_box.register(self.testVal),'%S','%d')
        self.text_box.grid(row=0, column=0, columnspan=4, ipady=10, sticky="WE")

    #Method that creates calculator buttons, appends them to a list and packs them into the grid.
    def create_number_buttons(self):
        button_characters = "789*456/123-0.=+"
        i = 0
        self.button_list = []
        for row_counter in range(2,6):
            for column_counter in range(4):
                self.button_list.append(Button(root, bg="#11708e", fg="white", activebackground="#11708e", pady=25, padx=35, text=button_characters[i], font=("Helvetica", 16, 'bold')))
                self.button_list[i].grid(row=row_counter, column=column_counter, sticky="NSEW")
                self.button_list[i].configure(command = lambda c=button_characters[i]: self.num_press(c))
                i += 1
        #Reconfigures the specific buttons.
        self.button_list[3].configure(bg="#d14302", activebackground="#d14302")
        self.button_list[7].configure(bg="#d14302", activebackground="#d14302")
        self.button_list[11].configure(bg="#d14302", activebackground="#d14302")
        self.button_list[13].configure(bg="#d14302", activebackground="#d14302")
        self.button_list[14].configure(command=lambda: self.calculate_answer(), bg="#d14302", activebackground="#d14302")
        self.button_list[15].configure(bg="#d14302", activebackground="#d14302")


    def create_clear_button(self):
        clear_button = Button(root, bg="#302e2e", fg="white", text="AC", font=("Helvetica", 12, 'bold'), pady=10,  command=lambda: self.clear_screen())
        clear_button.grid(row=1, columnspan=2, sticky="WE")


    def create_backspace_button(self):
        backspace_button = Button(root, bg="#302e2e", fg="white", text="Backspace", font=("Helvetica", 12, 'bold'), command=lambda: self.backspace())
        backspace_button.grid(row=1, column=3, sticky="NSEW")

    def create_author_button(self):
        author_button = Button(root, bg="#302e2e", fg="white", font=("Helvetica", 12, 'bold'), text="Info", command=lambda: self.show_author_button())
        author_button.grid(row=1, column=2, sticky="NSEW")



if __name__ == "__main__":
    root = Tk()
    calc = CalculatorGUI(root)
    root.title("Calculator")
    #Ensures the GUI window containing the calculator is unable to be resized, the 0,0 represents the x,y of resize allowed.
    root.resizable(0, 0)
    root.mainloop()

1 Ответ

0 голосов
/ 27 августа 2018

Если вы знаете, что хотите настроить группу виджетов на идентичный стиль, сохраните ссылки на виджеты в выделенном объекте (списке или словаре).Затем вы можете просмотреть эти конкретные ссылки, применяя идентичные настройки.Например, если вы хотите применить красный только к кнопкам оператора.

import tkinter as tk

master = tk.Tk()
numberframe = tk.Frame()
numberframe.grid(row=0, column=0)
button = {}
names = ('one', 'two', 'three', 'four', 'five',
         'six', 'seven', 'eight', 'nine', 'zero')
for num, name in enumerate(names):
   temp = tk.Button(master=numberframe,
                    text=(num+1)%10)
   temp.grid(column=num%3,
             row=num//3,
             sticky='nsew')
   button[name] = temp
operators = {}
operator_frame = tk.Frame()
operator_frame.grid(row=0, column=1)
operation = (('divide', '/'), ('multiply', '*'),
             ('subtract', '-'), ('add', '+'))
for name, sign in operation:
   temp = tk.Button(master=operator_frame,
                    text=sign)
   temp.grid()
   operators[name] = temp
# example individually configure by the reference name.
button['seven'].configure(fg='red')

# example configure by group
for item in operators:
   operators[item].configure(fg='red')
master.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...