【问题标题】:Display live console output in tkinter label在 tkinter 标签中显示实时控制台输出
【发布时间】:2018-09-19 03:02:27
【问题描述】:

我试图弄清楚如何做到这一点几天但没有成功。 如标题所述,有没有办法使用 tkinter 在某种文本框或标签中显示控制台输出(特别是下面代码中的打印)?

我有一个程序可以读取 .txt 文件并使用他的数据将一些坐标传递给云,该云在我的公司运行车队管理平台。

感谢任何帮助!

import json
import csv
import math
from math import sin, cos, sqrt, atan2, radians
import requests
from requests.auth import HTTPBasicAuth
import time
from tkinter import Tk, Label, Button, OptionMenu, Text, PhotoImage, StringVar
from functools import partial

begin = False
start = False
running = False
endTrip = False
running_counter = 0
payload_count = 0
num_lines = 0

headers = {
    'Content-Type': 'application/json',
    'Accept': 'text/plain',
}
payload_model = open('payload.json')
payload_file = json.load(payload_model)
file_name = ''
payload_model.close()

def btnStart_func(botao):
    global start
    start = not start
    lbl1['text'] = str(start)

def btnRunn_func(botao):
    global running
    running = not running
    lbl2['text'] = str(running)

def btnEnd_func(botao):
    global endTrip
    endTrip = not endTrip
    lbl3['text'] = str(endTrip)

def changeRoute():
    global file_name
    global num_lines
    file_name = var.get()
    print(file_name)
    try:
        with open(file_name) as fn:
            for line in fn:
                num_lines = num_lines+1
            fn.close()
            print(num_lines)
            num_lines = 0
    except IOError:
        print("file not found")


def beginSend():
    try:
        #'Global' to access the variables outside the function
        global file_name
        global payload_count
        global start
        global running
        global endTrip
        global running_counter
        with open(file_name) as csvfile:
            readCSV = csv.reader(csvfile, delimiter=',')
            for row in readCSV:
                payload_count = payload_count + 1
                if start == False:
                    print("Starting")
                    response = requests.post('SORRY, OMITED ',
                                             json=payload_file, headers=headers, auth=('user', 'password'))
                    print(str(response.status_code))
                    start = True
                elif running == False:
                    lat = row[2]
                    orient = row[3]
                    lon = row[4]
                    direction = row[5]
                    altitude = round(float(row[8]))
                    latdec = round(math.floor(float(lat) / 100) + (float(lat) % 100) / 60, 6)
                    if orient == 'S':
                        lat_decimal = latdec * -1
                    londec = round(math.floor(float(lon) / 100) + (float(lon) % 100) / 60, 6)
                    if direction == 'W':
                        lon_decimal = londec * -1
                    print(lat_decimal)
                    print(lon_decimal)

                    # Passing the coordinates to Json
                    payload_file['d']['message']['latitude'] = lat_decimal
                    payload_file['d']['message']['longitude'] = lon_decimal
                    payload_file['d']['message']['altitude'] = altitude

                    # Saving log files
                    payload_out_name = str(payload_count) + ' - payload_out.json'
                    payload_out = open(payload_out_name, 'w')
                    json.dump(payload_file, payload_out)
                    payload_out.close()
                    print("Running payload " + str(running_counter))
                    response = requests.post('SORRY, OMITED',
                                             json=payload_file, headers=headers, auth=('user', 'password'))
                    print(str(respose.status_code))
                    running_counter = running_counter + 1
                    if running_counter >= num_lines - 2:
                        running = True
                else:
                    if endTrip == False:
                        print("Entering END")
                        response = requests.post('SORRY, OMITED',
                                                 json=payload_file, headers=headers, auth=('user', 'password'))
                        print(str(response.headers))
                        print("END HEADER")
                        endTrip = True


    except IOError as e:
        print(e)


window = Tk()
text = Text(window)
text.tag_configure("BOLD")
window['bg']= 'gray'
bg_image_name = PhotoImage(file = 'SORRY, OMITED')
bg_label = Label(window, image=bg_image_name)
bg_label.place(x=0,y=0)


btn1 = Button(window, text='START', width= '20',font='Helvetica', fg='Blue')
btn1['command'] = partial(btnStart_func,btn1)
btn1.place(x=20,y=70)
btn2 = Button(window, text='RUNNING',width='20',font='Helvetica', fg='Blue')
btn2['command']= partial(btnRunn_func, btn2)
btn2.place(x=20,y=110)
btn3 = Button(window, text='END',width='20',font='Helvetica', fg='Blue')
btn3['command']= partial(btnEnd_func, btn3)
btn3.place(x=20,y=150)
btn5 = Button(window, text='CHANGE ROUTE',width='20',font='Helvetica', fg='Blue', command=changeRoute)
btn5.place(x=20,y=190)
btn4 = Button(window, text='BEGIN',width='20',font='Helvetica', fg='Blue', command=beginSend)
btn4.place(x=100,y=240)


OPTIONS = [
    'hopihari-guaruja.txt',
    'zooGuar-zooSP.txt',
    'picoJaragua-Interlagos.txt',
    'pqIbi-shopTatu.txt'
]

var = StringVar(window)
var.set(OPTIONS[0])

dropMenu = OptionMenu(window, var, *OPTIONS)
dropMenu.place(x=250, y=190)

menu = dropMenu.nametowidget(dropMenu.menuname)
menu.configure(font=('Impact', 20))

lbl1 = Label(window, text=str(start), font='Helvetica', fg='Blue')
lbl1.place(x=290,y=70)
lbl2 = Label(window, text=str(running), font='Helvetica', fg='Blue')
lbl2.place(x=290,y=110)
lbl3 = Label(window, text=str(endTrip), font='Helvetica', fg='Blue')
lbl3.place(x=290,y=150)
lbl4 = Label(window, text='HARDWARE SIMULATOR', font='Helvetica', fg='Black')
lbl4.place(x=70, y=25)



janela.geometry('400x400')
janela.title('HARDWARE SIMULATOR 1.0')
janela.mainloop()

@edit:问题已解决 好的,经过两天的努力,我终于找到了该怎么做。首先,我在函数中剪切了代码,正如您在上面的代码中所见,我的主要逻辑只在一个函数中运行,我将该函数划分为更小的函数,如下所示。 为了显示我使用标签的结果,我创建了一个函数,每次我需要更新我的标签时都会调用它(def attLabel()) 如果您尝试运行上面的代码,您将看到 GUI 在循环发生时冻结,为了解决这个问题,我正在使用 Thread 库,在一个线程中运行我的逻辑,在另一个线程中运行我的 GUI 使我能够显示实时值在标签中。 我知道我的代码并不干净漂亮,但它正在做他应该做的事情,所以......

import json
import csv
import math
from math import sin, cos, sqrt, atan2, radians
import requests
from requests.auth import HTTPBasicAuth
import time
from tkinter import Tk, Label, Button, OptionMenu, Text, PhotoImage, StringVar
import sys
from threading import Thread

begin = False
start = False
running = False
endTrip = False
running_counter = 0
payload_count = 0
num_lines = 0
lat_decimal = 0
lon_decimal = 0

headers = {
    'Content-Type': 'application/json',
    'Accept': 'text/plain',
}
payload_model = open('payload.json')
payload_file = json.load(payload_model)
file_name = ''
payload_model.close()

def attLabel(op):
    global lat_decimal
    global lon_decimal
    i=0
    if op == 'start':
        lbl5['text']= 'Start'
        lbl5.update_idletasks()
    elif op == 'run':
        lbl6['text'] = 'Latitude: ' + str(lat_decimal)
        lbl7['text'] = 'Longitude: ' + str(lon_decimal)
        lbl8['text'] = 'Running'
        lbl6.update_idletasks()
        lbl7.update_idletasks()
        lbl8.update_idletasks()
    elif op == 'end':
        lbl8['text']= 'Finished'
        lbl8.update_idletasks()


