Why is everything displayed in master window instead of particular frames? - python

So I started creating GUI that I'll use for testbench for electrical engines. My question is why is everything displayed in master window like this?:
Instead of the two frames?
The first time I wrote it, it was working perfectly:
[
but then I wanted to rearrange the code using classes and the problem appeared. I'm using Python 3.7.
My code:
import tkinter as tk
from tkinter import *
from tkinter import messagebox
class Lintebench():
def __init__(self, master):
self.master = master
self.master.title("Linte^2 testbench")
self.master.geometry('1000x600')
#FRAMES
frame = Frame(master, bg='#3e646c').place(relwidth=0.2, relheight=0.4, rely=0.6)
frame2 = Frame(master, bg='#3e646c').place(relwidth=0.8, relheight=0.4, rely=0.6, relx=0.2)
#FRAME 1
self.start_button = Button(frame, text="Start", padx=50, pady=50, bg='green', activebackground='grey', command=self.start_engine).pack()
self.stop_button = Button(frame2, text="Stop", padx=50, pady=50, bg='red', activebackground='grey', command=self.stop_engine).pack()
#FRAME 2
self.parameters = Label(frame2, text="PARAMETERS", font=("Arial", 16), fg='white', bg='#3e646c').place(relx=0)
self.set_parameter = Label(frame2, text="SET", font=("Arial", 16), fg='white', bg='#3e646c').place(relx=0.8)
self.values = Label(frame2, text="VALUES", font=("Arial", 16), fg='white', bg='#3e646c').place(relx=0.4)
self.torque = Label(frame2, text="TORQUE", font=("Arial", 12), fg='white', bg='#3e646c').place(relx=0.7, rely=0.2)
self.velocity = Label(frame2, text="VELOCITY", font=("Arial", 12), fg='white', bg='#3e646c').place(relx=0.7, rely=0.6)
#parameters to set
self.set_torque = Scale(frame2, orient=HORIZONTAL, length=200).place(relx=0.7, rely=0.3)
self.set_velocity = Scale(frame2, orient=HORIZONTAL, length=200).place(relx=0.7, rely=0.7)
def start_engine(*args):
messagebox.showinfo('Information','Engine was started')
def stop_engine(*args):
messagebox.showinfo('Information','Engine was stopped')
def main():
root = Tk()
lintebench = Lintebench(root)
root.mainloop()
if __name__ == '__main__':
main()here

It is because you have chained Frame(...) with place(...) and so frame and frame2 will be None. Separate the chained statement into two statements:
frame = Frame(master, bg='#3e646c')
frame.place(relwidth=0.2, relheight=0.4, rely=0.6)
frame2 = Frame(master, bg='#3e646c')
frame2.place(relwidth=0.8, relheight=0.4, rely=0.6, relx=0.2)
Actually you need to separate all the chained statements in your code if you want to reference the widgets in other place.
Also self.stop_button should be child of frame, not frame2:
self.stop_button = Button(frame, text="Stop", padx=50, pady=50, bg='red', activebackground='grey', command=self.stop_engine)
self.stop_button.pack()

I believe is becuase you're asigning their master as root, and you only have one root and when you make roo.mainloop() that makes them focus.

Related

OOP based tkinter

I want button 1 on to the second frame
from tkinter import *
root =Tk()
class Graphic():
def __init__(self, master):
self.colour = "blue"
self.frame_input = Frame(master, height =100, width=100, bg="green").grid(row=0, column=0)
self.label_process = Label(master, width=30).grid(row=1, column=0)
self.frame_button = Frame(master,height=100,width=100, bg="red").grid(row=2, column=0)
self.button = Button(master, text="1", bg=self.colour).grid(row=0, column=0)
if '__main__' == __name__:
grafic = Graphic(root)
root.mainloop()
The first argument for each widget is the parent to attach to. You told it to attach to master, and it did. If you want it attached to the second frame, change:
self.button = Button(master, text="1", bg=self.colour).grid(row=0, column=0)
to:
self.button = Button(self.frame_button, text="1", bg=self.colour)
self.button.grid(row=0, column=0)
Note, this still doesn't work, because you tried to chain your grid calls, and grid returns None, so all your attributes (including self.frame_button) are None, not widgets. To fix, split the creation and layout steps for all your widgets:
self.frame_input = Frame(master, height =100, width=100, bg="green")
self.frame_input.grid(row=0, column=0)
self.label_process = Label(master, width=30)
self.label_process.grid(row=1, column=0)
self.frame_button = Frame(master,height=100,width=100, bg="red")
self.frame_button.grid(row=2, column=0)
self.button = Button(self.frame_button, text="1", bg=self.colour)
self.button.grid(row=0, column=0)

Program not running when double clicked but runs from cmd?

I have made a python gui using tkinter and i have been running it through the commandline. But when i tried to open it by double clicking, it shortly shows the window but exits again. I tried commenting out all the places where it uses images thinking that it is because it dosent have file-editing permissions when its run by double click and it worked! But i need to use images in the gui, anyone have solutions?
import tkinter as tk
from PIL import Image, ImageTk
import time
root = tk.Tk()
root.title("Krypto Coin")
root.iconbitmap('icon.ico')
root.configure(bg="#112233")
Frame = tk.Frame(root, width=1200, height=800, bg="#112233")
Frame.grid(columnspan=3, rowspan=5)
icon = Image.open('icon_round.png')
icon = ImageTk.PhotoImage(icon)
icon_label = tk.Label(image=icon, borderwidth=0, highlightthickness=0)
icon_label.place(relx=0.5, rely=0.2, anchor="center")
text = tk.Label(root, text="Welcome to Krypto Coin (KTC)", bg="#112233", fg="#ffffff", font=("Arial", 32))
text.place(relx=0.5, rely=0.45, anchor="center")
text = tk.Label(root, text="Enter id of the receiver and amount", bg="#112233", fg="#ffffff", font=("Arial", 24))
text.place(relx=0.5, rely=0.5, anchor="center")
def trasfer_button_pressed():
time.sleep(0.1)
trasfer_button_text.set("Loading...")
trasfer_button.configure(state="disable")
trasfer_button.configure(bg="#112233")
input_id.configure(state="disable")
input_amount.configure(state="disable")
def trasfer_button_enter(e):
if trasfer_button_text.get() == "Transfer":
trasfer_button.configure(bg="#334455")
def trasfer_button_leave(e):
if trasfer_button_text.get() == "Transfer":
trasfer_button.configure(bg="#223344")
trasfer_button_text = tk.StringVar()
trasfer_button = tk.Button(root, textvariable=trasfer_button_text, command=lambda:trasfer_button_pressed(), bg="#223344", fg="#ffffff", width=15, height=1, font=("Arial", 24), borderwidth=0, highlightthickness=0)
trasfer_button_text.set("Transfer")
trasfer_button.place(relx=0.5, rely=0.65, anchor="center")
trasfer_button.bind("<Enter>", trasfer_button_enter)
trasfer_button.bind("<Leave>", trasfer_button_leave)
input_id = tk.Entry(root, width=48, font = "Arial 14", bg="#334455", fg="#ffffff", borderwidth=0, highlightthickness=0)
input_id.insert(0, "ID")
input_id.place(relx=0.45, rely=0.8, anchor="center", height=30)
input_amount = tk.Entry(root, width=20, font = "Arial 14", bg="#334455", fg="#ffffff", borderwidth=0, highlightthickness=0)
input_amount.insert(0, "Amount")
input_amount.place(relx=0.65, rely=0.8, anchor="center", height=30)
root.mainloop()

run commands on a split frame in the main window using tkinter

I'm new to tkinter and i've built this so far:
import tkinter as tk
import subprocess
import os
def maingui():
window = tk.Tk()
window.title("My first GUI")
#window.state('zoomed')
window.geometry("700x205")
window.configure(bg="black")
frame1 = tk.Frame(window, width=90, bg="orange")
# frame1.pack(fill=tk.Y, side=tk.LEFT)
frame1.grid(row=0, column=0)
frame2 = tk.Frame(window, width=1890, bg="black")
# frame2.pack(fill=tk.Y, side=tk.RIGHT)
frame2.grid(row=0, column=1)
lotomat = tk.Button(frame1, text=" Start\n Lotomat", padx=10, pady=5, bg="orange", fg="black",
relief=tk.GROOVE, command=lambda : startLotomat())
# lotomat.pack()
lotomat.grid(row=1, column=0)
convert = tk.Button(frame1, text=" URL2IP \n on \n Desktop", padx=10, pady=5, bg="orange", fg="black",
relief=tk.GROOVE, command=lambda : startURL2IP())
# convert.pack()
convert.grid(row=2, column=0)
startRps = tk.Button(frame1, text=" Start \nR.P.S", padx=12, pady=5, bg="orange", fg="black",
relief=tk.GROOVE, command=lambda : startRPS())
# startRps.pack()
startRps.grid(row=3, column=0)
endRun = tk.Button(frame1, text="Quit", padx=12, pady=10, bg="orange", fg="black",
relief=tk.RIDGE, command=lambda : ending())
# endRun.pack()
endRun.grid(row=4, column=0)
def startLotomat():
os.system('python lotomat.py')
def startURL2IP():
os.system('python urltoipondesktop.py')
def startRPS():
os.system('python rockpaperscissors.py')
def ending():
exit()
window.mainloop()
maingui()
each button runs a different .py file.
how can I use frames to split the window so the program runs on the right side?
Thanks!
Edit:
I've added a pic of the GUI, the goal is to run the left menu buttons on the black frame.
Following acw1668's comment and alot of thread researching here's the thread solution. so elegant, so simple! I love python!
def thread_handler(self, host):
wt = threading.Thread(target=self.write_to_file, args=(host,))
pt = threading.Thread(target=self.print_to_box, args=(host,))
dt = threading.Thread(target=self.delete_default_lines, args=())
wt.start()
pt.start()
dt.start()

Python Tkitner : unknown option "-height". Can't change the size of button

I am trying to make a simple program using tkinter.
I was trying to change font or style of width or height.
width can be changed but when it comes to height or font - it shows mistake.
I am thinking - maybe it can be because the layout?
(The button that is changed in width is in the bottom of def initUI)
Also in case anyone can also answer this question:
I made 1 frame red because there will be error messages there but does anyone know how to make this red lie less in width?
Thank you in
from tkinter import *
from tkinter.ttk import *
class Example(Frame):
def __init__(self,master):
super().__init__()
master.minsize(width=350, height=160)
master.maxsize(width=650, height=500)
self.initUI()
def initUI(self):
self.master.title("Hank (version 3)")
self.pack(fill=BOTH, expand=True)
frame1 = Frame(self)
frame1.pack(fill=X)
#dataset
lbl1 = Label(frame1, text="Dataset file_name", width=18)
lbl1.pack(side=LEFT, padx=5, pady=5)
entryDataset= Entry(frame1)
entryDataset.pack(fill=X, padx=5, expand=True)
#row col begin
frame2 = Frame(self)
frame2.pack(fill=X)
lblRow = Label(frame2, text="Row", width=6)
lblRow.pack(side=LEFT, padx=5, pady=5)
entryRow = Entry(frame2, width=5)
entryRow.pack(side=LEFT, padx=0, expand=True)
lblCol = Label(frame2, text="Column", width=7.5)
lblCol.pack(side=LEFT, padx=5, pady=5)
entryCol = Entry(frame2, width=5)
entryCol.pack(side=LEFT, padx=5, expand=True)
lblBegin = Label(frame2, text="Start at", width=6)
lblBegin.pack(side=LEFT, padx=5, pady=5)
entryBegin = Entry(frame2, width=5)
entryBegin.pack(side=LEFT, padx=0, expand=True)
#console window
s = Style()
s.configure('My.TFrame', background='grey')
frame3 = Frame(self, style='My.TFrame')
frame3.pack(fill=BOTH, expand=True)
#button start and help
s = Style()
s.configure('My.ConsoleFrame', background='red')
frame4 = Frame(self)
frame4.pack(fill=BOTH, expand=True)
startbutton = Button(frame4, text="Start Clustering", height="100", width="100")
startbutton.pack(side=RIGHT, padx=5, pady=5)
def main():
root = Tk()
root.geometry("300x160+300+160")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
This is one of the prime examples of why global imports are bad.
You write at the top:
from tkinter import *
from tkinter.ttk import *
This means that you import everything from tkinter and tkinter.ttk into your main.py namespace. Then you write for example:
frame3 = Frame(self, bg="grey")
....
lblCol = Label(frame2, text="Column", width=7)
These are Frame/Label objects, but which ones? The one in tkinter or the one in tkinter.ttk? If it is the first, you will have to set the height with -height, else you will have to use tkinter.ttk.Style(). Same with the -bg for the frame.
Solution:
import tkinter as tk
class Example(tk.Frame):
def __init__(self,master):
super().__init__()
master.minsize(width=350, height=160)
master.maxsize(width=650, height=500)
self.initUI()
def initUI(self):
self.master.title("Hank (version 3)")
self.pack(fill=tk.BOTH, expand=True)
frame1 = tk.Frame(self)
frame1.pack(fill=tk.X)
#dataset
lbl1 = tk.Label(frame1, text="Dataset file_name", width=18)
lbl1.pack(side=tk.LEFT, padx=5, pady=5)
entryDataset= tk.Entry(frame1)
entryDataset.pack(fill=tk.X, padx=5, expand=True)
#row col begin
frame2 = tk.Frame(self)
frame2.pack(fill=tk.X)
lblRow = tk.Label(frame2, text="Row", width=6)
lblRow.pack(side=tk.LEFT, padx=5, pady=5)
entryRow = tk.Entry(frame2, width=5)
entryRow.pack(side=tk.LEFT, padx=0, expand=True)
lblCol = tk.Label(frame2, text="Column", width=7)
lblCol.pack(side=tk.LEFT, padx=5, pady=5)
entryCol = tk.Entry(frame2, width=5)
entryCol.pack(side=tk.LEFT, padx=5, expand=True)
lblBegin = tk.Label(frame2, text="Start at", width=6)
lblBegin.pack(side=tk.LEFT, padx=5, pady=5)
entryBegin = tk.Entry(frame2, width=5)
entryBegin.pack(side=tk.LEFT, padx=0, expand=True)
frame3 = tk.Frame(self, bg="grey")
frame3.pack(fill=tk.BOTH, expand=True)
frame4 = tk.Frame(self)
frame4.pack(fill=tk.BOTH, expand=True)
startbutton = tk.Button(frame4, text="Start Clustering", height="100", width="100")
startbutton.pack(side=tk.RIGHT, padx=5, pady=5)
def main():
root = tk.Tk()
root.geometry("300x160+300+160")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
I did it here with the tkinter widgets. You can obviously do import tkinter.ttk as ttk and rewrite the code using those, it is just a matter of taste.

tkinter canvas text output

I have been looking at my code for a while and new to tkinter. The purpose of my code is to display text within the Canvas widget not overlay a label. But unsure how to do this:
My code is as follows:
from tkinter import *
class Example(Frame):
def printLabel(self):
self.hello = []
self.hello.append('Hello')
self.hello.append('World!')
return(self.hello)
def updatePanel(self):
self.panelA.config(text="{}".format(self.printLabel()))
def __init__(self, root):
Frame.__init__(self, root)
self.buttonA()
self.viewingPanel()
def buttonA(self):
self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height = 11, width = 13, command=lambda: self.updatePanel())
self.firstPage.place(x=0, y=0)
def viewingPanel(self):
self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3, anchor=NW, text="")
self.panelA.place(x=100, y=0)
self.cl= Canvas(self.panelA,bg='WHITE',width=165,height=113,relief=SUNKEN)
canvas_id = self.cl.create_text(15, 15, anchor="nw")
self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
self.xb.pack(side=BOTTOM,fill=X)
self.xb.config(command=self.cl.xview)
self.yb= Scrollbar(self.panelA,orient="vertical", command=self.cl.yview)
self.yb.pack(side=RIGHT,fill=Y)
self.yb.config(command=self.cl.yview)
self.cl.itemconfig(canvas_id,font=('Consolas',9), text="{}".format(self.printLabel()))
self.cl.configure(scrollregion = self.cl.bbox("all"))
self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
self.cl.config(width=250,height=150)
self.cl.pack(side=LEFT,expand=True,fill=BOTH)
def main():
root = Tk()
root.title("Tk")
root.geometry('378x176')
app = Example(root)
app.pack(expand=True, fill=BOTH)
root.mainloop()
if __name__ == '__main__':
main()
The Hello World! should display without the brackets in the Canvas but the main issue is that when I click on the Button it just overlaps the canvas and prints out the append on to the Label.
The Label should be inside the Canvas.
Here's how to fix the "main issue" along with the "brackets issue". The latter is taken care of by using the string join() method as suggested in the comments.
The updatePanel() method has been modified so it first create a Label widget with the text you want displayed in it, followed by a Canvas "window" object specifying that widget as its contents. Code for the way you were attempting to do it was also removed from the other class methods.
from tkinter import *
class Example(Frame):
def __init__(self, root):
Frame.__init__(self, root)
self.buttonA()
self.viewingPanel()
def printLabel(self):
text = []
text.append('Hello')
text.append('World!')
return ' '.join(text)
def updatePanel(self):
label = Label(self, bg='white', padx=3, pady=3, anchor=NW,
text=self.printLabel())
label.place(relx=0.5, rely=0.5, anchor=CENTER)
self.cl.create_window(100, 100, window=label) # Put Label in a Canvas "window".
def buttonA(self):
self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height=11,
width=13, command=lambda: self.updatePanel())
self.firstPage.place(x=0, y=0)
def viewingPanel(self):
self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3,
anchor=NW, text="")
self.panelA.place(x=100, y=0)
self.cl= Canvas(self.panelA, bg='WHITE', width=165, height=113, relief=SUNKEN)
canvas_id = self.cl.create_text(15, 15, anchor="nw")
self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
self.xb.pack(side=BOTTOM, fill=X)
self.xb.config(command=self.cl.xview)
self.yb= Scrollbar(self.panelA, orient="vertical", command=self.cl.yview)
self.yb.pack(side=RIGHT, fill=Y)
self.yb.config(command=self.cl.yview)
self.cl.itemconfig(canvas_id, font=('Consolas',9), text=self.printLabel())
self.cl.configure(scrollregion=self.cl.bbox("all"))
self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
self.cl.config(width=250, height=150)
self.cl.pack(side=LEFT, expand=True, fill=BOTH)
def main():
root = Tk()
root.title("Tk")
root.geometry('378x176')
app = Example(root)
app.pack(expand=True, fill=BOTH)
root.mainloop()
if __name__ == '__main__':
main()

Categories

Resources