#python #tkinter
#python #tkinter
Вопрос:
Я пытаюсь создать интерфейс базы данных SQLite, используя python и Tkinter для хранения результатов тестов. По сути, пользователь сначала выбирает опцию из выпадающего меню (панель меню Tkinter), которая генерирует форму с 6 предопределенными тестами для сбора входных данных. Входные данные из этих полей ввода затем сохраняются в SQLite, где каждая строка / тест хранится в отдельной таблице. Будут протестированы разные материалы, но тесты одинаковы для каждого. Я хочу сравнить одни и те же результаты тестирования для нескольких материалов на более позднем этапе для моделирования тенденций и т.д.
Итак, моя идея заключается в том, что строка меню вызывает функцию (которая определяет категорию теста, например, board_strength) для создания формы с датой и номером проекта и которая выполняет макет. Класс используется для генерации полей ввода, получения входных данных, вычисления среднего значения и сохранения значений в SQLite после заполнения каждой строки. Если пользователю требуется дополнительная строка для того же теста, кнопка должна добавить ее по мере необходимости. Затем, если пользователь переходит к следующему тесту (возможно, с помощью кнопки ..), у них снова есть возможность добавить еще одну строку для этого теста и так далее. Здесь я показал только 1 тест, и т.д., но есть еще 5.
Я попытался создать кнопку для генерации новой строки, но, похоже, она не работает должным образом. Я прочитал несколько сообщений на этом сайте и погуглил, и хотя я совсем новичок в работе с классами, это показалось мне самым простым способом сделать то, что я хочу.
from tkinter import *
import tkinter as tk
date = datetime.date.today()
class create_widgets:
'''create widgets for input data, collect input, determine average, and store'''
def __init__(self, window, test_name, units, row):
self.window = root
self.test_name = ''
self.units = ''
self.row = 0
self.add_entry(window, test_name, units, row)
def add_entry(self, window, test_name, units, row):
self.entries = []
lbl_of_test = Label(window, text = f'{test_name} ({units}):', font = ('Arial', 10))
lbl_of_test.grid(row = row, column = 0)
for i in range(3):
self.entry = Entry(window, width=8)
self.entry.grid(row=row, column=i 1)
self.entries.append(self.entry)
def board_strength():
''' Add project details and date and generate test labels'''
lbl1 = Label(top_frame, text = 'Board Strength Properties', font = ('Arial Bold', 12))
lbl1.pack(side = 'top')
display_date = Label(top_frame, text = f'Date: {date}', font = ('Arial', 10))
display_date.pack(anchor = 'w')
sample_lable = Label(top_frame, text = 'Project Number:', font = ('Arial Bold', 10))
sample_lable.pack(anchor = 'sw', side = 'left')
sample_entry = Entry(top_frame, width = 15)
sample_entry.pack(anchor = 'sw', side = 'left')
for i in range(3):
lbl = Label(btm_frame2, text = f'Test: {i 1}', font = ('Arial', 10))
lbl.grid(row=0, column=i 1)
#First test
ect_widgets = create_widgets(btm_frame2, test_name = 'ECT', units = 'kN/m', row = 1)
ect_button = Button(btm_frame2,text='Add ECT', command = ect_widgets.add_entry)
ect_button.grid(row=12,column= 1, pady = 20)
# Next test
# fct_widgets = create_widgets(btm_frame2, test_name = 'FCT', units = 'kPa', row = 1)
# fct_button = Button(btm_frame2,text="FCT", command = fct_widgets.add_entry)
# fct_button.grid(row=12,column= 2, pady = 20)
# Next: Add FCT
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="File", menu=filemenu)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=root.quit)
papermenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Paper", menu=papermenu)
boardmenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Board", menu=boardmenu)
boardmenu.add_command(label="Strength Properties", command = board_strength)
boardmenu.add_command(label="Structural Properties", command= 'board_structure')
root.config(menu=menubar)
root.mainloop()
Когда я запускаю этот код, я получаю следующую ошибку:
TypeError: add_entry() missing 4 required positional arguments: 'window', 'test_name', 'units', and 'row'
Почему ему все еще нужны эти аргументы, если я уже передал их при создании экземпляра ect_widget? И как мне соответственно увеличить номер строки при добавлении новых строк? Номера строк будут головной болью.
Любая помощь или ввод будут высоко оценены. Спасибо!
Комментарии:
1. Опубликуйте полную обратную трассировку
2. Вот полная трассировка: исключение в трассировке обратного вызова Tkinter (последний последний вызов): File «C:UsersAnaconda3libtkinter_ init_ .py», строка 1883, при вызове возвращает self.func(* аргументы) Ошибка типа: add_entry() отсутствуют 4 обязательных позиционных аргумента: ‘window’, ‘test_name’, ‘units’ и ‘row’
3. Может ли ошибка быть в
ect_widgets.add_entry
том, что вы не передаете никаких аргументов?
Ответ №1:
Этого фрагмента кода, который вы предложили, недостаточно для его реального запуска, поэтому я прошу прощения за незначительные ошибки, но я думаю, что я знаю, чего вам здесь не хватает.
Вероятно, вы хотите, чтобы метод add_entry не содержал всех этих требуемых аргументов. Хотя это необходимо для выполнения того, что он делает; вы можете сохранить эти данные в экземпляре класса при его создании.
def __init__(self, window, test_name, units, row):
self.window = window
self.test_name = test_name
self.units = units
self.row = row
self.add_entry()
def add_entry(self):
self.entries = []
lbl_of_test = Label(self.window,
text = f'{self.test_name} ({self.units}):',
font = ('Arial', 10))
lbl_of_test.grid(row = self.row, column = 0)
for i in range(3):
self.entry = Entry(self.window, width=8)
self.entry.grid(row=self.row, column=i 1)
self.entries.append(self.entry)
Что-то вроде этого, вероятно, более уместно. Мы храним атрибуты экземпляра, используя этот синтаксис «self.». «Self.window = window» и т.д. Сохраняет эти вещи, поэтому вы можете использовать их в любое время, не передавая их. Затем в методе add_entry он может использовать сохраненные значения этих объектов, вызывая их версию ‘self.’.
(С технической точки зрения, нет ничего волшебного в использовании слова ‘self’ перед этими переменными; это работает таким образом, потому что ‘self’ является первым аргументом, передаваемым в нестатические методы — включая __init__ — в классе. Все, что первым относится к экземпляру этого класса, следовательно, типичное имя ‘self’. Если вам когда-нибудь понадобится обратиться к экземпляру класса в его собственных методах, вы бы просто использовали ‘self’.)
Я надеюсь, что это поможет, дайте нам знать, если у вас есть еще вопросы.
PS Я разделил эту действительно длинную строку на несколько … как правило, вам не нужны строки длиной более 80 символов, а Python позволяет свободно вырезать строки между элементами внутри круглых скобок.
Комментарии:
1. Спасибо вам обоим за всю вашу помощь! Я решил свою проблему