def resetBtn():
    global start, endTrip, running, running_counter, payload_count
    start = False
    endTrip= False
    running = False
    payload_count = 0
    running_counter = 0
    lbl5['text']='Output'
    lbl6['text']='Output'
    lbl7['text']='Output'
    lbl8['text']='Output'
    print(str(start)+' e '+str(endTrip)+' e '+str(running)+' e '+str(running_counter)+' e '+str(payload_count))


def changeRoute():
    global file_name
    global num_lines
    file_name = var.get()+'.txt'
    print(file_name)
    try:
        with open(file_name) as fn:
            for line in fn:
                num_lines = num_lines+1
            fn.close()
            print(num_lines)
            lbl5['text'] = 'Route with ' + str(num_lines) + ' points'
            num_lines = 0
    except IOError:
        print("ERRO! Arquivo não encontrado!")

def beginStart():
    i = 0
    try:
        #'Global' para poder acessar as variáveis globais
        global file_name
        global start
        global payload_file
        global headers
        if start == False:
            #resposta = requests.post('SORRY OMITED', json=payload_file, headers=headers, auth=('user','password'))
            #print(str(resposta.status_code))
            lbl5.update_idletasks()
            start = True
            janela.after(100, attLabel('start'))
            run_process=Thread(target= r_unning)
            run_process.start()
    except IOError as e:
        print(e)


def r_unning():
    global file_name
    global payload_count
    global start
    global running
    global endTrip
    global running_counter
    global lat_decimal
    global lon_decimal
    global payload_file
    global headers
    num_lines = 0

    try:
        with open(file_name) as fn:
            for line in fn:
                num_lines = num_lines + 1
            fn.close()
            print(num_lines)
    except IOError as e:
        print(e)
    with open(file_name) as csvfile:
        readCSV = csv.reader(csvfile, delimiter=',')
        for row in readCSV:
            if running == False:
                lat = row[2]
                orient = row[3]
                lon = row[4]
                direction = row[5]
                altitude = round(float(row[8]))
                latdec = round(math.floor(float(lat) / 100) + (float(lat) % 100) / 60, 6)
                if orient == 'S':
                    lat_decimal = latdec * -1
                londec = round(math.floor(float(lon) / 100) + (float(lon) % 100) / 60, 6)
                if direction == 'W':
                    lon_decimal = londec * -1
                print(lat_decimal)
                print(lon_decimal)
                # print(str(resposta.status_code))

                # Passando as coordenadas em decimal para o json enviado
                payload_file['d']['message']['latitude'] = lat_decimal
                payload_file['d']['message']['longitude'] = lon_decimal
                payload_file['d']['message']['altitude'] = altitude

                # Preparando arquivo para enviar
                payload_out_name = str(payload_count) + ' - payload_out.json'
                payload_out = open(payload_out_name, 'w')
                json.dump(payload_file, payload_out)
                payload_out.close()
                print("Payload de running " + str(running_counter))
                # resposta = requests.post(SORRY OMITED', json=payload_file, headers=headers, auth=('user','password'))
                running_counter = running_counter + 1
                janela.after(100, attLabel('run'))
                janela.update_idletasks()
                if running_counter >= num_lines - 2:
                    running = True
                    janela.after(100, end)




def end():
    global endTrip
    if endTrip == False:
        print("Entrando no END")
        lbl8.configure(text='Terminated')
       # resposta = requests.post('SORRY OMITED', json=payload_file, headers=headers, auth=('user','password'))
       # print(str(resposta.headers))
        print("HEADER DO END")
        endTrip = True
        janela.after(500, attLabel('end'))



janela = Tk()
text = Text(janela)
text.tag_configure("BOLD")
janela['bg']= 'gray'
bg_image_name = PhotoImage(file = 'SORRY OMITED.png')
bg_label = Label(janela, image=bg_image_name)
bg_label.place(x=0,y=0)


