[英]TKinter not inserting a string to Text widget
對於長代碼,如果在我違反本規則之前,我事先表示歉意,因為這是我第一次在此站點上提問。 我對Python相當陌生,但是我目前正在為學校項目編寫程序,該程序從OpenFEC API請求數據,然后將其顯示在使用TKinter創建的GUI中。 如果我打印到控制台,一切都會很好,但是一旦嘗試將數據插入到“文本”小部件中,我將收到錯誤消息,並且不會顯示所有數據。 錯誤為“ TypeError:必須為str,而不是NoneType”,我嘗試使用str(varName)將變量轉換為字符串,但不起作用。 我已經在這個特定問題上工作了幾天,並且在互聯網上搜索了可能的解決方案,但是我沒有找到任何可以幫助我的東西。 感謝您能獲得的任何幫助。
import json
import urllib.request
import urllib.parse
import urllib.error
from tkinter import *
from tkinter import ttk
def inputValidation(year):
# Ask the user for a year
# year = yearEntry.get()
# Input validation
year = int(year) # Converting input to integer for comparison purposes
if year >= 2003 and year <= 2020:
message = "Here are the election dates for " + str(year) + ':' + '\n'
else:
message = "Please enter a valid year."
# Clear out any existing text from entry window
data.config(state=NORMAL)
data.delete(0.0, END)
# Set the data window
data.insert(1.0, message)
data.config(state=DISABLED)
# Convert the year back to a string
year = str(year)
return year
# Function to get API data
def apiCall(event, year, pageNumber):
""" Requests data from OpenFEC API by constructing a url using predetermined
values. """
apiKey = 'rdudHBjgS5srIohVWYyyUL64AOsqVfRkGZD4gvMU'
perPage = '90' # Number of items to print per page
electionYear = year
nullHide = 'true'
nullOnly = 'true'
sort = sortNum.get()
if sort == 1:
sort = '-election_state'
if sort == 2:
sort = '-election_date'
if sort == 3:
sort = 'office_sought'
url = ('https://api.open.fec.gov/v1/election-dates/?per_page=' + perPage +
'&api_key=' + apiKey +
'&election_year=' + electionYear +
'&page=' + pageNumber +
'&sort_hide_null=' + nullHide +
'&sort_null_only=' + nullOnly +
'&sort=' + sort)
uh = urllib.request.urlopen(url)
data = uh.read().decode()
js = json.loads(data)
print(url)
return js # We receive a dictionary with all the
info requested
# Function to print the API info
# Provide a year between 2003 - 2020
def electionDates(event):
year = yearEntry.get() # User provided year
year = inputValidation(year)
pageNumber = '1'
js = apiCall(event, year, pageNumber) # Call the API by using the first function
pages = js['pagination']['pages']
print('TOTAL PAGES: ', pages)
# print('TOTAL ITEMS: ', items)
while int(pages) >= int(pageNumber):
idx = 0
totalItems = 0
items = 0
print('PAGE', pageNumber, 'OF', pages)
for item in js['results']:
state = js['results'][idx]['election_state']
date = js['results'][idx]['election_date']
electionType = js['results'][idx]['election_type_full']
notes = js['results'][idx]['election_notes']
office = js['results'][idx]['office_sought']
# Changing initials from API to full office names
if office == 'S':
office = office.replace('S', 'Senate') # Print out the full word instead of just the initial
if office == 'H':
office = office.replace('H', 'House of Representatives') # Print out the full word, not the initial
if office == 'P':
office = office.replace('P', 'President') # Print out the full word instead of just the initial
idx = idx + 1 # idx allows us to iterate through each item in the dictionary
# Displaying Data in Text Box
data.config(state=NORMAL)
data.insert(2.0, '' +
'\n' 'Date: ' + date +
'\n' 'State: ' + state +
'\n' 'Election Type: ' + electionType +
'\n' 'Office: ' + office +
'\n' 'Notes: ' + notes +
'\n', END)
data.config(state=DISABLED)
items = items + 1
pageNumber = int(pageNumber) + 1
pageNumber = str(pageNumber)
js = apiCall(event, year, pageNumber) # Re-call the API function to print the next page
# -------- GUI CODE --------
root = Tk()
root.title('InfoLection')
frame = Frame(root)
sortNum = IntVar()
""" Create label, button, entry and text widgets into our frame. """
# --- Create instruction label ---
yearLbl = ttk.Label(root, text='Enter Year: ')
yearLbl.grid(row=0, column=1, sticky=E)
# --- Create Entry Box ---
yearEntry = ttk.Entry(root)
yearEntry.grid(row=0, column=2, columnspan=1, sticky=W)
yearEntry.delete(0, END)
yearEntry.insert(0, '')
# --- Create Submit Button ---
submitBtn = ttk.Button(root, text='Submit')
submitBtn.bind('<Button-1>', electionDates)
submitBtn.grid(row=3, column=0, columnspan=5, sticky=NSEW)
# Menu Bar
menu = Menu(root)
root.config(menu=menu)
# Submenu
subMenu = Menu(menu)
menu.add_cascade(label='About', menu=subMenu)
subMenu.add_command(label="Information")
subMenu.add_command(label='Exit')
# --- Radio Buttons to Select Sorting Method ---
# Label
sortByRB = ttk.Label(root, text='Sort by:')
sortByRB.grid(row=1, column=0, sticky=E)
# Radio Buttons
stateSortRB = ttk.Radiobutton(root, text='State', value=1, variable=sortNum)
# Sort by state
stateSortRB.grid(row=2, column=1, sticky=W)
dateSortRB = ttk.Radiobutton(root, text='Date', value=2, variable=sortNum)
# Sort by date
dateSortRB.grid(row=2, column=2, sticky=W)
officeSortRB = ttk.Radiobutton(root, text='Office', value=3,
variable=sortNum) # Sort by Office
officeSortRB.grid(row=2, column=3, sticky=W)
# --- Text Widget To Display Data ---
data = Text(root, width=50, height=25, wrap=WORD)
data.grid(row=4, column=0, columnspan=4, sticky=NSEW)
# --- Scroll Bar ---
scroll = ttk.Scrollbar(root, command=data.yview)
data['yscrollcommand'] = scroll.set
scroll.grid(row=4, column=5, pady=3, sticky=NSEW)
# Window Icon
# --- Keep Window Open ---
root.mainloop()
看起來您的notes變量返回為None。 您可以這樣做,使您的代碼更健壯,更易於調試:
undefined_s = 'N/A'
data.insert(2.0, '' +
'\n' 'Date: ' + (date or undefined_s) +
'\n' 'State: ' + (state or undefined_s) +
'\n' 'Election Type: ' + (electionType or undefined_s) +
'\n' 'Office: ' + (office or undefined_s) +
'\n' 'Notes: ' + (notes or undefined_s) +
'\n', END)
我發現了另一個錯誤並修復了它。
'&sort=' + str(sort))
# ^^^ added the str()
現在代碼運行了。 默認情況下,您應該使單選按鈕之一處於打開狀態。
我確實看到一些說明返回的是未定義的,但是我想這不是錯誤。 只是您要爬網的頁面上的什么信息的問題。 我確實看到其他一些字段也以未定義的形式返回,但這又是您正在爬網的頁面的功能。
您正在嘗試將"Notes: "
和notes
串聯起來,但是有時候notes
是None,並且不能將None添加到字符串中。 您可以手動轉換:
'\n' 'Notes: ' + str(notes) +
...但是我認為利用Python的str.format()
方法會更容易,該方法會自動將其參數轉換為字符串(在格式字符串中沒有任何說明的情況下):
data.insert(2.0, ''
'\n' 'Date: {}'
'\n' 'State: {}'
'\n' 'Election Type: {}'
'\n' 'Office: {}'
'\n' 'Notes: {}'
'\n'.format(date, state, electionType, office, notes)
, END)
...或者您可以使用f字符串,盡管這些僅在Python 3.6和更高版本中可用:
data.insert(2.0, '' +
'\n' f'Date: {date}'
'\n' f'State: {state}'
'\n' f'Election Type: {electionType}'
'\n' f'Office: {office}'
'\n' f'Notes: {notes}'
'\n', END)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.