I set four RadioButtons for users to choose the type of distribution, then use a global variable s_val to record the type of distribution. However, no matter which button users choose, s_val always equals to 0. I wonder what causes this problem.
Here is my code:
`import tkinter as tk
import tkinter.messagebox as messagebox
from numpy import*
#设计交互页面
#s_val强度分布种类
#r_val应力分布种类
para1_1 = 0
para1_2 = 0
para2_1 = 0
para2_2 = 0
class basedesk:
def __init__(self, master):
self.root = master
self.root.config()
self.root.title('可靠性计算')
self.root.geometry('400x300')
initface1(self.root)
class initface1:
def get_val1(self):
global s_val
s_val = self.s_value.get()
def __init__(self, master):
self.master = master
#基准界面initface1
self.initface1 = tk.Frame(self.master, )
self.initface1.pack()
reminder = tk.Label(self.initface1, text='please choose the distribution type of strength', width=50, height=10)
reminder.pack()
#获取应力分布的按键设计
self.s_value = tk.IntVar()
self.radio()
tk.Button(self.initface1, text='确定', command=self.change).pack()
def radio(self):
radio_bt1=tk.Radiobutton(self.initface1, text='normal distribution', variable=self.s_value, value=1,
command=self.get_val1())
radio_bt2=tk.Radiobutton(self.initface1, text='lg normal distribution', variable=self.s_value, value=2,
command=self.get_val1())
radio_bt3=tk.Radiobutton(self.initface1, text='exponential distribution', variable=self.s_value, value=3,
command=self.get_val1())
radio_bt4=tk.Radiobutton(self.initface1, text='weibull distribution', variable=self.s_value, value=4,
command=self.get_val1())
radio_bt1.pack()
radio_bt2.pack()
radio_bt3.pack()
radio_bt4.pack()
def change(self, ):
self.initface1.destroy()
face1(self.master)
class face1:
def __init__(self, master):
self.master = master
self.face1 = tk.Frame(self.master, )
self.face1.pack()
global s_val
print(s_val)
if s_val==1|s_val==2:
tk.Label(self.face1, text='please fill two parameters of this distribution', width=50, height=10).pack()
tk.Label(self.face1, text='mean').pack()
self.parameter1 = tk.Entry(self.face1, relief='groove', width=20)
self.parameter1.pack()
tk.Label(self.face1, text='standard deviation').pack()
self.parameter2 = tk.Entry(self.face1, relief='groove', width=20)
self.parameter2.pack()
else:
tk.Label(self.face1, text='please fill the parameter of this distribution', width=50, height=10).pack()
self.parameter1 = tk.Entry(self.face1, relief='groove', width=20)
self.parameter1.pack()
tk.Label(self.face1, text='caution: only numbers are allowed').pack()
tk.Button(self.face1, text='yes', command=self.com).pack()
def com(self):
global para1_1
global para1_2
global s_val
if s_val == 1 | s_val == 2:
if self.parameter1.get().isdigit()&self.parameter2.get().isdigit():
para1_1 = float(self.parameter1.get())
para1_2 = float(self.parameter2.get())
self.change()
else:
messagebox.showwarning('warning', 'not numbers')
else:
if self.parameter1.get().isdigit():
para1_1 = self.parameter1.get()
para1_2 = 0
self.change()
else:
messagebox.showwarning('warning', 'not numbers')
def change(self,):
self.face1.destroy()
initface2(self.master)
class initface2:
def __init__(self, master):
self.master = master
#第二个确认分布界面
self.initface2 = tk.Frame(self.master, )
self.initface2.pack()
reminder = tk.Label(self.initface2, text='please choose the distribution type of r', width=50, height=10)
reminder.pack()
#获取应力分布的按键设计
self.r_value = tk.IntVar()
radio_bt1 = tk.Radiobutton(self.initface2, text='normal distribution', variable=self.r_value, value=1,
command=self.get_val2())
radio_bt2 = tk.Radiobutton(self.initface2, text='lg normal distribution', variable=self.r_value, value=2,
command=self.get_val2())
radio_bt3 = tk.Radiobutton(self.initface2, text='exponential distribution', variable=self.r_value, value=3,
command=self.get_val2())
radio_bt4 = tk.Radiobutton(self.initface2, text='weibull distribution', variable=self.r_value, value=4,
command=self.get_val2())
radio_bt1.pack()
radio_bt2.pack()
radio_bt3.pack()
radio_bt4.pack()
btn = tk.Button(self.initface2, text='yes', command=self.change)
btn.pack()
def change(self, ):
self.initface2.destroy()
face2(self.master)
def get_val2(self):
global r_val
r_val = int(self.r_value.get())
class face2:
def __init__(self, master):
self.master = master
self.face2 = tk.Frame(self.master, )
self.face2.pack()
global r_val
if r_val == 1 | r_val == 2:
tk.Label(self.face2, text='please fill two parameters of this distribution', width=50, height=10).pack()
tk.Label(self.face2, text='mean').pack()
self.parameter3 = tk.Entry(self.face2, relief='groove', width=20)
self.parameter3.pack()
tk.Label(self.face2, text='standard deviation').pack()
self.parameter4 = tk.Entry(self.face2, relief='groove', width=20)
self.parameter4.pack()
else:
tk.Label(self.face2, text='please fill the parameter of this distribution', width=50, height=10).pack()
self.parameter3 = tk.Entry(self.face2, relief='groove', width=20)
self.parameter3.pack()
tk.Label(self.face2, text='caution: only numbers are allowed').pack()
tk.Button(self.face2, text='yes', command=self.com).pack()
def com(self):
global para2_2
global para2_1
global r_val
if r_val == 1 | r_val == 2:
if self.parameter3.get().isdigit() & self.parameter4.get().isdigit():
para2_1 = float(self.parameter3.get())
para2_2 = float(self.parameter4.get())
else:
messagebox.showwarning('warning', 'not numbers')
else:
if self.parameter3.get().isdigit():
para2_1 = float(self.parameter3.get())
para2_2 = 0
else:
messagebox.showwarning('warning', 'not numbers')
self.cal_res(s_val, r_val, para1_1, para1_2, para2_1, para2_2)
def cal_res(self,type1, type2, p1, p2, p3, p4):
if type1==1:
x1 = random.normal(p1, p2, size=(1000, 1))
elif type1==2:
x1 = random.lognormal(p1, p2, size=(1000, 1)), 2
elif type1==3:
x1 = random.weibull(p1, size=(1000, 1)), 2
else:
x1 = random.exponential(float(p1), size=(1000, 1)), 2
if type2==1:
x2 = random.normal(p3, p4, size=(1000, 1)), 2
elif type1==2:
x2 = random.lognormal(p3, p4, size=(1000, 1)), 2
elif type1==3:
x2 = random.weibull(p3, size=(1000, 1)), 2
else:
x2 = random.exponential(p3, size=(1000, 1)), 2
times = 0
n1 = 0
while times<1000:
if x1[times] > x2[times]:
n1 = n1+1
times = times+1
result = n1/1000
messagebox.showinfo('result', 'the result is'+str(result))
if __name__ == '__main__':
root = tk.Tk()
basedesk(root)
root.mainloop()
I tried to change the type of s_val, from global variabale to class varibale. Yet it did't work.
It's somewhat hard to follow your original code, so here's a reformulation that does (or at least should do) the same thing with a (somewhat) nicer UI:
The main idea in the refactoring here is to move things into reusable functions, and store state in Tk variables up until the last moment.
This could be made nicer still by e.g. wrapping each distribution into a class, but this is a start...
import tkinter as tk
import tkinter.messagebox as messagebox
import numpy as np
distribution_types = {
"normal": "normal distribution",
"lgnormal": "lg normal distribution",
"expo": "exponential distribution",
"weibull": "Weibull distribution",
}
def make_dist_groupbox(master, variable, command=None):
groupbox = tk.LabelFrame(master, text="Distribution type")
for dist, text in distribution_types.items():
tk.Radiobutton(groupbox, text=text, variable=variable, value=dist, command=command).pack(anchor=tk.W)
return groupbox
def make_var_groupbox(root, dist_var, par1_var, par2_var):
var_groupbox = tk.LabelFrame(root, text="Strength")
def update_var_boxes():
dist = dist_var.get()
if dist in ("normal", "lgnormal"):
p1_label["text"] = "mean"
p2_label["text"] = "std"
p2_entry["state"] = "normal"
else:
p1_label["text"] = "scale"
p2_label["text"] = ""
p2_entry["state"] = "disabled"
make_dist_groupbox(var_groupbox, dist_var, command=update_var_boxes).pack()
p1_label = tk.Label(var_groupbox, text="parameter 1")
p1_entry = tk.Entry(var_groupbox, textvariable=par1_var)
p2_label = tk.Label(var_groupbox, text="parameter 2")
p2_entry = tk.Entry(var_groupbox, textvariable=par2_var)
p1_label.pack()
p1_entry.pack()
p2_label.pack()
p2_entry.pack()
update_var_boxes()
return var_groupbox
def generate_dist(type, p1, p2, n=1000):
size = (n,)
if type == "normal":
return np.random.normal(p1, p2, size=size)
if type == "lgnormal":
return (np.random.lognormal(p1, p2, size=size),)
elif type == "weibull":
return np.random.weibull(p1, size=size)
elif type == "expo":
return np.random.exponential(float(p1), size=size)
def generate(s_dist_var, s_par1_var, s_par2_var, r_dist_var, r_par1_var, r_par2_var):
n = 1000
try:
s_dist = s_dist_var.get()
s_par1 = s_par1_var.get()
s_par2 = s_par2_var.get()
r_dist = r_dist_var.get()
r_par1 = r_par1_var.get()
r_par2 = r_par2_var.get()
except Exception as e:
messagebox.showerror("error", f"Invalid input: {e}")
return
x1 = generate_dist(s_dist, s_par1, s_par2, n=n)
x2 = generate_dist(r_dist, r_par1, r_par2, n=n)
times = np.sum(x1 > x2)
messagebox.showinfo(
"result",
f"Parameters:\n{s_dist}({s_par1}, {s_par2}), {r_dist}({r_par1}, {r_par2})\n\n" f"Result: {times / n}",
)
def main():
root = tk.Tk()
s_dist_var = tk.StringVar(value="normal")
s_par1_var = tk.DoubleVar()
s_par2_var = tk.DoubleVar()
r_dist_var = tk.StringVar(value="normal")
r_par1_var = tk.DoubleVar()
r_par2_var = tk.DoubleVar()
make_var_groupbox(root, s_dist_var, s_par1_var, s_par2_var).pack(side=tk.LEFT, anchor=tk.N)
make_var_groupbox(root, r_dist_var, r_par1_var, r_par2_var).pack(side=tk.RIGHT, anchor=tk.N)
action_button = tk.Button(
root,
text="Generate",
command=lambda: generate(s_dist_var, s_par1_var, s_par2_var, r_dist_var, r_par1_var, r_par2_var),
)
action_button.pack(side=tk.BOTTOM, anchor=tk.S, fill=tk.X)
root.mainloop()
if __name__ == "__main__":
main()