求问怎么使用多线程让 tkinter 里的数字跳动?

2017-04-29 08:15:23 +08:00
 jin6220

import tkinter

import requests

import threading

from bs4 import BeautifulSoup

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36', 'Referer':'https://wallstreetcn.com/live/global' }

def getprice(url):

  html=requests.get(url, headers=headers).text
  soup=BeautifulSoup(html,'lxml')
  price=soup.find('div',class_='price lt').get_text() #<div class="price lt" data-v-13b642d2="">12438.00</div>
  return price

while True:

g=getprice('https://wallstreetcn.com/markets/indices/GER30INDEX')
top = tkinter.Tk()
label = tkinter.Label(top,text=g)
label.pack()
tkinter.mainloop()
top.wm_attributes('-topmost',1)
7701 次点击
所在节点    Python
15 条回复
jin6220
2017-04-29 08:18:23 +08:00
不太会 md 格式 找了个网站贴了代码进去 然后所见所得修改了下贴进来 确实是好看了点
昨天试了大半天 看了多进程 多线程 锁 队列 但是还是写不出来
icedx
2017-04-29 08:19:00 +08:00
印象里不能用 while true

会阻塞界面的绘制
jin6220
2017-04-29 08:23:37 +08:00
@icedx 哦 那是不是把 getprice 放进多线程里?通过队列取出这个返回值,但是昨天试了一天还是不成功;或者其他方法怎么实现呐
icedx
2017-04-29 08:25:12 +08:00
对的
zjqzxc
2017-04-29 08:49:48 +08:00
当然是多线程,在线程中完成对主界面的更新工作

getprice 操作放进新线程里,每次需要绘制的时候执行一次,修改对应的 label 的 text 属性即可
jin6220
2017-04-29 08:52:06 +08:00
import tkinter
import requests
import threading
from bs4 import BeautifulSoup
import queue #import Queue

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36',
'Referer':'https://wallstreetcn.com/live/global'
}
def getprice(url):
html=requests.get(url, headers=headers).text
soup=BeautifulSoup(html,'lxml')
price=soup.find('div',class_='price lt').get_text() #<div class="price lt" data-v-13b642d2="">12438.00</div>
q.put(price)
return price

while True:
q = queue.Queue()
p = threading.Thread(target=getprice,args=('https://wallstreetcn.com/markets/indices/GER30INDEX',))
p.start()

qprice=q.get()
top = tkinter.Tk()
label = tkinter.Label(top,text=qprice)
label.pack()
tkinter.mainloop()
top.wm_attributes('-topmost',1)
写了个 不知道这个爬虫网页价格放到 tk 里随价格变化而变化,实现了没。
jin6220
2017-04-29 08:57:21 +08:00
@zjqzxc 您意思是绘制的 tk 也放进一个线程了吗? 6 楼那个怎么样?刚才试了可以显示价格,不知道堵塞没,但是功能太简单了。还想实现这些:价格有变化绘制 tk,没变化不用管。
zjqzxc
2017-04-29 09:05:05 +08:00
from tkinter import *
import threading
import time

root = Tk()
label1 = Label(root,text='0')
label1.pack()

def getPrice():
return time.time()

def threadGetPrice():
while(True):
label1['text'] = getPrice()
time.sleep(1)

t = threading.Thread(target=threadGetPrice,args=(),name='thread-refresh')
t.setDaemon(True)
t.start()

root.mainloop()

大概是这么个意思
如果想实现价格变化时绘制(修改 text ),可以在 threadGetPrice()中进行判断
jin6220
2017-04-29 09:08:33 +08:00
while 循环一次:构建队列,获取价格并放进队列,然后取出价格并绘制图形界面。
想实现价格有变化绘制图形,没变化不要管看来有点难度(针对我这种小白哈)
因为每次循环都是一个新的队列一个, 新的价格啊
zjqzxc
2017-04-29 09:15:03 +08:00
@jin6220 如果只是为了修改界面上的价格,完全没必要使用队列。

简单的思路是,有一个线程,在 while true:中获取最新价格,然后看是否改变了决定要不要更新主界面对应的 label 标签的 text 值;循环最后加一个 time.sleep(1)每次获取操作间隔 1 秒

另外:新建线程的操作不要放在 while 中。。更新操作交给新创建的线程来做
zjqzxc
2017-04-29 09:25:52 +08:00
import time
import tkinter
import requests
import threading
from bs4 import BeautifulSoup

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36',
'Referer':'https://wallstreetcn.com/live/global'
}
def getPrice(url):
(space)html=requests.get(url, headers=headers).text
(space)soup=BeautifulSoup(html,'lxml')
(space)price=soup.find('div',class_='price lt').get_text()
(space)return price

root = tkinter.Tk()
label1 = tkinter.Label(root,text='init...')
label1.pack()

def threadGetPrice():
(space)while(True):
(space)(space)label1['text'] = getPrice('https://wallstreetcn.com/markets/indices/GER30INDEX')
(space)(space)time.sleep(5)

t = threading.Thread(target=threadGetPrice,args=(),name='thread-refresh')
t.setDaemon(True)
t.start()

root.mainloop()
jin6220
2017-04-29 09:36:20 +08:00
@zjqzxc 嗯请问下 t.setDaemon(True) 这个是不是更新线程的操作,查了下说这是设置守护线程,如果是更新线程的话,为什么 def threadGetPrice()函数下面还要加一句 while True 呐,
jin6220
2017-04-29 09:39:55 +08:00
感觉到了进程 线程 这里 明显到了 python 的易学难精的地方了。。。
感觉大山来了 当初类 实例之类的马马虎虎地啃下来算是能看懂别人写的代码
但是进程 线程 锁之类的东西 完全看不懂 自猜: 好像搞懂 python 的运行机制才能玩转这些东西了 :)
jin6220
2017-04-29 10:11:15 +08:00
@zjqzxc 有点理解那个 while true 了 交作业了 只能等到周一看行不行了 这样就能桌面显示了

zjqzxc
2017-04-29 10:17:28 +08:00
@jin6220 这个 setDaemon 的作用并不是让代码循环执行。没有 while true,threadGetPrice()里的代码将只执行一次;
setDaemon(True)的作用:父线程启动了子线程,当父线程结束,子线程跟着同时被 kill;
setDaemon(False)的作用:父线程启动了子线程,当父线程结束,会等待子线程结束后,主线程才会结束;

如果把 setDaemon 改为 false,关闭窗体后 threadGetPrice ()继续执行,但此时主窗体已经不存在了,执行更新操作时会报错;

为啥会发生这个,具体原因我也没有确切答案。
猜测可能的原因是,tkinter 窗口的线程并不是手动创建的线程的父线程,关闭 tkinter 窗体的操作并不会等待手动创建的线程结束,所以就有问题了;
表现是:如果 setDaemon ( False ),关闭窗体后进程并不会立刻终止,而是等子线程完成后才会终止。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/358068

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX