I am trying to achieve reading from subprocess pipe stdout and stderr and updating GUI simultaneously. However my code is waiting all pipe reading process then updates all.
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
import subprocess
import threading
import time
from queue import *
class Application:
# load main window of application
def __init__(self, master):
self.current_script_file_name = None
self.q = Queue()
self.window = master
self.window.title("TK")
self.window.rowconfigure(1, minsize = 600, weight = 2)
self.window.columnconfigure(1, minsize = 600, weight= 2)
# create frame for buttons and create buttons
self.frame_buttons = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
self.button_save = tk.Button(master = self.frame_buttons, text = "Save", command = self.save_script_to_file)
self.button_run = tk.Button(master = self.frame_buttons, text = "Run", command = self.run_script_from_file)
# create frame for tk.Text editor and output
self.frame_text = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
self.text_editor = tk.Text(self.frame_text)
self.text_output = tk.Text(self.frame_text, background = "Black", foreground = "White")
#adjust buttons
self.button_save.grid(row = 0, column = 0, sticky = "ew", padx = 5, pady = 5)
self.button_run.grid(row = 1, column = 0, sticky = "ew", padx = 5)
self.frame_buttons.grid(row = 0, column = 0, sticky = "ns")
#adjust text editor and text output
self.text_editor.grid(row = 0, column = 0, sticky = "ew", padx = 10, pady = 10)
self.text_output.grid(row = 1, column = 0, sticky = "ew", padx = 5, pady = 5)
self.frame_text.grid(row = 0, column = 1, sticky = "ns")
self.text_output.insert(tk.END, 'Script Result:\n')
def run(self):
self.window.mainloop()
def save_script_to_file(self):
file_path = asksaveasfilename(
filetypes=[("Python Scripts", "*.py"), ("Kotlin Scripts", "*.kts*")]
)
if not file_path:
return
with open(file_path, "w") as output_file:
text = self.text_editor.get(1.0, tk.END)
output_file.write("#!/usr/bin/env python3\n")
output_file.write(text)
self.window.title(f"Text Editor Application - {file_path}")
def run_script_from_file(self):
# start thread so main window not going to freeze
threading.Thread(target=self.run_script).start()
self.update()
def run_script(self):
sub_proc = subprocess.Popen(['python','script.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
threading.Thread(target=self.pipe_reader, args=[sub_proc.stdout]).start()
threading.Thread(target=self.pipe_reader, args=[sub_proc.stderr]).start()
def update(self):
while not self.q.empty():
for source, line in iter(self.q.get, None):
self.text_output.insert(tk.END,line)
self.window.after(1000,self.update)
def pipe_reader(self, pipe):
try:
with pipe:
for line in iter(pipe.readline, b''):
self.q.put((pipe, line))
finally:
self.q.put(None)
if __name__ == '__main__':
root = tk.Tk()
app = Application(root)
app.run()
run_script_from_file is a button command. And self.q is a Queue belongs to same class of this functions.
Why my text_output tk.Text field is not updating asap
Script.py :
#!/usr/bin/env python3
import time
counter = 1
while counter < 6:
print ("The current counter value: %d" % counter)
counter = counter + 1
time.sleep(1)
print(asd)
Edit: I put all my code
Edit: Added script.py
Ok, so this is actually not too far off. One common gotcha, due to buffering you have to run python in -u mode. Only other thing really is to have the tkinter update loop running all the time. Try this:
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
import subprocess
import threading
import time
from queue import *
class Application:
# load main window of application
def __init__(self, master):
self.current_script_file_name = None
self.q = Queue()
self.window = master
self.window.title("TK")
self.window.rowconfigure(1, minsize = 600, weight = 2)
self.window.columnconfigure(1, minsize = 600, weight= 2)
# create frame for buttons and create buttons
self.frame_buttons = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
self.button_save = tk.Button(master = self.frame_buttons, text = "Save", command = self.save_script_to_file)
self.button_run = tk.Button(master = self.frame_buttons, text = "Run", command = self.run_script_from_file)
# create frame for tk.Text editor and output
self.frame_text = tk.Frame(master = self.window, relief = tk.RAISED, bd = 2)
self.text_editor = tk.Text(self.frame_text)
self.text_output = tk.Text(self.frame_text, background = "Black", foreground = "White")
#adjust buttons
self.button_save.grid(row = 0, column = 0, sticky = "ew", padx = 5, pady = 5)
self.button_run.grid(row = 1, column = 0, sticky = "ew", padx = 5)
self.frame_buttons.grid(row = 0, column = 0, sticky = "ns")
#adjust text editor and text output
self.text_editor.grid(row = 0, column = 0, sticky = "ew", padx = 10, pady = 10)
self.text_output.grid(row = 1, column = 0, sticky = "ew", padx = 5, pady = 5)
self.frame_text.grid(row = 0, column = 1, sticky = "ns")
self.text_output.insert(tk.END, 'Script Result:\n')
self.update()
def save_script_to_file(self):
file_path = asksaveasfilename(
filetypes=[("Python Scripts", "*.py"), ("Kotlin Scripts", "*.kts*")]
)
if not file_path:
return
with open(file_path, "w") as output_file:
text = self.text_editor.get(1.0, tk.END)
output_file.write("#!/usr/bin/env python3\n")
output_file.write(text)
self.window.title(f"Text Editor Application - {file_path}")
def run_script_from_file(self):
sub_proc = subprocess.Popen(['python3', '-u','script.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
threading.Thread(target=self.pipe_reader, args=[sub_proc.stdout]).start()
threading.Thread(target=self.pipe_reader, args=[sub_proc.stderr]).start()
def update(self):
while not self.q.empty():
source, line = self.q.get()
if line is None:
line = "DONE"
self.text_output.insert(tk.END,line)
self.window.after(100, self.update)
def pipe_reader(self, pipe):
for line in iter(pipe.readline, b''):
self.q.put((pipe, line))
self.q.put((pipe, None))
if __name__ == '__main__':
root = tk.Tk()
app = Application(root)
root.mainloop()
Related
I've built a GUI using Tkinter. On my dual monitor local machine, the appearance of the gui is as it was designed for.
I have the following issues though:
If I move the window to the second monitor, then the frames inside the main window don't resize according to the dimensions of the new monitor, so the gui looks like so I guess it has to do with the fact that I'm using the size of the monitor that the app is open to columnconfigure my frames.
screen_width = int(window.winfo_geometry().split('x', 1)[0])
tab_Digitizer.columnconfigure(0, minsize=int(0.75*screen_width), weight=80)
The second issue is that, if I connect from a remote machine (MacOS with XQuartz) using ssh, by default a small window opens and my gui looks like so
Oddly enough if I maximize the window, the layout gets completely messed up
Since I just started in Python and Tkinter probably I'm doing something wrong but can't figure out what.
Is there a way to automatically resize/rescale/shrink everything depending on the dimensions of the root window?
Also is it possible to do the same for the children of every parent i.e. widgets inside a frame
The code I have is super big to paste here, so I'm giving a link to it
https://pastebin.com/hHEYJ1bR but I have a snippet that might help
import tkinter as tk
import tkinter.font
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from PIL import ImageTk, Image
import screeninfo
from screeninfo import get_monitors
import os
# Method to make Label(Widget) invisible
def hide_frame(frame):
# This will remove the widget
frame.grid_remove()
# Method to make Label(widget) visible
def show_frame(frame, c, r, S, pdx):
# This will recover the widget
frame.grid(column=c, row=r, sticky=S, ipadx=(pdx,0))
# Method to make Label(widget) visible
def show_frame_padx(frame, c, r, S, pdx):
# This will recover the widget
frame.grid(column=c, row=r, sticky=S, padx=(pdx,0))
def populate(frame, rows):
'''Put in some fake data'''
for row in range(rows):
tk.Label(frame,
text = "%s" % row,
).grid(row=row, column=0)
t="Blah blah blah blah blah blah blah blah %s" %row
tk.Label(frame, text=t).grid(row = row,
column = 1,
sticky = EW
)
#____________________________________________________________________________________________
#This will be the main window
window = tk.Tk()
window.resizable(True, True)
window.attributes('-zoomed', True)
window.title("DICER daq")
default_font = tkinter.font.Font(font='TkDefaultFont')
screen_height = window.winfo_screenheight()
window.update()
screen_width = int(window.winfo_geometry().split('x', 1)[0])
screen_height = int(window.winfo_geometry().split('x', 1)[1].split('+', 1)[0])
#____________________________________________________________________________________________
#Upper frame
frame_logo = Frame(window, bd=10)
frame_logo.place(rely=0.0, relx=0.0, relwidth=1.0)
logo_label = tk.Label(frame_logo, text="daq", fg="red", font='Helvetica 18 bold')
logo_label.pack(anchor=W)
label_version = tk.Label(frame_logo, text="version test.0", fg="blue")
label_version.pack(side=LEFT)
#____________________________________________________________________________________________
#Lower frame
frame_main = Frame(window)
frame_main.place(rely=0.10, relx=0.0, relwidth=1.0)
#Create a tabcontrol
tabControl = ttk.Notebook(frame_main)
tabControl.grid(column=0, row=1)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Digitizer tab
tab_Digitizer = ttk.Frame(tabControl)
tabControl.add(tab_Digitizer, text=' Digitizer ')
tab_Digitizer.columnconfigure(0, minsize=int(0.75*screen_width), weight=80)
tab_Digitizer.columnconfigure(1, minsize=75, weight=10)
tab_Digitizer.columnconfigure(2, minsize=75, weight=10)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#This is to select available digitizer channels
def Digitizer_channel_selection(event):
print ("Digitizer channel selected:", var_digitizer_channel.get() )
pass
lbl_general_board_settings = Label(tab_Digitizer, text="Digitizer channel number", font='-weight bold')
lbl_general_board_settings.grid(column=0, row=0, sticky=W)
opt_digitizer_channel = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
var_digitizer_channel = IntVar(tab_Digitizer)
var_digitizer_channel.set(opt_digitizer_channel[0]) # default value
digitizer_channel = OptionMenu(tab_Digitizer, var_digitizer_channel, *opt_digitizer_channel, command = Digitizer_channel_selection)
digitizer_channel.grid(column=1, row=0, sticky=NSEW)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#General board settings
lbl_general_board_registers = Label(tab_Digitizer,
text = "General board registers",
font = '-weight bold',
)
lbl_general_board_registers.grid(column = 0,
row = 1,
sticky = W
)
btn_hide_general_board_registers = Button(tab_Digitizer,
text = "Hide",
font = '-weight bold',
command = lambda: hide_frame(frame_general_board_registers)
)
btn_hide_general_board_registers.grid(column = 1,
row = 1,
sticky = EW
)
btn_show_general_board_registers = Button(tab_Digitizer,
text = "Show",
font = '-weight bold',
command = lambda: show_frame_padx(frame_general_board_registers, 0, 2, EW, 0)
)
btn_show_general_board_registers.grid(column = 2,
row = 1,
sticky = EW
)
frame_general_board_registers = Frame(tab_Digitizer
)
frame_general_board_registers.columnconfigure(0, minsize=int(0.49*0.75*screen_width), weight=50)
frame_general_board_registers.columnconfigure(1, minsize=int(0.25*0.75*screen_width), weight=25)
frame_general_board_registers.columnconfigure(2, minsize=int(0.25*0.75*screen_width), weight=25)
frame_general_board_registers.config(highlightbackground="black", highlightthickness=3)
frame_general_board_registers.grid(column = 0,
row = 2,
sticky = EW,
ipadx = 0
)
populate(frame_general_board_registers, 35)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Channel settings
lbl_channel_registers = Label(tab_Digitizer,
text = "Channel registers",
font = '-weight bold'
)
lbl_channel_registers.grid(column = 0,
row = 3,
sticky = W
)
btn_hide_channel_registers = Button(tab_Digitizer,
text="Hide",
font="-weight bold",
command=lambda: hide_frame(frame_channel_registers)
)
btn_hide_channel_registers.grid(column = 1,
row = 3,
sticky = EW
)
btn_show_channel_registers = Button(tab_Digitizer,
text = "Show",
font = '-weight bold',
command = lambda: show_frame_padx(frame_channel_registers, 0, 4, W, 0)
)
btn_show_channel_registers.grid(column = 2,
row = 3,
sticky = EW
)
frame_channel_registers = Frame(tab_Digitizer
)
frame_channel_registers.grid(column = 0,
row = 4,
sticky = W
)
frame_channel_registers.columnconfigure(0, minsize=int(0.840*0.75*screen_width), weight=84)
frame_channel_registers.columnconfigure(1, minsize=int(0.075*0.75*screen_width), weight=8)
frame_channel_registers.columnconfigure(2, minsize=int(0.075*0.75*screen_width), weight=8)
frame_channel_registers.config(highlightbackground="black", highlightthickness=3)
##Channel settings - PSD
def onFrameConfigure(event):
'''Reset the scroll region to encompass the inner frame'''
canvas.configure(scrollregion=canvas.bbox("all"))
def handle_user_scrolling_up(event):
canvas.yview_scroll(-5, "units")
def handle_user_scrolling_down(event):
canvas.yview_scroll(5, "units")
def handle_scrollbar_scrolling(event):
canvas.configure(scrollregion=canvas.bbox("all"))
lbl_PSD_channel_registers = Label(frame_channel_registers,
text = "DPP-PSD registers",
font = (default_font.actual(), "10", "bold")
)
lbl_PSD_channel_registers.grid(column = 0,
row = 3,
ipadx = 20,
sticky = W)
btn_hide_PSD_channel_registers = Button(frame_channel_registers,
text = "Hide",
font = (default_font.actual(), "10", "bold"),
command = lambda: [hide_frame(canvas), hide_frame(myscrollbar)]
)
btn_hide_PSD_channel_registers.grid(column = 1,
row = 3,
sticky = EW
)
btn_show_PSD_channel_registers = Button(frame_channel_registers,
text = "Show",
font = (default_font.actual(), "10", "bold"),
command = lambda: [show_frame_padx(canvas, 0, 4, EW, 50), show_frame_padx(myscrollbar, 1, 4, NS, 0)])
btn_show_PSD_channel_registers.grid(column = 2,
row = 3,
sticky = EW
)
canvas = tk.Canvas(frame_channel_registers,
height = int(0.20*screen_height)
)
frame_PSD_channel_registers = Frame(canvas
)
frame_PSD_channel_registers.grid(column = 0,
row = 0,
sticky = EW
)
frame_PSD_channel_registers.bind("<Button-4>" , handle_user_scrolling_up)
frame_PSD_channel_registers.bind("<Button-5>" , handle_user_scrolling_down)
frame_PSD_channel_registers.bind("<Configure>", handle_scrollbar_scrolling)
myscrollbar=Scrollbar(frame_channel_registers ,orient="vertical", command=canvas.yview)
canvas.configure(scrollregion=canvas.bbox("all"))
myscrollbar.grid(column = 1,
row = 4,
sticky = NS,
ipadx = 0)
canvas.grid(column = 0,
row = 4,
sticky = EW,
padx = (50,0))
canvas.create_window((0, 0), window=frame_PSD_channel_registers, anchor="nw")
canvas.configure(yscrollcommand=myscrollbar.set)
canvas.columnconfigure(0, minsize=int(0.90*0.84*0.75*screen_width), weight=99)
canvas.columnconfigure(1, minsize=int(0.10*0.84*0.75*screen_width), weight=1)
frame_PSD_channel_registers.columnconfigure(0, minsize=int(0.20*0.84*0.75*screen_width), weight=20)
frame_PSD_channel_registers.columnconfigure(1, minsize=int(0.10*0.84*0.75*screen_width), weight=10)
frame_PSD_channel_registers.columnconfigure(2, minsize=int(0.60*0.84*0.75*screen_width), weight=50)
frame_PSD_channel_registers.config(highlightbackground="black", highlightthickness=1)
populate(frame_PSD_channel_registers, 35)
#This keeps the window open - has to be at the end
window.mainloop()
I really need help, my brain is melting because of this problem. I've studied python for 2 months maybe and I'm not very expert in programming. I've got an issue... I'm using tkinter on this program; in this small GUI I'd like to always keep updated the global variable "temp", and its value should change everytime I click on the button. I know that mainloop() is a blocking method, so it is possible to do something like this?
import tkinter as tk
class App:
def __init__(self):
super().__init__()
self.screen = tk.Tk()
self.screen.geometry("400x400")
self.screen.title("Modifica temperatura ambiente")
self.screen.grid_columnconfigure(0, weight = 1)
self.label = tk.Label(self.screen, text="ENTER TEMPERATUR VALUE", fg = "black", font = ("Calibri", 10) )
self.label.grid(row = 0, column = 0, sticky = "N", pady = 10)
self.input_ = tk.Entry(self.screen)
self.input_.grid(row = 1, column = 0, sticky = "WE", pady = 5, padx = 20)
self.button = tk.Button(self.screen, text = "INVIA", command = self.getvalue)
self.button.grid(row = 2, column = 0, sticky = "WE", pady = 5, padx = 10)
def getvalue(self):
self.temp = self.input_.get()
temperatura_label = tk.Label(self.screen, text = "Last input value is " + self.temp + " degrees", fg = "red")
temperatura_label.grid(row = 3, column = 0, sticky = "S")
return self.temp
app = App()
temp = app.getvalue()
print(temp)
app.screen.mainloop()
Thank for the help!
If you want to print it in the terminal, modify your getvalue function.
Code:
import tkinter as tk
screen = tk.Tk()
screen.geometry("400x400")
screen.title("Modifica temperatura ambiente")
screen.grid_columnconfigure(0, weight = 1)
class App:
def __init__(self, master):
super().__init__()
self.master = master
self.label = tk.Label(master, text="ENTER TEMPERATUR VALUE", fg = "black", font = ("Calibri", 10) )
self.label.grid(row = 0, column = 0, sticky = "N", pady = 10)
self.input_ = tk.Entry(master)
self.input_.grid(row = 1, column = 0, sticky = "WE", pady = 5, padx = 20)
def getvalue(self):
self.temp = self.input_.get()
temperatura_label = tk.Label(self.master, text = "Last input value is " + self.temp + " degrees", fg = "red")
temperatura_label.grid(row = 3, column = 0, sticky = "S")
if self.temp == None:
print()
else:
return self.temp
app = App(screen)
def main_loop():
global app
temp = app.getvalue()
print(temp)
button = tk.Button(screen, text = "INVIA", command = main_loop)
button.grid(row = 2, column = 0, sticky = "WE", pady = 5, padx = 10)
screen.mainloop()
I have a program running that is having issues when the timer runs. Every time "start" is hit, the application crashes. Any thoughts?
##-- Imports --##
import time
import openpyxl as xl
from Tkinter import *
##-- Classes --##
class App(Frame):
def startTimer(self):
self.check = True
self.now = time.strftime("%H:%M:%S")
while self.check == True:
self.timer.configure(text = self.now)
time.sleep(1)
def initUI(self):
self.parent.title("Emma's Time Manager")
self.pack(fill = BOTH, expand = 1)
def initWidget(self):
##Create button definitions##
self.buttonwidth = 12
self.quit = Button(self, text = "Quit", comman = self.quit, width = self.buttonwidth)
self.newClient = Button(self, text = "Add Client", command = lambda:self.newClientFunc(), width = self.buttonwidth)
self.timeStart = Button(self, text = "Start", command = lambda:self.startTimer(), width = self.buttonwidth)
self.timeEnd = Button(self, text = "End", command = lambda:self.endTimer(), width = self.buttonwidth)
self.saveBut = Button(self, text = "Save", command = lambda:self.saveFunc(), width = self.buttonwidth)
self.viewClient = Button(self, text = "View Client", command = lambda:self.viewCliFunc(), width = self.buttonwidth)
##Create lable definitions##
self.timer = Label(self, text = "00:00:00") ##self.timer used as display for timer##
##Create the listbox for Client Selection##
self.wb = xl.load_workbook("clients.xlsx")
self.clientNames = self.wb.get_sheet_names()
self.clivar = StringVar(self)
self.clivar.set(self.clientNames[0])
self.clilist = apply(OptionMenu, (self, self.clivar) + tuple(self.clientNames))
##Create Entry Box to describe work information##
self.info = Entry(self, width = 50)
##Create GUI for widgets##
self.clilist.grid(row = 0, column = 0)
self.timer.grid(row = 0, column = 1)
self.timeStart.grid(row = 0, column = 2)
self.timeEnd.grid(row = 0, column = 3)
self.info.grid(row = 1, column = 0, columnspan = 4)
self.newClient.grid(row = 2, column = 0)
self.viewClient.grid(row = 2, column = 1)
self.saveBut.grid(row = 2, column = 2)
self.quit.grid(row = 2, column = 3)
def __init__(self, parent):
Frame.__init__(self, parent, background = "light blue")
self.parent = parent
self.initUI()
self.initWidget()
def main():
try:
xl.load_workbook("clients.xlsx")
except:
temp = xl.Workbook()
temp.save("clients.xlsx")
temp.remove_sheet(temp.get_sheet_by_name("Sheet"))
root = Tk()
bob = App(root)
root.mainloop()
main()
Please note that most of the program is not yet finished. I just cannot seem to get this timer to run properly.
Looks like you have no way out of your while loop. You'll either need to set self.check to False, or break out of the loop.
while self.check == True:
self.timer.configure(text = self.now)
time.sleep(1)
I'm starting to code with Python and on my first application I have reached a brick wall. Any help on why this code is not displaying the widgets will be greatly appreciated!
import tkinter
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class ImprintPlusApp:
def _init_(self, master):
self.frame_header = ttk.Frame(master)
self.frame_header.pack()
ttk.Label(self.header_frame, text = "Bienvenidos a Imprint Plus Manager")
self.frame_crearorden = ttk.Frame(master)
self.frame_crearorden.pack()
ttk.Label(self.frame_crearorden, text = "Nombre").grid(row = 0, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Email").grid(row = 2, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Numero Cel/Tel").grid(row = 4, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Información Adicional").grid(row = 6, column = 0, padx = 5)
self.entry_name = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_email = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_numtc = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_addinf = Text(self.frame_crearorden, width = 50, height = 10)
self.entry_name.grid(row = 0, column = 1, padx = 5)
self.entry_email.grid(row = 2, column = 1, padx = 5)
self.entry_numtc.grid(row = 4, column = 1, padx = 5)
self.entry_addinf.grid(row = 7, column = 0, columnspan = 2, padx = 5)
ttk.Button(self.frame_crearorden, text = "Submit", command = self.submit).grid(row = 8, columnspan = 1, padx = 5)
ttk.Button(self.frame_crearorden, text = "Clear", command = self.clear).grid(row = 8, columnspan = 0, padx = 5)
def submit(self):
print ("Nombre: {}".format(self.entry_name.get()))
print ("Email: {}".format(self.entry_name.get()))
print ("Num Cel/Tel: {}".format(self.entry_name.get()))
print ("Información Adicional: {}".format(self.entry_name.get(1.0, "end")))
self.clear()
messagebox.showinfo(tite = "Orden #", message = "Orden Guardada")
def clear(self):
self.entry_name.delete(0, "end")
self.entry_email.delete(0, "end")
self.entry_numtc.delete(0, "end")
self.entry_addinf.delete(1.0, "end")
def main():
root = Tk()
app = ImprintPlusApp()
root.mainloop()
if __name__ == '__main__':
main()
Everytime I launch the code I get a blank tkinter window.
This had a few problems.
You had an _init_ method, not an __init__ method, so the created object wasn't being initialized.
You have to send the root tkinter object to the application, with app = ImprintPlusApp(root).
You had a self.header_frame once instead of self.frame_header.
You had a columnspan = 0 (which is invalid) instead of columnspan = 1 (which doesn't really need to be specified).
I've made the above changes in the code below. It may still need debugging, as I don't know exactly what design you had in mind.
import tkinter
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class ImprintPlusApp:
def __init__(self, master):
self.frame_header = ttk.Frame(master)
self.frame_header.pack()
ttk.Label(self.frame_header, text = "Bienvenidos a Imprint Plus Manager")
self.frame_crearorden = ttk.Frame(master)
self.frame_crearorden.pack()
ttk.Label(self.frame_crearorden, text = "Nombre").grid(row = 0, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Email").grid(row = 2, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Numero Cel/Tel").grid(row = 4, column = 0, padx = 5)
ttk.Label(self.frame_crearorden, text = "Información Adicional").grid(row = 6, column = 0, padx = 5)
self.entry_name = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_email = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_numtc = ttk.Entry(self.frame_crearorden, width = 24)
self.entry_addinf = Text(self.frame_crearorden, width = 50, height = 10)
self.entry_name.grid(row = 0, column = 1, padx = 5)
self.entry_email.grid(row = 2, column = 1, padx = 5)
self.entry_numtc.grid(row = 4, column = 1, padx = 5)
self.entry_addinf.grid(row = 7, column = 0, columnspan = 2, padx = 5)
ttk.Button(self.frame_crearorden, text = "Submit", command = self.submit).grid(row = 8, columnspan = 1, padx = 5)
ttk.Button(self.frame_crearorden, text = "Clear", command = self.clear).grid(row = 8, columnspan = 1, padx = 5)
def submit(self):
print ("Nombre: {}".format(self.entry_name.get()))
print ("Email: {}".format(self.entry_name.get()))
print ("Num Cel/Tel: {}".format(self.entry_name.get()))
print ("Información Adicional: {}".format(self.entry_name.get(1.0, "end")))
self.clear()
messagebox.showinfo(tite = "Orden #", message = "Orden Guardada")
def clear(self):
self.entry_name.delete(0, "end")
self.entry_email.delete(0, "end")
self.entry_numtc.delete(0, "end")
self.entry_addinf.delete(1.0, "end")
def main():
root = Tk()
app = ImprintPlusApp(root)
root.mainloop()
if __name__ == '__main__':
main()
I'd like to refer to labels in def check(self) . It should check if feedback from external device equals to something, but I don't know how to refer to label and change colour of it if it's equal or not. I'd like to change for example lab3 background to green or red, depending on equality. Here is my code:
# -*- coding: utf-8 -*-
import Tkinter as T, tkFileDialog
import os
from time import *
import serial
from ttk import Button, Label, Frame, Entry, Style
class Program(Frame):
def __init__(self, root):
Frame.__init__(self, root)
self.root = root
self.initUI()
def initUI(self):
self.root.title('OptoMaQ')
Style().configure('TFrame', background = '#6666ff')
Style().configure('TButton',background = '#6666ff')
lab1 = Label(self, text = 'Press Save to save a file', background = '#6666ff').grid(row = 0, columnspan = 5)
but1 = Button(self, text='Save', command=self.save).grid(row = 2,column = 1)
lab2 = Label(self, text = 'Press Exit to quite', background = '#6666ff').grid(row = 1, columnspan = 5)
but2 = Button(self, text = 'Exit',command = self.exit).grid(row = 2, column = 2)
lab3 = Label(self, text = 'Spectra-Hub', background = '#6666ff').grid(row = 3, columnspan = 5)
lab4 = Label(self, text = 'SpectraPro VM-504',background = '#6666ff').grid(row = 4,columnspan = 5)
lab5 = Label(self, text = 'SpectraPro SP-2-300i',background = '#6666ff').grid(row = 5, columnspan = 5)
but3 = Button(self, text = 'Check',command = self.check).grid(row = 6, columnspan = 5)
lab6 = Label(self, text = 'Type sth here', background = '#6666ff').grid(row = 7,columnspan = 5)
self.entry = Entry(self, justify = 'center',text = '1')
self.entry.grid(row = 8, columnspan =3)
self.fileop = options = {}
options['filetypes'] = [('all files', '.*'),('dat files','.dat'),('text files', '.txt')]
options['initialfile'] = 'file.txt'
options['parent'] = root
def check(self):
port = serial.Serial(15)
command = 'WHO'
port.write(command + '\r')
out = port.read(50)
if out == 'Acton Research Corp. \nSpectra-Hub':
lab3 = Label(self, text = 'Spectra-Hub', background = '#6666ff').grid(row = 3, columnspan = 5)
lab3.config(background = 'green')
port.close()
else:
lab3 = Label(self, text = 'Spectra-Hub', background = '#6666ff').grid(row = 3, columnspan = 5)
lab3.config(background = 'red')
port.close()
port2 = serial.Serial(16)
port2.write(command +'\r')
out2 = port2.read(50)
if out2 == 'Acton Research Corp. \nSpectraPro VM-504':
port2.close()
else:
port2.close()
port3 = serial.Serial(17)
port3.write(command + '\r')
out3 = port3.read(46)
if out3 == 'Acton Research Corp. \n SpectraPro SP-2-300i':
port3.close()
else:
port3.close()
def save(self):
filename = tkFileDialog.asksaveasfilename(**self.fileop)
if filename:
file = open(filename, 'a+')
time = strftime("%A, %d %b %Y, %H:%M:%S ", gmtime())
print time
file.write(time)
file.write('\n')
input = str(self.entry.get())
file.write(input)
file.close()
def exit(self):
root.destroy()
if __name__=='__main__':
root = T.Tk()
Program(root).pack()
root.mainloop()
I've tried something like this in lines 46-53 but it doesn't work. It shows that 'NoneType' object has no attribute 'config' in line 52. Any ideas? It's really important to me please help :)
That is because your labels are only defined in the scope of def initUI(self): and therefore inaccessible to def check(self)
Try defining your buttons as self.lab1 instead of lab1 and also refer to them in the same way.