Related
my name is Vo Minh Hoang. I wrote a Python program to upload file to draw graph but i have one problem which is the button to draw graph. Please help me and thank you very much. I send an image which is an example I want to complete the program.
from tkinter import *
from tkinter import filedialog
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
# functions
def openFile():
tf = filedialog.askopenfilename(
initialdir="C:/Users/MainFrame/Desktop/",
title="Open Text file",
filetypes=(("Text Files", "*.txt"),)
)
pathh.insert(END, tf)
tf = open(tf)
file_cont = tf.read()
txtarea.insert(END, file_cont)
tf.close()
def Draw():
tf = plt.figure(
mode='w',
title ="Draw",
ax = plt.subplots()
plt.subplots_adjust(left=0.3, bottom=0.25)
X, Y = np.loadtxt('data.txt', delimiter=',', unpack=True)
p, = ax.plot(X, Y, color="blue", marker="o")
print(X, Y)
)
tf.config(mode='w')
pathh.insert(END, tf)
data = str(txtarea.get(1.0, END))
tf.write(data)
tf.close()
ws = Tk()
ws.title("PythonGuides")
ws.geometry("400x500")
ws['bg']='#2a636e'
# adding frame
frame = Frame(ws)
frame.pack(pady=20)
# adding scrollbars
ver_sb = Scrollbar(frame, orient=VERTICAL )
ver_sb.pack(side=RIGHT, fill=BOTH)
hor_sb = Scrollbar(frame, orient=HORIZONTAL)
hor_sb.pack(side=BOTTOM, fill=BOTH)
# adding writing space
txtarea = Text(frame, width=40, height=20)
txtarea.pack(side=LEFT)
# binding scrollbar with text area
txtarea.config(yscrollcommand=ver_sb.set)
ver_sb.config(command=txtarea.yview)
txtarea.config(xscrollcommand=hor_sb.set)
hor_sb.config(command=txtarea.xview)
# adding path showing box
pathh = Entry(ws)
pathh.pack(expand=True, fill=X, padx=10)
# adding buttons
Button(
ws,
text="Open File",
command=openFile
).pack(side=LEFT, expand=True, fill=X, padx=20)
Button(
ws,
text="Draw",
command=Draw
).pack(side=LEFT, expand=True, fill=X, padx=20)
Button(
ws,
text="Exit",
command=lambda:ws.destroy()
).pack(side=LEFT, expand=True, fill=X, padx=20, pady=20)
ws.mainloop()
This is the code I try to complete
I tried to find in the Internet but it didn't work.
enter image description here
I am trying to build a code to make communications between my code and my Arduino Uno. I have a temperature sensor (tmp36) connected to the Arduino board, in the COM3, and I want to plot the temperature values in real time. I also have a start button, to start getting data and plot it in the graph, and a stop button to stop doing that.
When I run my code, I get a message saying: "could not convert string to float: b'Anal'", refering to line 19: " data = np.append(data,float(a[0:4]))". Can you tell me what is wrong? And would you be able to stop any more errors?
Thank You for your time!
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from tkinter import *
import numpy as np
import serial as sr
root = Tk()
root.title("Communications")
root.geometry('1920x1080')
root.resizable(False, False)
root.configure(background='black')
data = np.array([])
cond = False
def plot_data():
global cond, data
if (cond == True):
a = s.readline()
a.decode()
if(len(data) < 100):
data = np.append(data,float(a[0:4]))
else:
data[0:99] = data[1:100]
data[99] = float(a[0:4])
lines.set_xdata(np.arange(0, len(data)))
lines.set_ydata(data)
graph_1.draw()
root.after(1, plot_data)
def plot_start():
global cond
cond = True
s.reset_input_buffer()
def plot_stop():
global cond
cond = False
#graph
fig1 = Figure(facecolor="#090b80", figsize=(16,9), dpi=75)
ax1 = fig1.add_subplot(111)
ax1.set_title('Temperature', color='white', fontsize=14, fontweight="bold")
ax1.set_xlabel('Time, s', color='white', fontsize=10, fontweight="bold")
ax1.set_ylabel('ºC', color='white', fontsize=10, fontweight="bold")
ax1.set_xlim(0, 100)
ax1.set_ylim(0, 50)
ax1.spines['bottom'].set_color('#ffffff')
ax1.spines['top'].set_color('#090b80')
ax1.spines['right'].set_color('#090b80')
ax1.spines['left'].set_color('#ffffff')
ax1.tick_params(axis='x', colors='#ffffff')
ax1.tick_params(axis='y', colors='#ffffff')
lines = ax1.plot([], [], color='white')[0]
ax1.set_facecolor("#090b80")
graph_1 = FigureCanvasTkAgg(fig1, master=root)
graph_1.get_tk_widget().place(x=10, y=10, width=540, height=344)
graph_1.draw()
control_frame = Frame(root, bg="#242729", width=893, height=501)
control_frame.place(x=663, y=467)
root.update()
button_1 = Button(control_frame, text="Start", bg="#1cba26", fg="white", font=('arial', 20,'bold'), padx=101, activebackground="#109419", activeforeground="white", borderwidth=0, relief=RAISED, cursor="hand2", command=lambda:plot_start())
button_1.place(x=10, y=107.5)
root.update()
button_2 = Button(control_frame, text="Stop", bg="#eb0c0c", fg="white", font=('arial', 20,'bold'), padx=101.4, activebackground="#990909", activeforeground="white", borderwidth=0, relief=RAISED, cursor="hand2", command=lambda:plot_stop())
button_2.place(x=304, y=107.5)
#start serial port
s = sr.Serial('COM3', 9600)
s.reset_input_buffer()
root.after(1, plot_data)
root.mainloop()
I think so set a timeout: s = sr.Serial('COM3', 9600, timeout=1), but the main problem is this: a=a.decode(), you don't use a=. And if decode ypu the data, are this string type, but you use list. This problem can you solution:
import ast
i = b'0,1,2,3,4,5,6,7,8,999' # i is a bytes type val
dec=i.decode() #decode this
print(type(dec))
ldat=ast.literal_eval(dec) #convert str to list
print (ldat[3])
print (ldat[9])#here can use more characters data
And you can help the responders, if write an example line of readed data, arduino example and the full error message.
Good luck!
Sorry my english isn't perfect.
My code below creates an unwanted duplicate window when I try to add a window title using plt.figure().canvas.manager.set_window_title("Custom Title").
I've done some research and discovered that I am probably not supposed to be mixing pyplot and tkinter this way as they get confused. However I couldn't really make sense of the proposed solutions, some of which used something called FigureCanvasTkAgg which I don't know about. I want my plot to be freestanding, just as it is when I remove plt.figure().canvas.manager.set_window_title("Custom Title").
How can I refactor my code please to not violate any principles which my current code does and to remove the unwanted window?
import matplotlib.pyplot as plt
import tkinter as tk
import networkx as nx
NUM_ROWS = 5
BOLD_FONT = ("calbri", 12, "bold")
NORMAL_FONT = ("calbri", 12, "normal")
def create_widgets():
for i in range(NUM_ROWS):
key = chr(i + 65)
this_row = widgets[key] = {}
this_row["label"] = tk.Label(root, text=key, font=BOLD_FONT)
this_row["label"].grid(row=i, column=0, padx=5, pady=10)
this_row["factor_field"] = tk.Entry(root, width=60, font=NORMAL_FONT)
this_row["factor_field"].grid(row=i, column=1, padx=5, pady=10)
this_row["target_node_field"] = tk.Entry(
root, width=5, font=NORMAL_FONT)
this_row["target_node_field"].grid(row=i, column=2, padx=5, pady=10)
submit_button = tk.Button(root, text="Submit", command=submit,
font=BOLD_FONT).grid(row=NUM_ROWS + 1, column=0, padx=5, pady=10)
def submit():
plt.close()
G = nx.DiGraph()
edges = []
for key, row in widgets.items():
factor_field_contents = row["factor_field"].get()
target_node_field_contents = row["target_node_field"].get().upper()
if factor_field_contents != "" and target_node_field_contents != "":
edges.append((key, target_node_field_contents))
data[key] = {"factor": factor_field_contents,
"target_node": target_node_field_contents}
G.add_edges_from(edges)
# pos = nx.spring_layout(G, k=1.0, iterations=50)
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, node_size=500, node_color="green")
nx.draw_networkx_labels(G, pos, font_color="white")
nx.draw_networkx_edges(
G, pos, connectionstyle='arc3, rad = 0.1', width=2, arrows=True)
plt.figure().canvas.manager.set_window_title("Custom Title")
plt.show()
if __name__ == "__main__":
data = {}
widgets = {}
root = tk.Tk()
root.title("My App")
create_widgets()
root.mainloop()
You said you found a solution in FigureCanvasTkAgg, but you don't understand it. You have to gain that understanding because it is literally the only way (according to my research). My example should get you started in that understanding. To be honest, I don't know anything, at all, about matplotlib. I just read the docs and fulfilled the requirements. It seems to work perfectly at creating a single window.
#import matplotlib.pyplot as plt #remove this, you can't use it anymore
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import tkinter as tk
import networkx as nx
NUM_ROWS = 5
BOLD_FONT = ("calbri", 12, "bold")
NORMAL_FONT = ("calbri", 12, "normal")
def create_widgets():
for i in range(NUM_ROWS):
key = chr(i + 65)
this_row = widgets[key] = {}
this_row["label"] = tk.Label(root, text=key, font=BOLD_FONT)
this_row["label"].grid(row=i, column=0, padx=5, pady=10)
this_row["factor_field"] = tk.Entry(root, width=60, font=NORMAL_FONT)
this_row["factor_field"].grid(row=i, column=1, padx=5, pady=10)
this_row["target_node_field"] = tk.Entry(
root, width=5, font=NORMAL_FONT)
this_row["target_node_field"].grid(row=i, column=2, padx=5, pady=10)
submit_button = tk.Button(root, text="Submit", command=submit,
font=BOLD_FONT).grid(row=NUM_ROWS + 1, column=0, padx=5, pady=10)
#this is your single window
#I'm sure some of this could be made just once and reused
#I'm also sure this could be made more dynamic
#At least you have the multi-window part solved
def plotter():
global plotwin
plotwin = tk.Toplevel(root)
fig = Figure(figsize=(5,5), dpi=100)
fig.add_subplot(111)
canvas = FigureCanvasTkAgg(fig, plotwin)
canvas._tkcanvas.pack(fill='both', expand=True)
NavigationToolbar2Tk(canvas, plotwin, pack_toolbar=True).update()
def submit():
try:
#if plotter() hasn't been called yet this will throw a NameError
#we simply catch and ignore it
plotwin.destroy()
except NameError as e:
pass
G = nx.DiGraph()
edges = []
for key, row in widgets.items():
factor_field_contents = row["factor_field"].get()
target_node_field_contents = row["target_node_field"].get().upper()
if factor_field_contents != "" and target_node_field_contents != "":
edges.append((key, target_node_field_contents))
data[key] = {"factor": factor_field_contents,
"target_node": target_node_field_contents}
G.add_edges_from(edges)
# pos = nx.spring_layout(G, k=1.0, iterations=50)
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, node_size=500, node_color="green")
nx.draw_networkx_labels(G, pos, font_color="white")
nx.draw_networkx_edges(G, pos, connectionstyle='arc3, rad = 0.1', width=2, arrows=True)
#instantiate window
plotter()
if __name__ == "__main__":
data = {}
widgets = {}
root = tk.Tk()
root.title("My App")
create_widgets()
root.mainloop()
In my code I see that the Label is not being updated with the 'textvariable', despite I believe I'm doing it right (probably not!).
varmuTemperature = StringVar(value="default value")
self.Label = Label(Frame2, textvariable = varmuTemperature)
self.Label.pack()
This should show a label with "default value" written on it. The problem is that I don't see anything written.
I have my code posted here.
import matplotlib
import matplotlib.artist as artists
import matplotlib.pyplot as plt
#import matplotlib.mlab as mlab
import scipy.stats
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,
NavigationToolbar2Tk
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
import numpy as np
import statistics
from tkinter import *
from tkinter import ttk
import serial
import time
import itertools
integer=0
xList = []
humidityList = []
humidityListHistogram = []
temperatureList = []
temperatureListHistogram = []
cnt=0
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
ser = serial.Serial()
style.use("seaborn-whitegrid")
#varmuTemperature = StringVar()
#varmuHumidity = StringVar()
f=plt.figure(0, figsize=(20,10))
humidityGraph = plt.subplot(224)
humidityGraph.set_title("Humidity vs Time")
humidityGraph.set_ylabel("Humidity RAW (Dec)")
humidityGraph.set_xlabel("Sample ()")
temperatureGraph = plt.subplot(223)
temperatureGraph.set_title("Temperature vs Time")
temperatureGraph.set_ylabel("Temperature RAW (Dec)")
temperatureGraph.set_xlabel("Sample ()")
humidityGraphHistogram = plt.subplot(222)
temperatureGraphHistogram = plt.subplot(221)
temperatureGraphHistogramNormal = temperatureGraphHistogram.twinx()
humidityGraphHistogramNormal = humidityGraphHistogram.twinx()
side_text = plt.figtext(0.93, 0.5, 'Text 1'+'\n'+'Text 2', bbox=dict(facecolor='white'))
plt.subplots_adjust(left = 0.05, right = 0.95, bottom = 0.05, top = 0.95, wspace = 0.16, hspace = 0.21)
class make_window():
def __init__(self, *args, **kwargs):
win = Tk()
win.title("Test")
win.state("zoomed")
Frame1 = Frame(win)
Frame1.pack()
self.comboBoxAvailableCOMPort = ttk.Combobox(Frame1, width = 30)
self.comboBoxAvailableCOMPort['values'] = []
self.comboBoxAvailableCOMPort.pack(padx=5, pady=5, side = LEFT)
self.buttonCheckComAvailable = Button(Frame1, text="Check COM Available", command = self.CheckComAvailable)
self.buttonCheckComAvailable.pack(padx=5, pady=10, side = LEFT)
self.buttonOpenCOMPort = Button(Frame1, text="Open COM Port", command = self.OnOpenCom)
self.buttonOpenCOMPort.pack(padx=5, pady=10, side = LEFT)
self.buttonCloseCOMPort = Button(Frame1, text="Close COM Port" , command = self.OnCloseCOM)
self.buttonCloseCOMPort.pack(padx=5, pady=10,side = LEFT)
self.CheckComAvailable()
Frame2 = Frame(win, highlightbackground = "red", highlightcolor = "red", highlightthickness = 1)
Frame2.pack()
varmuTemperature = StringVar(value="default value")
varmuTemperature.set("trerta")
print(varmuTemperature.get())
self.Label = Label(Frame2, textvariable = varmuTemperature)
self.Label.pack()
self.buttonCloseProgram = Button(Frame2, text="Close Program", command = self.OnCloseProgram)
self.buttonCloseProgram.pack(expand=True, fill='x', anchor='s')
Frame3 = Frame(win)
Frame3.pack()
canvas = FigureCanvasTkAgg(f, Frame3)
canvas.get_tk_widget().pack(padx=5, pady=10, side=BOTTOM, expand = True)
toolbar = NavigationToolbar2Tk(canvas, Frame3)
toolbar.update()
canvas._tkcanvas.pack(padx=5, pady=10,side = TOP)
def CheckComAvailable(self):
self.comboBoxAvailableCOMPort['values'] =[]
result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
self.comboBoxAvailableCOMPort['values'] += tuple(result)
self.comboBoxAvailableCOMPort.set(result[0])
def OnOpenCom(self):
ser.baudrate = 115200
ser.port = self.comboBoxAvailableCOMPort.get()
try:
ser.open()
ser.readline()
ser.write("#dut,0$\n".encode('utf-8'))
ser.readline()
ser.write("#v,1800,1800$\n".encode('utf-8'))
ser.write("#W,77,08,07$\n".encode('utf-8'))
ser.readline()
except(OSError):
print("COM Port in use")
def OnCloseCOM(self):
global xList
global humidityList
global temperatureList
global humidityListHistogram
global temperatureListHistogram
global integer
integer=0
xList = []
humidityList = []
temperatureList = []
ser.close()
def OnCloseProgram(self):
self.OnCloseCOM()
exit()
## def toggle_geom(self,event):
## geom=self.master.winfo_geometry()
## print(geom,self._geom)
## self.master.geometry(self._geom)
## self._geom=geom
def animate(i):
global integer
global cnt
try:
ser.write(("#R,77,00,03$" + chr(10)).encode('utf-8'))
humidityLine=ser.readline()
inthumidityLine= int(humidityLine,16)
if (inthumidityLine > 8388608):
inthumidityLine = inthumidityLine - 16777216
humidityList.append(inthumidityLine)
humidityListHistogram.append(inthumidityLine)
ser.write(("#R,77,03,03$" + chr(10)).encode('utf-8'))
temperatureLine=ser.readline()
LineHistogram = temperatureLine
inttemperatureLine= int(temperatureLine,16)
if (inttemperatureLine > 8388608):
inttemperatureLine = inttemperatureLine - 16777216
temperatureList.append(inttemperatureLine)
temperatureListHistogram.append(inttemperatureLine)
xList.append(integer)
integer+=1
##################################################################################################################
## Creates the HUMIDITY Graphics
##################################################################################################################
humidityGraph.clear()
humidityGraph.plot(xList,humidityList,'-b*', label = "Humidity RAW")
humidityGraph.legend(loc='upper right', fancybox = True, frameon = True, shadow = True)
humidityGraph.set_title("Humidity vs Time")
humidityGraph.set_ylabel("Humidity RAW (Dec)")
humidityGraph.set_xlabel("Sample ()")
muHumidity = statistics.mean(humidityListHistogram)
#print("Mean = " + str(muHumidity) + " ; N = " + str(len(humidityListHistogram)))
#global varmuHumidity
#varmuHumidity.set("Humidity: ")
if (len(humidityListHistogram) > 1):
sigmaHumidity = statistics.pstdev(humidityListHistogram)
else:
sigmaHumidity = 100
humidityGraphHistogram.clear()
nHumidity, binsHumidity, patchesHumidity = humidityGraphHistogram.hist(humidityListHistogram, 100, density=False, facecolor='blue', alpha=0.75, histtype = 'stepfilled')
normalDistHumidity = scipy.stats.norm.pdf(binsHumidity, muHumidity, sigmaHumidity)
humidityGraphHistogramNormal.clear()
humidityGraphHistogramNormal.plot(binsHumidity, normalDistHumidity, 'r--')
humidityGraphHistogram.set_title("Histogram for Humidity Data")
humidityGraphHistogram.set_ylabel("Humidity RAW Counts (Dec)")
humidityGraphHistogram.set_xlabel("BINS ()")
humidityGraphHistogramNormal.set_ylabel("Normal Distribution")
##################################################################################################################
## Creates the TEMPERATURE Graphics
##################################################################################################################
temperatureGraph.clear()
temperatureGraph.plot(xList,temperatureList,'-r*', label = "Temperature RAW")
temperatureGraph.legend(loc='upper right', fancybox = True, frameon = True, shadow = True)
temperatureGraph.set_title("Temperature vs Time")
temperatureGraph.set_ylabel("Temperature RAW (Dec)")
temperatureGraph.set_xlabel("Sample ()")
muTemperature = statistics.mean(temperatureListHistogram)
#global varmuTemperature
#varmuTemperature.set("Temperature: " )
if (len(temperatureList) > 1):
sigmaTemperature = statistics.pstdev(temperatureListHistogram)
else:
sigmaTemperature = 100
temperatureGraphHistogram.clear()
nTemperature, binsTemperature, patchesTemperature = temperatureGraphHistogram.hist(temperatureListHistogram, 100, density=False, facecolor='red', alpha=0.75, histtype = 'stepfilled')
normalDistTemperature = scipy.stats.norm.pdf(binsTemperature, muTemperature, sigmaTemperature)
temperatureGraphHistogramNormal.clear()
temperatureGraphHistogramNormal.plot(binsTemperature, normalDistTemperature, 'b--')
temperatureGraphHistogram.set_title("Histogram for Temperature Data")
temperatureGraphHistogram.set_ylabel("Temperature RAW Counts (Dec)")
temperatureGraphHistogram.set_xlabel("BINS ()")
temperatureGraphHistogramNormal.set_ylabel("Normal Distribution")
if (cnt > 100):
xList.pop(0)
humidityList.pop(0)
temperatureList.pop(0)
cnt+=1
except(OSError):
bla=0
win = make_window()
ani = animation.FuncAnimation(f, animate, interval = 300)
make_window.mainloop()
Debugging a bit and start commenting lines of code, I see that the problem may come from the
f=plt.figure(0, figsize=(20,10))
Commenting this line (and all dependencies of this) makes the Label to be written.
Can someone help here, please? I don't get why the graphics can interfere in the Label.
Thanks a lot.
The general problem seems to be your management of instance variables and objects. You keep around as self.* variables, things you'll never need to reference again, like buttonCheckComAvailable, but fail to make self.* variables for things, like varmuTemperature, that you will need to reference later.
Object-wise, you do things that don't make sense:
make_window.mainloop()
as make_window is an object class, not an instance, and an instance of the class make_window won't respond to mainloop anyway as it contains a window but isn't one itself.
Here's my MCVE for your example code that makes varmuTemperature an instance variable and, just for demonstration purposes, sets it when the various buttons on the interface are clicked so you can see it's working:
from tkinter import *
from tkinter import ttk
class make_window():
def __init__(self):
self.win = Tk()
self.win.title("Test")
self.win.state("zoomed")
Frame1 = Frame(self.win)
self.comboBoxAvailableCOMPort = ttk.Combobox(Frame1, width=30)
self.comboBoxAvailableCOMPort['values'] = []
self.comboBoxAvailableCOMPort.pack(padx=5, pady=5, side=LEFT)
Button(Frame1, text="Check COM Available", command=self.CheckComAvailable).pack(padx=5, pady=10, side=LEFT)
Button(Frame1, text="Open COM Port", command=self.OnOpenCom).pack(padx=5, pady=10, side=LEFT)
Button(Frame1, text="Close COM Port", command=self.OnCloseCom).pack(padx=5, pady=10, side=LEFT)
Frame1.pack()
Frame2 = Frame(self.win, highlightbackground="red", highlightcolor="red", highlightthickness=1)
self.varmuTemperature = StringVar(value="default value")
Label(Frame2, textvariable=self.varmuTemperature).pack()
Button(Frame2, text="Close Program", command=self.OnCloseProgram).pack(expand=True, fill='x', anchor='s')
Frame2.pack()
def CheckComAvailable(self):
self.varmuTemperature.set("CheckCom")
def OnOpenCom(self):
self.varmuTemperature.set("OpenCom")
def OnCloseCom(self):
self.varmuTemperature.set("CloseCom")
def OnCloseProgram(self):
self.OnCloseCom()
exit()
window = make_window()
window.win.mainloop()
I am trying to use a ttk.notebook in python3 on a Linux (Ubuntu 14.04LTS) system to read Blockquote`# -- coding: utf-8 --data from experiments and perform several curve fits on this data in order to calculate the coefficients needed for a Finite Element calculation.
The actual calculation of these curves I have already performed without tkinter. I am now setting up the user interface.
All works well, until I want to fill in the variable a as global variable, noting is exported to the Ipython shell (using spyder2). The variables: CreepData and path2 which are made global in the same way are visble in the Ipython shell.
I am not sure if the way I am extracting values from the combo boxes or the Entry fields on the notebook page select units and run work in the intended way.
See the code below:
""" Created on Sat Jan 16 18:56:16 2016
#author: peterk
Derived frpm a lot of posted examples """ import csv from copy import
deepcopy import numpy as np import matplotlib import scipy import
matplotlib matplotlib.use("TkAgg") from
matplotlib.backends.backend_tkagg import
FigureCanvasTkAgg,NavigationToolbar2TkAgg from matplotlib.figure
import Figure from matplotlib import pyplot as plt from scipy import
stats from scipy.optimize import curve_fit from tkinter import *
import tkinter as tk import tkinter.font as tkFont import tkinter.ttk
as ttk from tkinter import filedialog path2="./creep.csv"
class CreepNotebook(ttk.Frame):
def __init__(self, isapp=True, name='notebookdemo'):
ttk.Frame.__init__(self, name=name)
self.pack(expand=True, fill="both")
self.master.title('Creep fit')
self.isapp = isapp
self._create_widgets()
self.master.minsize(1920,1000)
def _create_widgets(self):
self._create_main_panel()
def _create_main_panel(self):
mainPanel = ttk.Frame(self, name='demo')
mainPanel.pack( expand=True, side="top", fill="both")
# create the notebook
nb = ttk.Notebook(mainPanel, name='notebook')
# extend bindings to top level window allowing
# CTRL+TAB - cycles thru tabs
# SHIFT+CTRL+TAB - previous tab
# ALT+K - select tab using mnemonic (K = underlined letter)
nb.enable_traversal()
nb.pack(fill="both", padx=2, pady=3,expand=True)
self._create_readme_tab(nb)
self._create_import_data_tab(nb)
self._create_select_units_run_tab(nb)
self._create_text_tab(nb)
def _create_readme_tab(self, nb):
# frame explaining the app
frame = ttk.Frame(nb, name='readMeFirst')
# widgets to be displayed on 'Description' tab
msg = ["Ttk is the new Tk themed widget set. One of the widgets ",
"it includes is the notebook widget, which provides a set ",
"of tabs that allow the selection of a group of panels, ",
"each with distinct content. They are a feature of many ",
"modern user interfaces. Not only can the tabs be selected ",
"with the mouse, but they can also be switched between ",
"using Ctrl+Tab when the notebook page heading itself is ",
"selected. Note that the second tab is disabled, and cannot "
"be selected."
" aaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"ccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"dddddd",
"eeeee",
"f",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
" here is text too"]
lbl = ttk.Label(frame, wraplength='4i', justify=tk.LEFT, anchor=tk.CENTER,
text=''.join(msg))
neatVar = tk.StringVar()
btn = ttk.Button(frame, text='Neat!', underline=0,
command=lambda v=neatVar: self._say_neat(v))
neat = ttk.Label(frame, textvariable=neatVar, name='neat')
# position and set resize behaviour
lbl.grid(row=0, column=0, columnspan=2, sticky='new', pady=5)
btn.grid(row=1, column=0, pady=(2,4))
neat.grid(row=1, column=1, pady=(2,4))
frame.rowconfigure(1, weight=1)
frame.columnconfigure((0,1), weight=1, uniform=1)
# bind for button short-cut key
# (must be bound to topplevel window)
self.winfo_toplevel().bind('<Alt-n>', lambda e, v=neatVar: self._say_neat(v))
# add to notebook (underline = index for short-cut character)
nb.add(frame, text='ReadMeFirst', underline=0, padding=2)
def _say_neat(self, v):
v.set('Yeah, I know...')
self.update()
self.after(500, v.set(''))
# return path2
# =============================================================================
def _create_import_data_tab(self, nb):
# Populate the second pane.
frame = ttk.Frame(nb, name="import data")
global l
global k
global sigma
global creepData
global filen
global path2
butn=ttk.Button(frame, text='select csv file', command=self.askopenfilename2)
butn.pack(side="top")
self.file_opt = options = {}
options['defaultextension'] = '.csv'
options['filetypes'] =[('csv files', '.csv'),('all files', '.*')]
options['initialdir'] = '.'
options['initialfile'] = 'creep2.csv'
options['parent'] = nb
options['title'] = 'Select csv file'
global creepData
print("path2 in _create_import_data_tab")
print (path2)
nb.add(frame, text='Import data', underline=0)
def askopenfilename2(self):
global path2
global creepData
path2 = filedialog.askopenfilename(**self.file_opt)
print("path2 in askopenfilename2")
print(path2)
creepReader=csv.reader(open(path2, newline=""), delimiter=',')
creepData=list(creepReader)
#enter code here
========================================
def _create_text_tab(self, nb):
# populate the third frame with a text widget
frame = ttk.Frame(nb)
txt = tk.Text(frame, width=40, height=10)
vscroll = ttk.Scrollbar(frame, orient=tk.VERTICAL, command=txt.yview)
txt['yscroll'] = vscroll.set
vscroll.pack(side=tk.RIGHT)
# txt.pack(tk.fill=BOTH, tk.expand=True)
txt.pack() # btn2l.pack(side="top", pady=5)
# btn2.pack(side="top", pady=2)
# w.pack(side="top", pady=2)
# neatVar = tk.StringVar()
# btn = ttk.Button(frame, text='Neat!', underline=0,
# command=lambda v=neatVar: self._say_neat(v))
# neat = ttk.Label(frame, textvariable=neatVar, name='neat')
# def _say_neat(self, v):
# v.set('Yeah, I know...')
# self.update()
# self.after(500, v.set(''))
# add to notebook (underline = index for short-cut character)
nb.add(frame, text='Text Editor', underline=0)
#============================================================
def _create_select_units_run_tab(self, nb):
# select units and perform the calculation
frame = ttk.Frame(nb, name="select units and calculate")
global l
global k
global sigma
global creepData
global a
a=tk.StringVar()
frame.grid(column=0, row=0, rowspan=12, columnspan=5,sticky=(N,S,E,W))
units = ('m,kg,s', 'mm,Mg,s', 'mm,kg,ms')
a=tk.StringVar()
cbl0 = ttk.Label(frame, text='Select or fill in the required fields and push the run button')
cbl1 = ttk.Label(frame, text='Select units used in your FE-prgram')
cb1 = ttk.Combobox(frame, value=units, state='readonly')
# cbl1.pack(side="top")
# cb1.pack(side="top")
time_units=('hrs', 's','ms')
cbl2=ttk.Label(frame, text='Select time units used in the csv file')
cb2 = ttk.Combobox(frame, value=time_units, state='readonly')
# cbl2.pack(side="top")
# cb2.pack(side="top")
strain_units=('strain [%]', 'strain [-]','CreepModulus [MPa]')
cbl3=ttk.Label(frame, text='Select strain or modulus units used in the csv file')
cb3 = ttk.Combobox(frame, value=strain_units, state='readonly')
# cbl3.pack(side="top")
# cb3.pack(side="top")
yml=ttk.Label(frame, text=' Input Anisotropic Youngs Modulus in MPa')
ym=Entry(frame)
# yml.pack(side="top")
# ym.pack(side="top")
isfl=ttk.Label(frame, text='Input Isotropic factor')
isf=Entry(frame)
# isfl.pack(side="top")
# isf.pack(side="top")
run1Var = tk.StringVar()
btn2 = ttk.Button(frame, text='Run', underline=0,
command=lambda w=run1Var: self._run1(w))
btn2l = ttk.Label(frame, textvariable=run1Var, name='run1')
cbl0.grid(column=0, row=0, sticky=W, pady=100)
cbl1.grid(column=6, row=1, sticky=W, pady=25)
cb1.grid(column=6, row=2, sticky=W, pady=2)
cbl2.grid(column=6, row=3, sticky=W, pady=25)
cb2.grid(column=6, row=4, sticky=W, pady=2)
cbl3.grid(column=6, row=5, sticky=W, pady=25)
cb3.grid(column=6, row=6, sticky=W, pady=2)
yml.grid(column=6, row=7, sticky=W, pady=25)
ym.grid(column=6, row=8, sticky=W ,pady=2)
isfl.grid(column=6, row=9, sticky=W, pady=25)
isf.grid(column=6, row=10, sticky=W, pady=2)
btn2l.grid(column=6, row=11, sticky=W, pady=25)
btn2.grid(column=6, row=12, sticky=W, pady=2)
nb.add(frame, text='Select data and run', underline=0, padding=2)
a=cb1.get()
print(a)
print(cb1.get())
yms=ym.get()
isfs=isf.get()
def _run1(self, w):
# global CreepData
# global creepDat
# creepDat=deepcopy(creepData)
w.set('CreepData is copied')
self.update()
self.after(500, w.set(''))
#===================================================================
if __name__ == '__main__':
CreepNotebook().mainloop()`
If needed I can upload the csv.files on my repro, but I do not think it is needed for answering the question. The run1 function would be used to fit the data curves and return a message that the calculations were performed.
CHANGED - sorry I did not initially understand your question, prehaps this is more helpful:
first I'd recommend taking a look at both of these:
when to use global statement
Share variables between methods
second, you are creating the input entries in _create_select_units_run_tab and then you do:
def _create_select_units_run_tab:
...
a = cb1.get()
...
this will get the contents immediately after being created and even before .mainloop() is called so it will absolutely always be an empty string, in order to get the content later in _run1 you need to keep track of the entries instead:
def _create_select_units_run_tab:
...
self.input_fields = [cb1,cb2,cb3,ym,isf]
#this will give all other methods access to the input fields
#then to get them back you can use this:
def get_inputs(self):
return [entry.get() for entry in self.input_fields]
#then in run you can get the data in the fields
def _run1(self, w):
inp_data = self.get_inputs()
print(inp_data)
if "" in inp_data:
w.set("you need to fill everthing in first!")
else:
w.set(str(inp_data))
...
While testing the code I cancelled the file dialog window which threw an error because path2 == "" so you may want a check:
def askopenfilename2(self):
...
if path2 is not "":
creepReader=csv.reader(open(path2, newline=""), delimiter=',')
creepData = list(creepReader)
#else:
# creepData = None # or just leave it as the last used value?
...
not to mention the open() is never closed (Input and Output Python documentation):
It is good practice to use the with keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way. It is also much shorter than writing equivalent `try-finally` blocks:
with open('workfile', 'r') as f:
... read_data = f.read()
>>> f.closed
True
So you may want to implement that too:
with open(path2, newline="") as file_obj:
creepReader=csv.reader(file_obj, delimiter=',')
Lastly I'd like to draw attention to:
self.after(500,w.set('')
w.set('') is being called immediately and using the return value None in self.after, to instead call w.set with the argument you need to do this:
self.after(500,w.set,'')
then tkinter will call it after 500ms forwarding any extra arguments it receives in after
There may be other issues with your code that I missed but I hope this helped.