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

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()

Related

Computer keeps restarting when trying to open py2app application

I've made a really simple desktop app using Tkinter. When I set up everything in py2app the program looks like its generated fine, but when I click on it to open my computer restarts everytime. The code will run fine when I run it out of the Python IDE, but my screen goes black and restarts and brings me back to the MacOS login page when I try to run it by clicking on the icon or running the py2app version from the terminal. Has anyone run into this issue?
from tkinter import *
import tkinter
# importing everyting from tkinter
# expression to access among all the functions
expression = ""
# functions
def input_number(number, equation):
# accessing the global expression variable
global expression
# concatenation of string
expression = expression + str(number)
equation.set(expression)
def clear_input_field(equation):
global expression
expression = ""
# setting empty string in the input field
equation.set("Enter the expression")
def evaluate(equation):
global expression
# trying to evaluate the expression
try:
result = str(eval(expression))
# showing the result in the input field
equation.set(result)
# setting expression to empty string
expression = ""
except:
# some error occured
# showing it to the user equation.set("Enter a valid expression")
expression = ""
def new_calc():
new_window = Tk()
new_window.title("A whole new window")
# set the configuration of GUI window
new_window.geometry("450x220")
print('This is a new window!')
# creating the GUI
def main():
# main window
window = Tk()
# setting the title of GUI window
window.title("Calculator")
# set the configuration of GUI window
window.geometry("450x220")
# varible class instantiation
equation = StringVar()
# input field for the expression
input_field = Entry(window, textvariable=equation)
input_field.place(height=100)
# we are using grid position
# for the arrangement of the widgets
input_field.grid(columnspan=4, ipadx=100, ipady=5)
# settin the placeholder message for users
equation.set("Enter the expression")
# creating buttons and placing them at respective positions
_1 = Button(window, text='1', bd=0, command=lambda: input_number(1, equation), height=2, width=7)
_1.grid(row=2, column=0)
_2 = Button(window, text='2', bd=0, command=lambda: input_number(2, equation), height=2, width=7)
_2.grid(row=2, column=1)
_3 = Button(window, text='3', bd=0, command=lambda: input_number(3, equation), height=2, width=7)
_3.grid(row=2, column=2)
_4 = Button(window, text='4', bd=0, command=lambda: input_number(4, equation), height=2, width=7)
_4.grid(row=3, column=0)
_5 = Button(window, text='5', bd=0, command=lambda: input_number(5, equation), height=2, width=7)
_5.grid(row=3, column=1)
_6 = Button(window, text='6', bd=0, command=lambda: input_number(6, equation), height=2, width=7)
_6.grid(row=3, column=2)
_7 = Button(window, text='7', bd=0, command=lambda: input_number(7, equation), height=2, width=7)
_7.grid(row=4, column=0)
_8 = Button(window, text='8', bd=0, command=lambda: input_number(8, equation), height=2, width=7)
_8.grid(row=4, column=1)
_9 = Button(window, text='9', bd=0, command=lambda: input_number(9, equation), height=2, width=7)
_9.grid(row=4, column=2)
_0 = Button(window, text='0', bd=0, command=lambda: input_number(0, equation), height=2, width=7)
_0.grid(row=5, column=0)
plus = Button(window, text='+', bd=0, command=lambda: input_number('+', equation), height=2, width=7)
plus.grid(row=2, column=3)
minus = Button(window, text='-',bd=0, command=lambda: input_number('-', equation), height=2, width=7)
minus.grid(row=3, column=3)
multiply = Button(window, text='*', bd=0, command=lambda: input_number('*', equation), height=2, width=7)
multiply.grid(row=4, column=3)
divide = Button(window, text='/', bd=0, command=lambda: input_number('/', equation), height=2, width=7)
divide.grid(row=5, column=3)
equal = Button(window, text='=', bd=0, command=lambda: evaluate(equation), height=2, width=7)
equal.grid(row=5, column=2)
clear = Button(window, text='Clear', bd=0, command=lambda: clear_input_field(equation), height=2, width=7)
clear.grid(row=5, column=1)
# showing the GUI
window.mainloop()
# start of the program
if __name__ == '__main__':
main()
Here is the setup file:
from setuptools import Extension, setup
APP = ['CalcApp.py']
DATA_FILES = []
OPTIONS = {
'iconfile':'Calculator.icns',
'argv_emulation': True,
'packages': ['certifi'],
}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)

How do I use grid_forget more than once in tkinter?

