Related
I am making a small app with Tkinter, for educational purposes, which consists of pressing a button and displaying the contents of a textobox ... in another multiline textbox.
The problem is that you see this:
<bound method Text.get of <tkinter.Text object.! Text2 >>
and not the content that I manually write of the textobox. The textbox that I would like to print in the multiline textobox (called text) is called textbox_test. Textbox_test is called
A = f "{test_textbox.get} {'' .join (word2)} {abitanti} abitanti su un'area di {superficie}".
Questo è il textobox
test_textbox = Text(window,width=10,height=1)
test_textbox.pack()
test_textbox.place(x=5, y=100)
How can I remove the error above and correctly display the text of a textbox? I attach complete code. Thank you
from tkinter import *
from tkinter import ttk
import tkinter as tk
import sqlite3
import random
window=Tk()
window.title("xxxxxxxx")
window.geometry("750x750")
window.configure(bg='#78c030')
con = sqlite3.connect('/home/xxxxxxxxxxx/Database.db')
cursor = con.cursor()
# Search Data
def city(name_city):
name_city = city.get()
cursor.execute('SELECT * FROM Info WHERE City =?',(name_city,))
results = cursor.fetchone()
return results
# Print Data in textbox multiline
def write():
name_city = city.get
results = city(name_city)
inhabitants = results[2]
surface = results[3]
if categoria.get() == "Test 1" and sottocategoria.get() == "Test 1.1":
cursor.execute('SELECT xxxxxxxx FROM TableExample ORDER BY RANDOM() LIMIT 1')
word2 = cursor.fetchone()
text.delete(1.0,END)
A= f"{test_textbox.get} {''.join(word2)} {inhabitants} inhabitants on an area of {surface}"
B= f"Che sale a"
text.insert(tk.END, random.choice([A, B]))
button2 = Button(window, text="Button2", bg='white', command = write)
button2.pack()
button2.place(x=5, y=330)
### TEXTBOX MULTILINE ###
text = Text(window,width=63,height=38)
text.pack()
text.place(x=180, y=24)
### TEXTBOX ###
test_textbox = Text(window,width=10,height=1)
test_textbox.pack()
test_textbox.place(x=5, y=100)
### CATEGORIA E SOTTO CATEGORIA ###
cat=StringVar()
sub_cat=StringVar()
def change_val(*args):
if cat.get() == "Test 1":
sottocategorias = ["Test 1.1", "Test 1.2", "Test 1.3"]
sottocategoria.config(values=sottocategorias)
else:
sottocategorias = ["aaaa"]
sottocategoria.config(values=sottocategorias)
categorias=["Test 1", "Test 2", "Test 3"]
categoria=ttk.Combobox(window,value=categorias,textvariable=cat,width=16)
categoria.place(x=5, y=25)
cat.set("Scegliere categoria")
sottocategorias=["aaaa"]
sottocategoria=ttk.Combobox(window,textvariable=sub_cat,value=sottocategorias,
width=16)
sottocategoria.place(x=5, y=55)
cat.trace("w",change_val)
### COMBOBOX ###
def combo_nation():
cursor.execute('SELECT DISTINCT Nation FROM Info')
result=[row[0] for row in cursor]
return result
def combo_city(event=None):
val = city.get()
cursor.execute('SELECT City FROM Info WHERE Nation = ?', (val,))
result = [row[0] for row in cursor]
city['value'] = result
city.current(0)
return result
nation=ttk.Combobox(window,state="readonly")
nation['value'] = combo_nation()
nation.bind('<<ComboboxSelected>>', combo_city)
nation.place(x=5, y=150,height = 25, width = 180)
city=ttk.Combobox(window,state="readonly")
city.place(x=5, y=180, height = 25, width = 180)
window.mainloop()
IMPORTANT: If you try to change to A = f "{test_textbox.get (" 1.0 "," end-1c ")} {'' .join (word2)}, that's not good. The app won't open. Without this code instead opens
As #BryanOakley said in comment you need get with () to run it and widget Text needs it with arguments like
A = f"{test_textbox.get('1.0','end-1c')} ...
It didn't work because it was only part which you would have to replace in full text, but it seems you replaced all text. Because you didn't run code in console so you couldn't see error message which could explain problem
Full line should be
A = f"{test_textbox.get('1.0','end-1c')} {''.join(word2)} {inhabitants} inhabitants on an area of {surface}"
I have written this code and for some reason it refuses to return any sort of value or input for slef.REV when used in the function post(self) however it will return a value when I try and return a value in the getlen() function which is used to reurn the number of characters in the review.I dont have this problem for any other variables that I retrieve data from within this class. Below is the relevant code, any help would be appreciated. the lines where this problem occures is the first functio calld post(lines 1-5) and 4 lines up from the bottom
def post(self):
MovieID = self.MovID
REV = self.REV
AddReview(conn,cursor,Add_Review,MovieID,REV)
print(REV)
def shrek_film(self):
self.title = "Shrek"
self.MovID = 1
self.root4 = tk.Toplevel()
self.root4.title("Watch Shreck")
self.root4.geometry("1400x800")
frame_4 = tk.Frame(self.root4, bg = "black")
frame_4.pack(fill = tk.BOTH, expand = True, padx=0 , pady=0)
frame_4.grid_columnconfigure(1,weight=1)
self.Create_canvas = tk.Canvas(frame_4, width=2000, height=1080)
self.Create_canvas.place(x=-50, y=-50)
self.Create_img = PhotoImage(file="shrek-landscape.gif")
self.Create_canvas.create_image(20, 20, anchor = NW, image=self.Create_img)
play_button= tk.Button(frame_4,bg="orange",text="play", command = self.addHistory)
play_button.place(x=700,y=400)
play_button.config(font=("Ariel","30"))
def gtelen():
Review = reviewbox.get('1.0',END)
REVLEN = len(Review)
REVLENLEFT = (231-len(Review))
if REVLEN >=230:
lenbox = tk.Label(frame_4 ,text="No words left",bg="orange")
lenbox.place(x=360,y=460)
lenbox.config(font=("Ariel","15"))
else:
lenbox = tk.Label(frame_4 ,text=REVLENLEFT,bg="orange")
lenbox.place(x=360,y=460)
lenbox.config(font=("Ariel","15"))
print(Review)
Words_button = tk.Button(frame_4, bg="orange",text="check number of words remaining", command=gtelen)
Words_button.place(x=150,y=460)
Words_button.config(font=("Ariel","10"))
reviewlable=tk.Label(frame_4,text="Write a review",bg="orange")
reviewlable.place(x=10,y=460)
reviewlable.config(font=("ariel","15"))
Review_button= tk.Button(frame_4,bg="orange",text="See Reviews")#, command = self.ViewReviews)
Review_button.place(x=490,y=450)
Review_button.config(font=("Ariel","15"))
reviewbox= Text(frame_4,width=100,height=12)
reviewbox.place(x=10,y=500)
self.REV = reviewbox.get('1.0',END)
post_button = tk.Button(frame_4,bg="orange",text="Post Review", command = self.post)
post_button.place(x=830,y=650)
post_button.config(font=("Ariel","15"))
You can use Entry instead and use a StringVar
v = StringVar() # Create StringVar
reviewbox = Entry(frame_4, width = 100, height = 12, textvariable = v) # Create Entry widget
reviewbox.place(x = 10, y = 500) # Place Entry widget
self.REV = v.get() # Get contents of StringVar
The line self.REV = reviewbox.get('1.0',END) is being called about a millisecond after creating the text widget. The user will not even have seen the widget yet, much less have had time to type in it.
You can't call the get() method until after the user has had a chance to enter data, such as inside the post method.
def post(self):
MovieID = self.MovID
REV = reviewbox.get("1.0", "end")
AddReview(conn,cursor,Add_Review,MovieID,REV)
print(REV)
I am writing a simple app to calculate some values according to entered value by user. I almost accomplished it!
Now I want to know:
1. How can I clear my txtFixedIncome text box every time I click on it?
2. How can it be implemented to display the content of txtFixedIncome text box with thousands separator (digit group separator)? i.e. displaying 27659 as 27,659.
import tkinter
mainForm = tkinter.Tk()
mainForm.title('Shahr Fixed Income Fund')
def btnCalculatePressed():
txtCalculationResult.delete('1.0', 'end')
#txtCalculationResult.insert(tkinter.INSERT, "Button was pressed")
#txtCalculationResult.pack()
yourIncomePortion = txtFixedIncome.get('1.0', 'end')
print(yourIncomePortion)
txtCalculationResult.insert(tkinter.INSERT, yourIncomePortion)
btnCalculate = tkinter.Button(mainForm , text = "Calculate", command= btnCalculatePressed)
txtCalculationResult = tkinter.Text(mainForm )
txtCalculationResult.insert(tkinter.INSERT, "CalculationResults")
txtFixedIncome = tkinter.Text(mainForm, height = 1, width = 30 )
txtFixedIncome.insert(tkinter.INSERT, "your income portion")
txtFixedIncome.pack();
txtCalculationResult.pack()
btnCalculate.pack()
mainForm.mainloop()
Solution of first question:
bind focus in and focus out of your widget. Like:
txtFixedIncome.bind("<FocusIn>",lambda _:txtFixedIncome.delete('1.0', 'end'))
txtFixedIncome.bind("<FocusOut>",lambda _:txtFixedIncome.insert("1.0","your income portion" if str(txtFixedIncome.get("1.0","end")) == "\n" else ""))
This will erase all data in entry when focused out and enter information data when focused in.
Solution of second question:
You can make a function to update your values and format them like:
def updat(text):
try:txtCalculationResult.insert(tkinter.INSERT,"{:,.0f}".format(float(text)))
except:txtCalculationResult.insert(tkinter.INSERT,"CalculationResults")
As:
>>> "{:,.0f}".format(23442)
'23,442'
>>>
Full code:
Here is a full example code that shows the behavior you are expecting:
import tkinter
mainForm = tkinter.Tk()
mainForm.title('Shahr Fixed Income Fund')
def updat(text):
try:txtCalculationResult.insert(tkinter.INSERT,"{:,.0f}".format(float(text)))
except:txtCalculationResult.insert(tkinter.INSERT,"CalculationResults")
def btnCalculatePressed():
txtCalculationResult.delete('1.0', 'end')
yourIncomePortion = txtFixedIncome.get('1.0', 'end')
updat(yourIncomePortion)
btnCalculate = tkinter.Button(mainForm , text = "Calculate", command= btnCalculatePressed)
txtCalculationResult = tkinter.Text(mainForm)
txtCalculationResult.insert(tkinter.INSERT, "CalculationResults")
txtFixedIncome = tkinter.Text(mainForm, height = 1, width = 30 )
txtFixedIncome.insert(tkinter.INSERT, "your income portion")
txtFixedIncome.bind("<FocusIn>",lambda _:txtFixedIncome.delete('1.0', 'end'))
txtFixedIncome.bind("<FocusOut>",lambda _:txtFixedIncome.insert("1.0","your income portion" if str(txtFixedIncome.get("1.0","end")) == "\n" else ""))
txtFixedIncome.pack();
txtCalculationResult.pack()
btnCalculate.pack()
mainForm.mainloop()
Format during typing:
If you want to format the string during typing as you commented then use the following code:
import tkinter
mainForm = tkinter.Tk()
mainForm.title('Shahr Fixed Income Fund')
def updat(text):
try:txtCalculationResult.insert(tkinter.INSERT,"{:,.0f}".format(float(text.replace(",",""))))
except:txtCalculationResult.insert(tkinter.INSERT,"CalculationResults")
def btnCalculatePressed():
txtCalculationResult.delete('1.0', 'end')
yourIncomePortion = txtFixedIncome.get('1.0', 'end')
updat(yourIncomePortion)
btnCalculate = tkinter.Button(mainForm , text = "Calculate", command= btnCalculatePressed)
txtCalculationResult = tkinter.Text(mainForm)
txtCalculationResult.insert(tkinter.INSERT, "CalculationResults")
txtFixedIncome = tkinter.Text(mainForm, height = 1, width = 30 )
txtFixedIncome.insert(tkinter.INSERT, "your income portion")
def updat2():
text = txtFixedIncome.get("1.0","end")
txtFixedIncome.delete("1.0","end")
try:
txtFixedIncome.insert(tkinter.INSERT,"{:,.0f}".format(float(text.replace(",",""))))
except:
txtFixedIncome.insert(tkinter.INSERT,text[:-1])
txtFixedIncome.bind("<FocusIn>",lambda _:txtFixedIncome.delete('1.0', 'end'))
txtFixedIncome.bind("<FocusOut>",lambda _:txtFixedIncome.insert("1.0","your income portion" if str(txtFixedIncome.get("1.0","end")) == "\n" else ""))
txtFixedIncome.bind("<Key>",lambda _:mainForm.after(50,updat2))
txtFixedIncome.pack();
txtCalculationResult.pack()
btnCalculate.pack()
mainForm.mainloop()
#imports
from tkinter import *
from tkinter import messagebox as ms
import sqlite3
# make database and users (if not exists already) table at programme start up
with sqlite3.connect('quit.db') as db:
c = db.cursor()
c.execute('CREATE TABLE IF NOT EXISTS user (username TEXT NOT NULL ,password TEX NOT NULL);')
db.commit()
db.close()
#main Class
class main:
def __init__(self,master):
# Window
self.master = master
# Some Usefull variables
self.username = StringVar()
self.password = StringVar()
self.n_username = StringVar()
self.n_password = StringVar()
#Create Widgets
self.widgets()
def NewPage():
global NewRoot
root.withdraw() # hide (close) the root/Tk window
NewRoot = tk.Toplevel(root)
# use the NewRoot as the root now
#Login Function
def login(self):
with sqlite3.connect('quit.db') as db:
c = db.cursor()
#Find user If there is any take proper action
find_user = ('SELECT * FROM user WHERE username = ? and password = ?')
c.execute(find_user,[(self.username.get()),(self.password.get())])
result = c.fetchall()
if result:
self.logf.pack_forget()
self.head['text'] = self.username.get() + '\n Logged In'
self.head['pady'] = 150
root.after(2000, NewPage)
else:
ms.showerror('Oops!','Username Not Found.')
def new_user(self):
#Establish Connection
with sqlite3.connect('quit.db') as db:
c = db.cursor()
#Find Existing username if any take proper action
find_user = ('SELECT * FROM user WHERE username = ?')
c.execute(find_user,[(self.username.get())])
if c.fetchall():
ms.showerror('Error!','Username Taken Try a Diffrent One.')
else:
ms.showinfo('Success!','Account Created!')
self.log()
#Create New Account
insert = 'INSERT INTO user(username,password) VALUES(?,?)'
c.execute(insert,[(self.n_username.get()),(self.n_password.get())])
db.commit()
#Frame Packing Methords
def log(self):
self.username.set('')
self.password.set('')
self.crf.pack_forget()
self.head['text'] = 'LOGIN'
self.logf.pack()
def cr(self):
self.n_username.set('')
self.n_password.set('')
self.logf.pack_forget()
self.head['text'] = 'Create Account'
self.crf.pack()
#Draw Widgets
def widgets(self):
self.head = Label(self.master,text = 'LOGIN',font = ('',35),pady = 10)
self.head.pack()
self.logf = Frame(self.master,padx =10,pady = 10)
Label(self.logf,text = 'Username: ',font = ('',20),pady=5,padx=5).grid(sticky = W)
Entry(self.logf,textvariable = self.username,bd = 5,font = ('',15)).grid(row=0,column=1)
Label(self.logf,text = 'Password: ',font = ('',20),pady=5,padx=5).grid(sticky = W)
Entry(self.logf,textvariable = self.password,bd = 5,font = ('',15),show = '*').grid(row=1,column=1)
Button(self.logf,text = ' Login ',bd = 3 ,font = ('',15),padx=5,pady=5,command=self.login).grid()
Button(self.logf,text = ' Create Account ',bd = 3 ,font = ('',15),padx=5,pady=5,command=self.cr).grid(row=2,column=1)
self.logf.pack()
self.crf = Frame(self.master,padx =10,pady = 10)
Label(self.crf,text = 'Username: ',font = ('',20),pady=5,padx=5).grid(sticky = W)
Entry(self.crf,textvariable = self.n_username,bd = 5,font = ('',15)).grid(row=0,column=1)
Label(self.crf,text = 'Password: ',font = ('',20),pady=5,padx=5).grid(sticky = W)
Entry(self.crf,textvariable = self.n_password,bd = 5,font = ('',15),show = '*').grid(row=1,column=1)
Button(self.crf,text = 'Create Account',bd = 3 ,font = ('',15),padx=5,pady=5,command=self.new_user).grid()
Button(self.crf,text = 'Go to Login',bd = 3 ,font = ('',15),padx=5,pady=5,command=self.log).grid(row=2,column=1)
if __name__ == '__main__':
#Create Object
#and setup window
root = Tk()
root.title('Login Form')
#root.geometry('400x350+300+300')
main(root)
root.mainloop()
On line 37 it says NewPage is not defined but I defined it on line 24, please help. this program is object oriented and im a student trying to complete this for my A-Level project. I dont understand alot of this code but any help would be much appreciated. Im a amateur when it comes to python/tkinter/sqlite but need this help otherwise I will fail my course because my teacher is not much help when it comes to programming
You are missing self in your function def NewPage(self): and go to the line which you have root.after(2000, NewPage) and replace it with root.after(2000, self.NewPage)
I am trying to let the user add three entries and the code will use them to get data from an API and then export the data to CSV. I am trying to do it like this but I am not sure what is the issue and I am still new on Tkinter.
from Tkinter import *
import sys
import csv
from urllib import urlopen
import json
from dateutil.relativedelta import relativedelta
from datetime import datetime
import pandas as pd
root = Tk()
start2 = StringVar()
end2 = StringVar()
root.geometry("1600x800+0+0")
root.title("Data")
startd = "2017-13-03"
endd = "2017-13-03"
power1 =""
ID = "1232.4343.323"
class data1:
def __init__(self,master):
frame = Frame(master)
#frame.pack()
Tops = Frame(root, width=1600, height=1000, bg="powder blue")
Tops.pack(side=TOP)
self.output()
thelabel = Label(Tops, text="Data",font =('arial',30))
thelabel.pack(side=TOP)
def output(self):
Label(text='Start Date:',font=('arial', 12, 'bold')).pack(side=LEFT,padx=12,pady=12)
self.startd = Entry(root, width=10)
self.startd.pack(side=LEFT,padx=2,pady=16)
Label(text='End Date:',font=('arial', 12, 'bold')).pack(side=LEFT,padx=12,pady=12)
self.endd = Entry(root, width=10)
self.endd.pack(side=LEFT,padx=2,pady=16)
Label(text='Device ID:',font=('arial', 12, 'bold')).pack(side=LEFT,padx=12,pady=12)
self.ID = Entry(root, width=10)
self.ID.pack(side=LEFT,padx=2,pady=16)
self.b = Button(root, text='Submit', command=self.getjsondata)
self.b.pack(side=LEFT,padx=20,pady=5)
def getjsondata(self):
global power1
url1 = "https://api.data.com/mongo/measures/"+ID+"/"+startd+"/"+endd+"/?format=json"
power1 = urlopen(url1).read()
power1 = json.loads(power1)
power11 = pd.DataFrame(power1)
power11.csv(power11, file="MyData.csv")
b = data1(root)
root.mainloop()
The data comes in a json format and this is how the data comes:
[{"timestamp":"2017-01-14T19:47:00Z","value":"423"},{"timestamp":"2017-01-14T19:47:30Z","value":"419"},{"timestamp":"2017-01-14T19:48:00Z","value":"431"},{"timestamp":"2017-01-14T19:48:30Z","value":"429"},{"timestamp":"2017-01-14T19:49:00Z","value":"422"},{"timestamp":"2017-01-14T19:49:30Z","value":"427"},{"timestamp":"2017-01-14T19:50:00Z","value":"426"},{"timestamp":"2017-01-14T19:50:30Z","value":"427"},{"timestamp":"2017-01-14T19:51:00Z","value":"428"},{"timestamp":"2017-01-14T19:51:30Z","value":"426"},{"timestamp":"2017-01-14T19:52:00Z","value":"424"},{"timestamp":"2017-01-14T19:52:30Z","value":"423"},{"timestamp":"2017-01-14T19:53:00Z","value":"453"},{"timestamp":"2017-01-14T19:53:30Z","value":"433"},{"timestamp":"2017-01-14T19:54:00Z","value":"445"},{"timestamp":"2017-01-14T19:54:30Z","value":"438"},{"timestamp":"2017-01-14T19:55:00Z","value":"430"},{"timestamp":"2017-01-14T19:55:30Z","value":"437"},{"timestamp":"2017-01-14T19:56:00Z","value":"425"},{"timestamp":"2017-01-14T19:56:30Z","value":"420"},{"timestamp":"2017-01-14T19:57:00Z","value":"431"},{"timestamp":"2017-01-14T19:57:30Z","value":"435"},{"timestamp":"2017-01-14T19:58:00Z","value":"443"},{"timestamp":"2017-01-14T19:58:30Z","value":"430"},{"timestamp":"2017-01-14T19:59:00Z","value":"425"},{"timestamp":"2017-01-14T19:59:30Z","value":"406"},{"timestamp":"2017-01-14T20:00:00Z","value":"412"},{"timestamp":"2017-01-14T20:00:30Z","value":"417"},{"timestamp":"2017-01-14T20:01:00Z","value":"422"},{"timestamp":"2017-01-14T20:01:30Z","value":"422"},{"timestamp":"2017-01-14T20:02:00Z","value":"418"},{"timestamp":"2017-01-14T20:02:30Z","value":"415"},{"timestamp":"2017-01-14T20:03:00Z","value":"423"},{"timestamp":"2017-01-14T20:03:30Z","value":"411"},{"timestamp":"2017-01-14T20:04:00Z","value":"413"}]
I have filtered the data using panadas, my main issue is how to link an entry to a variable that I could use in my code. The entries are:
ID:
Starting date:
Ending date:
Please let me know what is the issue in my code.On the other hand I am planing to give the user the open in where to save the csv file on his computer if that is possible.
Thanks in advance
If problem is on pandas side:
It seems you need read_json and then if need select data by timestamps use loc:
df = pd.read_json(url1).set_index('timestamp')
print (df)
value
timestamp
2017-01-14 19:47:00 423
2017-01-14 19:47:30 419
2017-01-14 19:48:00 431
2017-01-14 19:48:30 429
...
...
date = pd.to_datetime('2017-01-14 19:47:00')
var = df.loc[date, 'value']
print (var)
423