#btn1 = Button(janela, text='START', width= '20',font='Helvetica', fg='Blue')
#btn1['command'] = partial(btnStart_func,btn1)
#btn1.place(x=20,y=63)
#btn2 = Button(janela, text='RUNNING',width='20',font='Helvetica', fg='Blue')
#btn2['command']= partial(btnRunn_func, btn2)
#btn2.place(x=20,y=103)
#btn3 = Button(janela, text='END',width='20',font='Helvetica', fg='Blue')
#btn3['command']= partial(btnEnd_func, btn3)
#btn3.place(x=20,y=143)
btn5 = Button(janela, text='Select Route',width='10',font='Helvetica', fg='white',bg='black', command=changeRoute)
btn5.place(x=22,y=78)
btn4 = Button(janela, text='Begin',width='10',font='Helvetica', fg='white',bg='black', command=beginStart)
btn4.place(x=22,y=173)
btn6 = Button(janela, text= 'Reset', width = '10', font='Helvetica', fg='white',bg = 'black', command=resetBtn)
btn6.place(x=295,y=173)



OPTIONS = [
    'hopihari-guaruja',
    'zooGuar-zooSP',
    'picoJaragua-Interlagos',
    'pqIbi-shopTatu'
]

var = StringVar(janela)
var.set(OPTIONS[0])

dropMenu = OptionMenu(janela, var, *OPTIONS)
dropMenu.place(x=270, y=78)
menu = dropMenu.nametowidget(dropMenu.menuname)
menu.configure(font=('Impact', 10), fg='white',bg='black')

#lbl1 = Label(janela, text=str(start), font='Helvetica', fg='Blue')
#lbl1.place(x=290,y=63)
#lbl2 = Label(janela, text=str(running), font='Helvetica', fg='Blue')
#lbl2.place(x=290,y=103)
lbl3 = Label(janela, text='Output', font='Helvetica', fg='white',bg='black')
lbl3.place(x=180,y=183)
lbl4 = Label(janela, text='SORRY OMITED', font='Helvetica', fg='white',bg='black')
lbl4.place(x=70, y=25)
lbl5 = Label(janela, text='SAIDA', font='Helvetica', fg='white',bg='black')
lbl5.place(x=180, y=223)
lbl6 = Label(janela, text='SAIDA', font='Helvetica', fg='white',bg='black')
lbl6.place(x=180, y=263)
lbl7 = Label(janela, text='SAIDA', font='Helvetica', fg='white',bg='black')
lbl7.place(x=180, y=303)
lbl8 = Label(janela, text='SAIDA', font='Helvetica', fg='white',bg='black')
lbl8.place(x=180, y=343)


janela.geometry('400x400')
janela.title('HARDWARE SIMULATOR 1.0')
janela.mainloop()

感谢大家的帮助!

【问题讨论】:

  • 看起来您已经使用了一些 Label() 小部件 - 为什么不将这种技术用于 lat/lon/response 呢?
  • 感谢您的建议,我会调查的。
  • 如果您持续(定期)捕获控制台输出,然后将其放入其中,您可以在 tkinter 小部件中显示控制台输出,这可能尽可能接近实时获取它.
  • 我对问题 Run multiple programs sequentially in one Windows command prompt? 的部分回答显示了如何从外部程序(例如控制台)获取输出,这可能有助于您实施我在之前评论中的建议。
  • 我尝试按照 cluskii 告诉我的操作,但我的标签在我的程序运行时没有更新,只有当他完成执行时,我的 GUI 冻结,最后,标签更新发生跨度>

标签: python tkinter console output display


【解决方案1】:

我找到的解决方案是: 创建线程以在 mainloop() 之外运行您的函数 当我们有任何类型的循环进入 de mainloop() 线程时,就会出现问题。 我用那个函数来解决我的问题

定义你自己的名字,我的是endTrue

def endTrue():
    global flag
    send_process = Thread(target=begin)
    send_process.start()
    flag = False

控制新线程内循环的变量

global flag

target = 要在侧线程中执行的函数

send_process = Thread(target=begin)

启动新线程

 send_process.start()

用于控制循环的变量

flag = False

希望这对未来的人有所帮助,gl 和 hf!

【讨论】:

    猜你喜欢
    • 2022-01-22
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    • 2020-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    相关资源
    最近更新 更多