I'm trying to give myself Excercises using imports and keeping programs and modules separate from each other. In this particular excercise I've given myself, I have a basic feet-to-inches and inches-to-feet converter.
Everything works except for one problem. Where the answer is displayed on the GUI, a new answer covers the old answer, rather than replace.
import tkinter as tk
from tkinter import E, W
import Converter
window = tk.Tk()
window.title("Converter")
answer_label = tk.Label(window, text="No Answer")
answer_label.grid(row=5)
def feet_to_inches_function(old_label):
old_label.grid_forget()
answer_label = tk.Label(window, text=Converter.feet_to_inches(int(entry_bar.get())))
answer_label.grid(row=5)
def inches_to_feet_function(old_label):
old_label.grid_forget()
answer = tk.Label(window, text=Converter.inches_to_feet(int(entry_bar.get())))
answer.grid(row=5)
title_label = tk.Label(window, text="Convert")
entry_bar = tk.Entry(window, font=('HELVETICA', 10))
fti_button = tk.Button(window, text="Feet to Inches", command=lambda: feet_to_inches_function(answer_label))
itf_button = tk.Button(window, text="Inches to Feet", command=lambda: inches_to_feet_function(answer_label))
quit_button = tk.Button(window, text="Quit", command=window.destroy)
title_label.grid(row=0, column=0, sticky=W)
entry_bar.grid(row=1, columnspan=2, sticky=(E, W))
fti_button.grid(row=3, column=0)
itf_button.grid(row=3, column=1)
quit_button.grid(row=4, columnspan=2, sticky=(E, W))
window.mainloop()
Also as a separate question,I'm having a hard time understanding mainloop.I know that it makes the program go in an infinate loop, but from where? I don't see any logical evidence that shows that my code is on an endless loop.
Thanks so much
Here's a solution for you:
import tkinter as tk
from tkinter import E, W
window = tk.Tk()
window.title("Converter")
answer_label = tk.Label(window, text="No Answer")
answer_label.grid(row=5)
def feet_to_inches_function():
answer_label.configure(text='As you want (INCHES)')
def inches_to_feet_function():
answer_label.configure(text='As you want (FEET)')
title_label = tk.Label(window, text="Convert")
entry_bar = tk.Entry(window, font=('HELVETICA', 10))
fti_button = tk.Button(window, text="Feet to Inches", command=feet_to_inches_function)
itf_button = tk.Button(window, text="Inches to Feet", command=inches_to_feet_function)
quit_button = tk.Button(window, text="Quit", command=window.destroy)
title_label.grid(row=0, column=0, sticky=W)
entry_bar.grid(row=1, columnspan=2, sticky=(E, W))
fti_button.grid(row=3, column=0)
itf_button.grid(row=3, column=1)
quit_button.grid(row=4, columnspan=2, sticky=(E, W))
window.mainloop()
All you need is to configure the text of the Label in both functions.

How to hide a part of the frame through button pressing

I have a window with two parts. One part is to do some settings. I want to hide it until the user press a setting button. is it possible to hide a part of the frame that contains many widgets?
I have seen many examples to hide a widget in tkinter (eg. pack_forget and grid_forget). In my case, I am trying to hide a part of the frame through a button press (that contains more than one widgets). Any suggestions please
I can't use more than one frames because of some issues.
import tkinter as tk
def startFn():
pass
#fn body
def stopFn():
pass
#fn body
def FnToShow():
pass
#fn body ???
def FnToHide():
pass
#fn body ???
root = tk.Tk()
root.geometry('600x400')
#two containers like this.
#trying to hide container_2 untill the user press settingBtn
container_1 = tk.Frame(root, borderwidth=2, relief="solid")
container_2 = tk.Frame(root, borderwidth=2, relief="solid")
startBtn = tk.Button(container_1, text = "Start", command =startFn)
startBtn.grid(row=4, column=4)
stopBtn = tk.Button(container_1, text = "Stop", command= stopFn)
stopBtn.grid(row=5, column=4)
settingBtn = tk.Button(container_1, text = "Settings", command= FnToShow)
settingBtn.grid(row=6, column=4)
setting_1 = tk.Label(container_2, text = "Setting-1", fg='#000000')
setting_1.grid(row=3, column=10)
setting_2 = tk.Label(container_2, text = "Setting-2", fg='#000000')
setting_2.grid(row=4, column=10)
closeSettingBtn = tk.Button(container_2, text = "close Settings", command= FnToHide)
closeSettingBtn.grid(row=5, column=10)
container_1.pack(side="left", expand=True, fill="x", padx=1, pady=1)
container_2.pack(side="right",expand=True, fill="x", padx=1, pady=1)
root.mainloop()
You could show/hide the entire container_2 using the functions FnToShow and FnToHide:
something like this:
import tkinter as tk
def startFn():
pass
def stopFn():
pass
def FnToShow():
container_2.pack(side="right",expand=True, fill="x", padx=1, pady=1)
def FnToHide():
container_2.pack_forget()
root = tk.Tk()
root.geometry('600x400')
container_1 = tk.Frame(root, borderwidth=2, relief="solid")
container_2 = tk.Frame(root, borderwidth=2, relief="solid")
startBtn = tk.Button(container_1, text="Start", command =startFn)
startBtn.grid(row=4, column=4)
stopBtn = tk.Button(container_1, text="Stop", command= stopFn)
stopBtn.grid(row=5, column=4)
settingBtn = tk.Button(container_1, text="Settings", command= FnToShow)
settingBtn.grid(row=6, column=4)
setting_1 = tk.Label(container_2, text="Setting-1", fg='#000000')
setting_1.grid(row=3, column=10)
setting_2 = tk.Label(container_2, text="Setting-2", fg='#000000')
setting_2.grid(row=4, column=10)
closeSettingBtn = tk.Button(container_2, text="close Settings", command= FnToHide)
closeSettingBtn.grid(row=5, column=10)
container_1.pack(side="left", expand=True, fill="x", padx=1, pady=1)
root.mainloop()

