I am learning a bit of tkinter at the moment and have come across a problem I can't seem to solve.
I have 1 class (named 'GUI') in which I first declare an object of another class (named 'client') then create a simple tkinter GUI with an entry field in which the user enters an address.
I then have a button that when pressed, gets the address and passes it to a function of the client class. This function calls another function from a library, which goes out to an external source (the 'client') and gets the value of a boolean register at that address.
Up to here I have working.
I now would like to update another entry field in the tkinter GUI with the value of that Boolean register.
Here is a code sample:
class GUI:
def __init__(self, master):
device = client()
self.master = master
#Define size (x,y) and position (top left is 0,0) of window
master.geometry("800x400+300+300")
#Disable window resize
master.resizable(width=False, height=False)
#GUI Controls
lbl_read_discrete_output = Label(self.master, text="Read boolean register")
lbl_read_discrete_output_address = Label(self.master, text="Address:")
ent_read_discrete_output_address = Entry(self.master)
btn_read_discrete_output_address = Button(self.master, text='READ', command=lambda: device.read_discrete_output(int(ent_read_discrete_output_address.get())))
ent_read_discrete_output_value = Entry(self.master, state='disabled')
#GUI Layout
lbl_read_discrete_output.grid(column=0, row=6, padx=5, pady=5)
lbl_read_discrete_output_address.grid(column=0, row=7, padx=5, pady=5)
ent_read_discrete_output_address.grid(column=1, row=7, padx=5, pady=5)
btn_read_discrete_output_address.grid(column=2, row=7, padx=5, pady=5)
ent_read_discrete_output_value.grid(column=3, row=7, padx=5, pady=5)
class client:
def __init__(self):
pass
def read_discrete_output(self, address):
data = self._client.read_coils(address-1, 1).bits[0:1]
if not data[0]:
#Update entry field 'ent_read_discrete_output_value' with "FALSE"
else:
#Update entry field 'ent_read_discrete_output_value' with "TRUE"
def main():
#Create GUI object
root = Tk()
app = GUI(root)
root.mainloop()
if __name__ == '__main__':
main()
Any help would be greatly appreciated!
You can solve that problem, this way:
import tkinter as tk
from tkinter import *
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
class GUI:
def __init__(self, master):
self.master = master
#GUI Controls
lbl_read_discrete_output = Label(self.master, text="Read boolean register")
lbl_read_discrete_output_address = Label(self.master, text="Address:")
self.ent_read_discrete_output_address = Entry(self.master)
btn_read_discrete_output_address = Button(self.master, text='READ', command=lambda: device.read_discrete_output(int(self.ent_read_discrete_output_address.get())))
self.ent_read_discrete_output_value = Entry(self.master, state='disabled')
#GUI Layout
lbl_read_discrete_output.grid(column=0, row=6, padx=5, pady=5)
lbl_read_discrete_output_address.grid(column=0, row=7, padx=5, pady=5)
self.ent_read_discrete_output_address.grid(column=1, row=7, padx=5, pady=5)
btn_read_discrete_output_address.grid(column=2, row=7, padx=5, pady=5)
self.ent_read_discrete_output_value.grid(column=3, row=7, padx=5, pady=5)
self.x=self.ent_read_discrete_output_address.get()
print(self.x)
device=clientx(self.ent_read_discrete_output_value,self.ent_read_discrete_output_address.get())
class clientx():
def __init__(self,ent,address):
self.address=address
self.ent=ent
def read_discrete_output(self, address):
with ModbusClient('127.0.0.1') as client:
data = self.client.read_coils(address-1, 1).bits[0:1]
if not data[0]:
self.ent.config(state="disabled")
else:
self.ent.config(state="disabled")
def main():
#Create GUI object
root = tk.Tk()
app = GUI(root)
root.mainloop()
if __name__ == '__main__':
main()
Let me know if this works.
Related
Using Python I have created a frame with empty ComboBox, TextBox and a Button. My ComboBox values are taken from List acitivity_list which initialy is empty. I am looking for a solution where user can insert a text into a TextBox and append the List activity_list so it appears in ComboBox by clicking the Button.
I failed implementing the append() function to update the List. My goal is to have a functionality where I write the name of activity in the TextBox, click the 'Add' Button and it appears in my ComboBox.
Thank you.
from tkinter import *
from tkinter import ttk
class Activity:
def __init__(self,root):
self.root=root
self.root.title("database")
self.root.geometry("1350x700+0+0")
title=Label(self.root, text="Daily Activities Database", font=("Calibri",40,"bold"))
title.pack(side=TOP)
#ComboBox
activity_list = []
Frame1=Frame(self.root,bd=4, relief=RIDGE)
Frame1.place(x=20, y=75, width=355, height=560 )
combo_activity=ttk.Combobox(Frame1, font=("Calibri",20))
combo_activity["values"]= activity_list
combo_activity.grid(row=10, column=1, padx=20, pady=10)
#Textbox
txt_act=Entry(Frame1, font=("Calibir",20))
txt_act.grid(row=11, column=1, padx=20, pady=20)
#Button
bt1 = ttk.Button(Frame1, text = "Add")
bt1.grid(row=12, column=1, padx=20, pady=20)
root=Tk()
ob=Activity(root)
root.mainloop()
Add an instance method which is triggered when Add is clicked. In the function, add the user input into activity_list and then update the values option of combo_activity.
However, you need to change some local variables to instance variables, otherwise they cannot be accessed inside the new function:
from tkinter import *
from tkinter import ttk
class Activity:
def __init__(self, root):
self.root = root
self.root.title("database")
self.root.geometry("1350x700+0+0")
title=Label(self.root, text="Daily Activities Database", font=("Calibri",40,"bold"))
title.pack(side=TOP)
Frame1 = Frame(self.root,bd=4, relief=RIDGE)
Frame1.place(x=20, y=75, width=355, height=560 )
#ComboBox
self.activity_list = []
self.combo_activity = ttk.Combobox(Frame1, font=("Calibri",20))
self.combo_activity["values"] = self.activity_list
self.combo_activity.grid(row=10, column=1, padx=20, pady=10)
#Textbox
self.txt_act = Entry(Frame1, font=("Calibir",20))
self.txt_act.grid(row=11, column=1, padx=20, pady=20)
#Button
bt1 = ttk.Button(Frame1, text="Add", command=self.add_activity) # added command option
bt1.grid(row=12, column=1, padx=20, pady=20)
def add_activity(self):
activity = self.txt_act.get().strip()
if activity:
self.activity_list.append(activity)
self.combo_activity["values"] = self.activity_list
root = Tk()
ob = Activity(root)
root.mainloop()
Thank you for help. I have adjusted the code like this and the button disappeared for the frame. Perhaps there is something wrong with indentation?
from tkinter import *
from tkinter import ttk
class Activity:
def __init__(self,root):
self.root=root
self.root.title("database")
self.root.geometry("1350x700+0+0")
title=Label(self.root, text="Daily Activities Database", font=("Calibri",40,"bold"))
title.pack(side=TOP)
#ComboBox
activity_list = []
Frame1=Frame(self.root,bd=4, relief=RIDGE)
Frame1.place(x=20, y=75, width=355, height=560 )
combo_activity=ttk.Combobox(Frame1, font=("Calibri",20))
combo_activity["values"]= activity_list
combo_activity.grid(row=10, column=1, padx=20, pady=10)
#Textbox
txt_act=Entry(Frame1, font=("Calibir",20))
txt_act.grid(row=11, column=1, padx=20, pady=20)
#Button
def add_task(self):
activity = txt_act.get()
activity_list.append(activity)
return activity_list
bt1 = ttk.Button(Frame1, text = "Add")
bt1.grid(row=12, column=1, padx=20, pady=20, command=add_task)
root=Tk()
ob=Activity(root)
root.mainloop()
I am creating a login system with Tkinter and the grid() method but I have no idea where I can put the image. As i did not use classes and functions, it was pretty easy to embed the path for the image (img = PhotoImage(file = r"C:\\Users\\admin\\Desktop\\Foto\\Haken.png") img1 = img.subsample(10,10), but, since I am new in Python, I donĀ“t really know where to put the path in this code when the code is more organized. Here is what I tried:
from tkinter import *
from tkinter.ttk import *
class Login_system(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Login System Prova")
Label(text = "Surname").grid(row=0, column=0, sticky=W, pady=2)
Label(text = "Your Password").grid(row=1, column=0, sticky=W, pady=2)
Label(text = "Your E-Mail").grid(row=2, column=0,sticky=W, pady=2)
Entry().grid(row = 0, column=1, pady=2)
Entry().grid(row = 1, column=1, pady=2)
Entry().grid(row = 2, column=1, pady=2)
Entry().grid(row = 3, column=1, pady=2)
Checkbutton(text = "Keep me on-line").grid(row = 4, sticky = W, columnspan= 1)
def main():
root = Tk()
root.geometry("200x150+400+300")
root.resizable(True, True)
global image
image = Frame.PhotoImage(file = r"C:\\Users\\admin\\Desktop\\Foto\\Haken.png")
app = Login_system(root)
root.mainloop()
if __name__ == "__main__":
main()
But I get this error:
Traceback (most recent call last):
File "C:\Users\admin\Desktop\Python\GUI APP\login_system_new.py", line 40, in <module>
main()
File "C:\Users\admin\Desktop\Python\GUI APP\login_system_new.py", line 34, in main
image = Frame.PhotoImage(file = r"C:\\Users\\admin\\Desktop\\Foto_Marco\\Haken.png")
AttributeError: type object 'Frame' has no attribute 'PhotoImage'
[Finished in 0.5s]
Have you got any suggestion? I would like to put the image on the far right column.
If the image is part of the Login_system, then it is better put it inside the class. Also you forget to specify the parent of widgets inside the class, so the widgets will be children of root instead.
Also avoid importing modules like below:
from tkinter import *
from tkinter.ttk import *
In this case, you cannot use some of the widgets from tkinter because they are override by those from ttk.
Below is a modified sample based on your code:
import tkinter as tk
from tkinter import ttk
class Login_system(ttk.Frame):
def __init__(self, parent):
ttk.Frame.__init__(self, parent)
self.initUI()
def initUI(self):
self.master.title("Login System Prova")
ttk.Label(self, text="Surname").grid(row=0, column=0, sticky=tk.W, pady=2)
ttk.Label(self, text="Your Password").grid(row=1, column=0, sticky=tk.W, pady=2)
ttk.Label(self, text="Your E-Mail").grid(row=2, column=0, sticky=tk.W, pady=2)
ttk.Entry(self).grid(row=0, column=1, pady=2)
ttk.Entry(self).grid(row=1, column=1, pady=2)
ttk.Entry(self).grid(row=2, column=1, pady=2)
ttk.Entry(self).grid(row=3, column=1, pady=2)
ttk.Checkbutton(self, text="Keep me on-line").grid(row=4, sticky=tk.W, columnspan=2)
self.image = tk.PhotoImage(file=r"C:\\Users\\admin\\Desktop\\Foto\\Haken.png").subsample(10,10)
ttk.Label(self, image=self.image).grid(row=0, column=2, rowspan=5, padx=(20,0))
def main():
root = tk.Tk()
#root.geometry("200x150+400+300")
#root.resizable(True, True)
app = Login_system(root)
app.pack(fill='both', expand=1, padx=10, pady=10)
root.mainloop()
if __name__ == "__main__":
main()
I have a small test application using Python tkinter that I got to work. The problem is that it does not exit properly when the "Quit" button is pressed. It is a two-frame tabbed application where I started with the StackOverflow question ttk tkinter multiple frames/windows.
It is now a full example that works, but needs work because it doesn't quit and exit properly. When I press the "Quit" button, it kills the frame for that tab, but the application doesn't quit and exit properly. I have to hit the Window "X" Close icon to close it.
My main question is how (and where?) do I test for the event on either the "Quit" button on the "Feet to Meters" calculator, or the "Cancel/Quit" button on the BMI calculator.
A second question I have is that the design of the application seems inefficient to me, because it creates two widgets "Frame" objects, each with their own set of buttons, including 2 "quit" buttons. How do I put these tabs and frames into a parent window and then add a quit button on that parent window to close the entire application.
I modified the buttons to properly destroy the Frame that the button is in:
Changed button2 "command=self.quit" to "command=self.destroy"
self.button2 = ttk.Button(self, text="Cancel/Quit", command=self.quit).grid(row=3, column=1, sticky=E)
to
self.button2 = ttk.Button(self, text="Cancel/Quit", command=self.destroy).grid(row=3, column=1, sticky=E)
""" Created on Thu Jul 11 17:20:22 2019 """
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class App1(ttk.Frame):
""" This application calculates BMI and returns a value. """
def __init__(self, master=None):
ttk.Frame.__init__(self, master)
self.grid()
self.createWidgets()
def createWidgets(self):
#text variables
self.i_height = StringVar()
self.i_weight = StringVar()
self.o_bmi = StringVar()
#labels
self.label1 = ttk.Label(self, text="Enter your weight:").grid(row=0, column=0, sticky=W)
self.label2 = ttk.Label(self, text="Enter your height:").grid(row=1, column=0, sticky=W)
self.label3 = ttk.Label(self, text="Your BMI is:").grid(row=2, column=0, sticky=W)
#text boxes
self.textbox1 = ttk.Entry(self, textvariable=self.i_weight).grid(row=0, column=1, sticky=E)
self.textbox2 = ttk.Entry(self, textvariable=self.i_height).grid(row=1, column=1, sticky=E)
self.textbox3 = ttk.Entry(self, textvariable=self.o_bmi).grid(row=2, column=1, sticky=E)
#buttons
self.button1 = ttk.Button(self, text="Ok", command=self.calculateBmi).grid(row=3, column=2, sticky=E)
## Changed button2 "command=self.quit" to "command=self.destroy"
# self.button2 = ttk.Button(self, text="Cancel/Quit", command=self.quit).grid(row=3, column=1, sticky=E)
self.button2 = ttk.Button(self, text="Cancel/Quit", command=self.destroy).grid(row=3, column=1, sticky=E)
#exitApplication = tk.Button(root, text='Exit Application', command=root.destroy)
#canvas1.create_window(85, 300, window=exitApplication)
def calculateBmi(self):
try:
self.weight = float(self.i_weight.get())
self.height = float(self.i_height.get())
self.bmi = self.weight / self.height ** 2.0
self.o_bmi.set(self.bmi)
except ValueError:
messagebox.showinfo("Error", "You can only use numbers.")
finally:
self.i_weight.set("")
self.i_height.set("")
class App2(ttk.Frame):
""" Application to convert feet to meters or vice versa. """
def __init__(self, master=None):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""Create the widgets for the GUI"""
# 1 textbox (stringvar)
self.entry= StringVar()
self.textBox1= ttk.Entry(self, textvariable=self.entry).grid(row=0, column=1)
# 5 labels (3 static, 1 stringvar)
self.displayLabel1 = ttk.Label(self, text="feet").grid(row=0, column=2, sticky=W)
self.displayLabel2 = ttk.Label(self, text="is equivalent to:").grid(row=1, column=0)
self.result= StringVar()
self.displayLabel3 = ttk.Label(self, textvariable=self.result).grid(row=1, column=1)
self.displayLabel4 = ttk.Label(self, text="meters").grid(row=1, column=2, sticky=W)
# 2 buttons
self.calculateButton = ttk.Button(self, text="Calculate", command=self.convert_feet_to_meters).grid(row=2, column=2, sticky=(S,E))
self.quitButton = ttk.Button(self, text="Quit", command=self.destroy).grid(row=2, column=1, sticky=(S,E))
#exitApplication = tk.Button(root, text='Exit Application', command=root.destroy)
#canvas1.create_window(85, 300, window=exitApplication)
def convert_feet_to_meters(self):
"""Converts feet to meters, uses string vars and converts them to floats"""
self.measurement = float(self.entry.get())
self.meters = self.measurement * 0.3048
self.result.set(self.meters)
### CODE BELOW COMMENTED OUT WHEN JOINING ORIGINAL POSTER CODE WITH HIS SOLUTION
### It seems no longer relevant since App1 and App2 have their own buttons.
#def button1_click():
# """ This is for the BMI Calculator Widget """
# root = Tk()
# app = App1(master=root)
# app.mainloop()
#
#def button2_click():
# """ This is for the Feet to Meters Conversion Widget """
# root = Tk()
# app = App2(master=root)
# app.mainloop()
#def main():
# window = Tk()
# button1 = ttk.Button(window, text="bmi calc", command=button1_click).grid(row=0, column=1)
# button2 = ttk.Button(window, text="feet conv", command=button2_click).grid(row=1, column=1)
# window.mainloop()
def main():
#Setup Tk()
window = Tk()
#Setup the notebook (tabs)
notebook = ttk.Notebook(window)
frame1 = ttk.Frame(notebook)
frame2 = ttk.Frame(notebook)
notebook.add(frame1, text="BMI Calc")
notebook.add(frame2, text="Feet to Meters")
notebook.grid()
#Create tab frames
app1 = App1(master=frame1)
app1.grid()
app2 = App2(master=frame2)
app2.grid()
#Main loop
window.mainloop()
if __name__ == '__main__':
main()
The application doesn't quit when the "Quit" button is pressed. Only the individual frames quit.
Thanks to Martineau for the hint that helped me get this example to work. I declared 'window as a global variable, since it was defined in the name space of the class constructors. Without that, there was an error raised of undefined window. This method breaks the encapsulation and modularity of the classes by passing in the window as a global. If there is a better way to do this, I would like to know.
# -*- coding: utf-8 -*-
""" Created on Thu Jul 11 17:20:22 2019
Filename: tkinter-multiple-frames-windows_v3.py
From question on StackOverflow question "ttk tkinter multiple frames/windows"
at https://stackoverflow.com/questions/6035101/ttk-tkinter-multiple-frames-windows?rq=1
Now a full example that works but it needed some modification to clarify how it works.
"""
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class BMICalcApp(ttk.Frame):
""" This application calculates BMI and returns a value. """
def __init__(self, master=None):
ttk.Frame.__init__(self, master)
self.grid()
self.createWidgets()
def createWidgets(self):
#text variables
self.i_height = StringVar()
self.i_weight = StringVar()
self.o_bmi = StringVar()
#labels
self.label1 = ttk.Label(self, text="Enter your weight:").grid(row=0, column=0, sticky=W)
self.label2 = ttk.Label(self, text="Enter your height:").grid(row=1, column=0, sticky=W)
self.label3 = ttk.Label(self, text="Your BMI is:").grid(row=2, column=0, sticky=W)
#text boxes
self.textbox1 = ttk.Entry(self, textvariable=self.i_weight).grid(row=0, column=1, sticky=E)
self.textbox2 = ttk.Entry(self, textvariable=self.i_height).grid(row=1, column=1, sticky=E)
self.textbox3 = ttk.Entry(self, textvariable=self.o_bmi).grid(row=2, column=1, sticky=E)
#buttons
self.button1 = ttk.Button(self, text="Ok", command=self.calculateBmi).grid(row=3, column=2, sticky=E)
self.button2 = ttk.Button(self, text="Cancel/Quit", command=window.destroy).grid(row=3, column=1, sticky=E)
def calculateBmi(self):
try:
self.weight = float(self.i_weight.get())
self.height = float(self.i_height.get())
self.bmi = self.weight / self.height ** 2.0
self.o_bmi.set(self.bmi)
except ValueError:
messagebox.showinfo("Error", "You can only use numbers.")
finally:
self.i_weight.set("")
self.i_height.set("")
class ConvertFeetMeters(ttk.Frame):
""" Application to convert feet to meters or vice versa. """
def __init__(self, master=None):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
"""Create the widgets for the GUI"""
# 1 textbox (stringvar)
self.entry= StringVar()
self.textBox1= ttk.Entry(self, textvariable=self.entry).grid(row=0, column=1)
# 5 labels (3 static, 1 stringvar)
self.displayLabel1 = ttk.Label(self, text="feet").grid(row=0, column=2, sticky=W)
self.displayLabel2 = ttk.Label(self, text="is equivalent to:").grid(row=1, column=0)
self.result= StringVar()
self.displayLabel3 = ttk.Label(self, textvariable=self.result).grid(row=1, column=1)
self.displayLabel4 = ttk.Label(self, text="meters").grid(row=1, column=2, sticky=W)
# 2 buttons
self.calculateButton = ttk.Button(self, text="Calculate", command=self.convert_feet_to_meters).grid(row=2, column=2, sticky=(S,E))
self.quitButton = ttk.Button(self, text="Quit", command=window.destroy).grid(row=2, column=1, sticky=(S,E))
def convert_feet_to_meters(self):
"""Converts feet to meters, uses string vars and converts them to floats"""
self.measurement = float(self.entry.get())
self.meters = self.measurement * 0.3048
self.result.set(self.meters)
def main():
#Setup Tk()
global window
window = Tk()
#Setup the notebook (tabs)
notebook = ttk.Notebook(window)
frame1 = ttk.Frame(notebook)
frame2 = ttk.Frame(notebook)
notebook.add(frame1, text="BMI Calc")
notebook.add(frame2, text="Feet to Meters")
notebook.grid()
#Create tab frames
bmi_calc = BMICalcApp(master=frame1)
bmi_calc.grid()
feet_meters_calc = ConvertFeetMeters(master=frame2)
feet_meters_calc.grid()
#Main loop
window.mainloop()
if __name__ == '__main__':
main()
I am struggling with this small application. I fallowed many forum and answer but I couldn't find the right answer.
I marked in the code the problems I am having:
The first problem is I could not find a way for output the results in a ttk entry widget.
The second problem is how to execute different code depending on the radiobutton checked.
The third problem is how can I make the program with better syntax?
Code:
from tkinter import ttk
from tkinter import *
from tkinter import messagebox
class main_window:
def __init__(self, master = None):
self.frame1 = ttk.Frame(master)
self.frame1.pack()
master.title('Calculation program')
master.resizable(False, False)
master.configure(background='blue')
self.radiob1 = ttk.Radiobutton(self.frame1, value="M", text="Molar (M)")
self.radiob1.grid(column=0, row=1, sticky="nw", padx=25)
self.radiob2 = ttk.Radiobutton(self.frame1, value="mM", text="milliMolar (mM)")
self.radiob2.grid(column=0, row=2, sticky="nw", padx=25)
self.mol_weight = ttk.Entry(self.frame1, width=24, font=('Arial', 10))
self.mol_weight.grid(row=0, column=3, padx=3, pady=5)
self.amount = ttk.Entry(self.frame1, width=24, font=('Arial', 10))
self.amount.grid(row=1, column=3, padx=3, pady=5)
self.results = ttk.Entry(self.frame1, width=15, font=('Cambria', 10))
self.results.grid(row=6, column=3, padx=5, pady=5)
ttk.Label(self.frame1, text='Molecular Weight:').grid(row=0, column=1, padx=0, pady=3, sticky='w')
ttk.Label(self.frame1, text='Amount:').grid(row=1, column=1, padx=0, pady=3, sticky='w')
ttk.Label(self.frame1, text='Results').grid(row=5, column=3, padx=0, pady=6, sticky='s')
ttk.Button(self.frame1, text='Calculate',
command=self.calculate).grid(row=4, column=0, padx=5, pady=5, sticky='e')
ttk.Button(self.frame1, text='Clear',
command=self.clear).grid(row=4, column=1, padx=5, pady=5, sticky='w')
def calculate(self):
if self.radiob1.SELECTED??:
return self.molare()
elif self.radiob2.SELECTED??:
return self.millimolar
else:
messagebox.showinfo(title="No good, you have to select one!")
messagebox.showinfo(title='Calculations', message='Calculations Completed!')
def molare(self):
a = self.mol_weight.get()
b = self.amount.get()
ans = a + b
self.results["Results"] = "Is: " + ans [???]
def millimolar(self):
a = self.mol_weight.get()
b = self.amount.get()
ans = a - b
self.results["Results"] = "Is: " + ans [???]
def clear(self):
self.mol_weight.delete(0, 'end')
self.amount.delete(0, 'end')
self.radiob1.DESELECT() ??
self.radiob2.DESELECT()??
def main():
root = Tk()
Main_window = main_window(root)
root.mainloop()
if __name__ == "__main__":
main()
1) To put text in an Entry widget, use the insert method:
entry.delete(0, "end") # clear entry
entry.insert(0, "my text") # insert new text
2) Associate a StringVar with your radiobuttons and use its get method to know which button is selected
import tkinter as tk
from tkinter import ttk
def callback():
if var.get() == "r1":
print("r1 is selected")
elif var.get() == "r2":
print("r2 is selected")
else:
print("None")
root = tk.Tk()
var = tk.StringVar(root, value="")
ttk.Radiobutton(root, variable=var, value="r1", text="r1").pack()
ttk.Radiobutton(root, variable=var, value="r2", text="r2").pack()
ttk.Button(root, text="print", command=callback).pack()
root.mainloop()
To clear the radiobutton selection, you can do var.set("").
3) It's a rather subjective question. First, class name are usually capitalized. Personally, I make my Main class inherit from tk.Tk:
class Main(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
# window configuration
self.title('Calculation program')
#...
# widgets
ttk.Label(self, text="example").grid()
#...
self.mainloop()
if __name__ == "__main__":
Main()
And, as it was said in the comments, a and b should be converted to float or int before making calculations and then do "Is %d" % ans or any of the other proposition of furas in the comments.
I recommend you this website: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html to get the list of all options and methods of each tkinter/ttk widget.
I made 2 windows: main & login.I want the button and login window in toplevel,but always jump into main,why?
If I write code in poplogin() and not import module ,it works correct.
main.py
#! python3
from tkinter import *
from login import login
def demo():
root = Tk()
root.title("demo")
root.geometry('640x400')
Button(root,text='login',width=10,command=poplogin).grid(row=3,column=1,padx=10,pady=5)
root.mainloop()
def poplogin():
toplevel = Toplevel()
toplevel.grid()
toplevel.title('login')
login(toplevel)
if __name__ == "__main__":demo()
login.py
#! python3
from tkinter import *
class login(Frame):
def __init__(self,parent=None):
Frame.__init__(self,parent)
self.creat_login()
def creat_login(self):
Label(text='email').grid(row=1)
user_email = Entry()
user_email.grid(row=1,column=1,padx=10,pady=5)
Label(text='password').grid(row=2)
user_password = Entry(show='*')
user_password.grid(row=2,column=1,padx=10,pady=5)
Button(text='login',width=10).grid(row=3,column=1,padx=10,pady=5)
if __name__ == '__main__':
login().mainloop()
You have to inform widget who is its parent - Widget(parent, ...). If you don't do this then tkinter use main window.
In your code you have to use self
And you have to use self.pack() to show Frame in Toplevel
#! python3
from tkinter import *
class login(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.creat_login()
# show in Toplevel
self.pack()
def creat_login(self):
# self
Label(self, text='email').grid(row=1)
# self
user_email = Entry(self)
user_email.grid(row=1, column=1, padx=10, pady=5)
# self
Label(self, text='password').grid(row=2)
# self
user_password = Entry(self, show='*')
user_password.grid(row=2, column=1, padx=10, pady=5)
# self
Button(self, text='login', width=10).grid(row=3, column=1, padx=10, pady=5)
if __name__ == '__main__':
login().mainloop()
right code
from tkinter import *
class login(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.creat_login(parent)
# With or without this line the same results,I don't know why
self.grid()
def creat_login(self,parent):
Label(parent, text='email').grid(row=1)
user_email = Entry(parent)
user_email.grid(row=1, column=1, padx=10, pady=5)
Label(parent, text='password').grid(row=2)
user_password = Entry(parent, show='*')
user_password.grid(row=2, column=1, padx=10, pady=5)
Button(parent, text='login', width=10).grid(row=3, column=1, padx=10, pady=5)
if __name__ == '__main__':
login().mainloop()