我刚刚开始利用Python的tkinter模块创建一些基本的GUI。在下面显示的GUI中,提示用户选择机油指数,随后的价格信息将出现(价格信息已通过网络抓取)。但是,我还没有找到一种方便的方法来清除用户选择其他油价指数时的定价标签文本。我在下面附有完整的代码。任何建议将不胜感激。谢谢。
# Import Python Modules
from tkinter import *
from ttk import *
import urllib2
from bs4 import BeautifulSoup
import re
# Generate Basic Window
root = Tk()
root.geometry("225x125")
root.resizable(0,0)
root.title("Global Oil Price GUI")
# Functions
def fetchdata(event):
index = combo.current() # Get index of combobox selection
# Obtain HTML
url = 'http://oilprice.com/oil-price-charts/45' # URL to be scraped
content = urllib2.urlopen(url)
parsed = BeautifulSoup(content,'html.parser')
# Parse HTML
oilprice = parsed.findAll('td',attrs = {'class': 'last_price'})
change = parsed.findAll('td',{'class':['change_up flat_change_cell','change_down flat_change_cell','change_up','change_down']})
change_percent = parsed.findAll('td',{'class':['change_up_percent percent_change_cell','change_down_percent percent_change_cell','change_up_percent','change_down_percent']})
# Pre-Initialize Arrays
oilprice_extract = []
change_extract = []
change_percent_extract = []
time_extract = []
# Loop and Extract Text
for ele_price, ele_change, ele_change_percent in zip(oilprice,change,change_percent):
oilprice_extract.append(float(ele_price.text))
change_extract.append(ele_change.text)
change_percent_extract.append(ele_change_percent.text.split('%')[0] + '%')
time_extract.append(re.sub('\n\t',' ',ele_change_percent.text.split('%')[1]))
# Fill Field Based Upon Selection
price_label = Label(root,text = oilprice_extract[index]).grid(row = 2,column = 2)
change_label = Label(root,text = change_extract[index]).grid(row = 3,column = 2)
change_percent_label = Label(root,text = change_percent_extract[index]).grid(row = 4,column = 2)
update_label = Label(root,text = time_extract[index]).grid(row = 5,column = 2)
# Driver Code
combo_label = Label(root,text = "Futures & Indexes",justify = LEFT).grid(row = 0, column = 0)
combo = Combobox(root,values = ["WTI Crude","Brent Crude","Mars US","OPEC Basket","Canadian Crude Index"],width = 17)
combo.grid(row = 1, column = 0)
combo.bind("<<ComboboxSelected>>",fetchdata)
price_display = Label(root,text = " Price (USD):").grid(row = 2,column = 0)
change_display = Label(root,text = "Change:").grid(row = 3,column = 0)
change_percent_display = Label(root,text = "Change Percent:").grid(row = 4,column = 0)
update_display = Label(root,text = "Last Updated:").grid(row = 5,column = 0)
root.mainloop() # Run window continuously**
更新:
仍然是一个小问题。
场景:用户选择WTI Crude作为第一选择,它显示:“最新更新:(11分钟延迟)”
然后,用户选择“火星美国”,其上应显示“最新更新:(2天延迟)”
问题:这张照片上的标签相互重叠EXAMPLE PHOTO 有什么解决办法吗?
答案 0 :(得分:0)
以下脚本显示了一个示例,其中标签动态递增1,直到按下停止按钮为止:
import tkinter as tk
counter = 0
def counter_label(label):
def count():
global counter
counter += 1
label.config(text=str(counter))
label.after(1000, count)
count()
root = tk.Tk()
root.title("Counting Seconds")
label = tk.Label(root, fg="green")
label.pack()
counter_label(label)
button = tk.Button(root, text='Stop', width=25, command=root.destroy)
button.pack()
root.mainloop()
参考:https://www.python-course.eu/tkinter_labels.php
您不应一遍又一遍地重新创建标签。
此外,我认为下面的示例会更好。
from tkinter import *
from tkinter.ttk import *
import requests
from tkinter.ttk import Combobox
from bs4 import BeautifulSoup, SoupStrainer
# import re # As long as you can make do with str.replace(), you should use it instead of re.sub.
class CQueryOil(Tk):
def __init__(self, query_country: list):
super().__init__() # init Tk
self.__url = 'http://oilprice.com/oil-price-charts/45'
self._query_country = query_country
self._intvar_price = IntVar()
self._strvar_change = StringVar(value='')
self._strvar_change_percent = StringVar(value='')
self._strvar_update_time = StringVar(value='')
self.init_ui()
@property
def url(self):
return self.__url
@property
def query_list(self):
return self._query_country
def run(self):
self.mainloop()
def init_ui(self) -> None:
self.geometry("225x125")
self.resizable(0, 0)
self.title("Global Oil Price GUI")
[self.grid_columnconfigure(col, weight=1) for col in (1, 2)]
n_padx = 5
Label(self, text="Futures & Indexes", justify=LEFT).grid(row=0, column=0, padx=n_padx, sticky='w')
combo = Combobox(self, values=self.query_list, width=17)
combo.grid(row=1, column=0, padx=n_padx, columnspan=2, sticky='w')
combo.bind("<<ComboboxSelected>>", lambda event: self.update(event, combo=combo))
for cur_row, label_name in enumerate(['Price (USD):', 'Change:', 'Change Percent:', 'Last Updated:']):
Label(self, text=label_name, width=14).grid(row=2 + cur_row, column=0, padx=n_padx, sticky='e')
Label(self, textvariable=self._intvar_price).grid(row=2, column=1, sticky='w')
Label(self, textvariable=self._strvar_change).grid(row=3, column=1, sticky='w')
Label(self, textvariable=self._strvar_change_percent).grid(row=4, column=1, sticky='w')
Label(self, textvariable=self._strvar_update_time).grid(row=5, column=1, sticky='w')
def update(self, event, combo) -> None:
resp = requests.get(self.url)
if resp.status_code != 200:
return
filter_data = SoupStrainer('tr', attrs={'class': ['stripe show_graph', 'stripe show_graph update_on_load']
# 'data-id': ['45', '46', '50', '29', '68']
})
parsed = BeautifulSoup(resp.text, 'lxml', parse_only=filter_data)
idx = combo.current() # Get index of combobox selection
try:
dst_td_tags = parsed.find('td', string=self.query_list[idx]).find_next_siblings()
except:
import traceback
print(traceback.format_exc())
raise NameError(f'====Must match the data on the web page. Name:{self.query_list[idx]}=====') # literal format Py3.6↑
dst_list = [td.text for td in dst_td_tags]
price, change, change_percent, update_time = dst_list
change_percent = change_percent.split('%')[0] # As long as you can make do with str.replace(), you should use it instead of re.sub.
update_time = update_time.replace('\n\t', ' ')
change_percent = change_percent
update_time = update_time
self._intvar_price.set(price)
self._strvar_change.set(change)
self._strvar_change_percent.set(change_percent)
self._strvar_update_time.set(update_time)
if __name__ == '__main__':
obj = CQueryOil(["WTI Crude", "Brent Crude", "Mars US", "Opec Basket", "Canadian Crude Index"]) # Must match the data on the web page
obj.run()
答案 1 :(得分:0)
正确的方法是使用StringVar
设置Label
的初始值,然后您只需要调用.set()
实例的StringVar
方法要更新。
示例:
price_str = StringVar()
prica_label = Label(root, textvariable=price_str).pack()
price_str.set("new price")