The button text and color does not appear on Tkinter program

The program works fine on other computers that run window's or ubuntu but the text won't show on the buttons. Here's a snippet of a longer code:
from Tkinter import *
from math import atan
from math import log
import math
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
# --- function ---
def create_first_frame():
global root
global frame
# frame.destroy()
frame = Frame(bg="blue")
frame.pack()
label1 = Label(frame, text="hello!", fg="white", bg="blue", font="normal 30")
label1.pack()
button1 = Button(frame, text="Enter", fg="white", bg="blue", font="normal 20")
button1.pack()
button2 = Button(frame, text="Exit", font="normal", fg="white", bg="red", command=root.destroy)
button2.pack(side=LEFT)
root = Tk()
create_first_frame()
root.mainloop()
We were expecting words like "start" and "exit" to show.
We just want the colors of the buttons to show along with the text
I am not sure what the question is. I took out unnecessary imports, and ran
from tkinter import *
def create_first_frame():
global root
global frame
# frame.destroy()
frame = Frame(bg="blue")
frame.pack()
label1 = Label(frame, text="hello!", fg="white", bg="blue", font="normal 30")
label1.pack()
button1 = Button(frame, text="Enter", fg="white", bg="blue", font="normal 20")
button1.pack()
button2 = Button(frame, text="Exit", font="normal", fg="white", bg="red", command=root.destroy)
button2.pack(side=LEFT)
root = Tk()
create_first_frame()
root.mainloop()
Which creates for me:
This is colored as you have specified...

What can I do to make the frame without widgets?

What I want the frame to do is that when I click on the 'clear' button, the frame is cleaned but it does not and when I enter a string that is not valid and then a valid one, it shows traces of the past and past action. I already tried changing the Label.grid () by a Label.pack (), but it is worse since the 'animation' looks like a stack without removing any element when the 'clear' button is pressed
This is basically what would make it change
from tkinter import *
import tkinter.ttk as ttk
def clear():
area.delete(0,END)
frame.config(bd=1, relief=SUNKEN)
frame.update()
status = Label(frame)
status.grid(row=0, column=0, sticky=NSEW)
def statusVal(value):
if not value == 0:
status = Label(frame, background="#ff4242", fg="#262626", text="Cadena invalida", anchor="center")
status.grid(row=0, column=0)
frame.config(bd=1, relief=SUNKEN, background="#ff4242")
frame.update()
else:
status = Label(frame, background="#56ed42", fg="#262626", text="Cadena valida", anchor="center")
status.grid(row=0, column=0)
frame.config(bd=1, relief=SUNKEN, background="#56ed42")
frame.update()
#Test
def validation():
capture = area.get()
if capture == '1':
return statusVal(0)
else:
return statusVal(1)
root = Tk()
root.geometry("300x150+300+300")
area = Entry(root)
area.grid(row=1, column=0, columnspan=2, sticky=E+W+S+N, padx=5)
frame = Frame(root, bd=1, relief=SUNKEN)
frame.grid(row=2, column=0, padx=5, pady=5, columnspan=2, sticky=W+E+S+N)
frame.columnconfigure(0,weight=5)
frame.rowconfigure(0,weight=5)
abtn = Button(root, text="Validate", command=validation)
abtn.grid(row=1, column=3)
cbtn = Button(root, text="Clear", command=clear)
cbtn.grid(row=2, column=3, pady=5)
root.mainloop()
See if this works better. The main change was to have the status Label always exist and hide or unhide it as desired — instead of creating a new one every time the validation() function was called. I also removed the code that was explicitly updating the frame which isn't necessary.
from tkinter import *
import tkinter.ttk as ttk
def clear():
area.delete(0,END)
status.grid_remove() # Hide. but remember grid options.
def statusVal(value):
if not value == 0:
status.config(background="#ff4242", fg="#262626", text="Cadena invalida",
anchor="center")
status.grid() # Unhide
else:
status.config(background="#56ed42", fg="#262626", text="Cadena valida",
anchor="center")
status.grid() # Unhide
#Test
def validation():
capture = area.get()
if capture == '1':
statusVal(0)
else:
statusVal(1)
# Main
root = Tk()
root.geometry("300x150+300+300")
area = Entry(root)
area.grid(row=1, column=0, columnspan=2, sticky=E+W+S+N, padx=5)
frame = Frame(root, bd=1, relief=SUNKEN)
frame.grid(row=2, column=0, padx=5, pady=5, columnspan=2, sticky=W+E+S+N)
frame.columnconfigure(0,weight=5)
frame.rowconfigure(0,weight=5)
# Initialize status Label.
status = Label(frame, anchor="center")
status.grid(row=0, column=0)
status.grid_remove() # Hide it.
abtn = Button(root, text="Validate", command=validation)
abtn.grid(row=1, column=3)
cbtn = Button(root, text="Clear", command=clear)
cbtn.grid(row=2, column=3, pady=5)
root.mainloop()

Categories

Resources