pal201
Фев. 25, 2010 15:58:36
Выполняется несколько потоков, нужно что бы каждый поток мог писать в окно scrolledtext. Делаю через глобальную переменную-список.
log=
n_log=
def win():
global log,n_log
tk=Tk()
st=ScrolledText(tk)
st.pack()
if len(log)>len(n_log):
st.insert(END,log)
n_log=log
tk.update()
tk.mainloop()
def print_log(tx):
global log, n_log
print log,n_log
log.extend()
в потоках вызывается функция print_log. нужно что бы обновлялось окно и дописывался лог в это окно. Подскажите как решить?
truporez
Фев. 25, 2010 16:27:30
Если одна очередь на всех, то Queue. Если приватно, то Pipe.
pal201
Фев. 25, 2010 16:45:01
Очередей и пулов нет. Потоки не будут создаваться динамически. Простто есть 3 потока, 1 из них -.> Gui, из дух других нужно писать в scrolledtext, вроде как и задаче не сложная, как решить?
truporez
Фев. 25, 2010 17:06:50
Создать глобальную очередь(Queue) и всем негуевым потокам туда писать, а гуевый тред пусть выгребает.
Можно и через глобальный список, только надо использовать mutex'ы, и учитывая, что списки суть объекты изменяемые - возможны различные глюки.
pal201
Фев. 25, 2010 19:06:16
Дело в том, что я не понимаю как “выгребать”. Например, обновилась переменная список, как заставить перечитать ее GUI? У меня получается, что она читается только один раз в момент создания. Я так понимаю, что нужно сделать некоторый обработчик событий?
truporez
Фев. 25, 2010 20:15:19
Не ленитесь читать документацию.
http://docs.python.org/library/queue.htmlесть методы put и get
pal201
Фев. 25, 2010 20:46:31
все это хорошо, но не понятно! Вот реализация обновления на простом примере, используется переменная:
import Tkinter
import time
curtime = ‘'
clock = Tkinter.Label()
clock.pack()
def tick():
global curtime
newtime = time.strftime(’%H:%M:%S')
if newtime != curtime:
curtime = newtime
clock.config(text=curtime)
clock.after(200, tick)
tick()
clock.mainloop()
Все предельно просто, я хочу так же использовать переменную, а оно что-то не работает, хотя переменная меняется.
truporez
Фев. 25, 2010 21:50:24
ваш пример работает.
а вот пример с использование дополнительной нити
import Tkinter
import time
import Queue
import threading
queue = Queue.Queue()
log_lb = Tkinter.Listbox()
log_lb.pack()
def lb_updater():
global queue
try:
val = queue.get()
log_lb.insert(Tkinter.END, val)
log_lb.see(Tkinter.END)
except Queue.Empty:
pass
log_lb.after(1000,lb_updater)
def worker(queue, stop_event):
while not stop_event.is_set():
queue.put(time.strftime('%H:%M:%S'))
time.sleep(1)
stop_event = threading.Event()
th = threading.Thread(target=worker, args=(queue,stop_event))
th.start()
lb_updater()
log_lb.mainloop()
stop_event.set()
th.join()
pal201
Фев. 27, 2010 16:04:57
Решил проблему обновления таким способом:
def l():
global log
st.delete('1.0',END)
for t in log:
st.insert(END,str(t)+'\n')
tk.after(300,l)
l()
#var=StringVar(tk)
tk.mainloop()
И сразу возник вопрос, у меня запускается gui в отдельном потоке, все вроде выполняется, но главное окно закрывается сразу после завершения основного тела программы. Что делать?
GUI запускаю так:
thread.start_new(win,())
pal201
Фев. 27, 2010 21:36:56
Решил переписать код используя класс, теперь зависает. Что делаю неправильно?:
# -*- coding: utf-8 -*-
from Tkinter import *
import threading,time
from ScrolledText import *
log=
class AppGUI:
global log
def __init__(self):
#self.insert_st #запуск вывода на экран лога
self.tk = Tk()
frame = Frame(self.tk)
frame.pack()
button=Button(frame, text=“Write_Log”, command=self.write_log)
button.pack()
button2=Button(frame, text=“Print_Log”, command=self.print_log('123'))
button2.pack()
self.st=ScrolledText(frame)
self.st.pack()
def insert_st(self):
global log
#print log
self.st.delete('1.0',END)
for t in log:
self.st.insert(END,str(t)+'\n')
self.tk.after(300,self.insert_st)
def run(self):
self.tk.mainloop()
def write_log(self):
threading.Thread(target=gui.insert_st).start()
def print_log(self,tx):
global log
#mutex.acquire()
log.append(tx)
#mutex.release()
gui = AppGUI()
gui.run()