this is my main module(this is for a point of sale system)
from tkinter import *
from SettingsMenuPOS import *
from Globalvariables import *
root = Tk() #mainprogram
root.iconbitmap('D:/Gatlabs logo.ico')
opensettingsmenu = Button(root, text= "Open Settings", command = settingsmain)
root.title(Mname)
opensettingsmenu.grid(row= 0, column= 0)
enter_button = Button( root , text = "ENTER", padx = 20, pady = 10, command= EnterEvent)
enter_button.grid(row= 0, column= 1)
root.mainloop()
im importing a setting module which changes the title of the program
from Globalvariables import *
from tkinter import *
#Mart Name
#user accounts
def settingsmain():
settingmenu = Toplevel()
settingmenu.iconbitmap('D:/Gatlabs logo.ico')
global entryformartname
labelformartname = Label(settingmenu, text = "Enter name of your store")
entryformartname = Entry(settingmenu)
entryformartname.grid(row = 0, column = 0)
setmartname = Button(settingmenu, text = "setname", command = setname)
setmartname.grid(row= 0, column = 1)
settingmenu.mainloop()
def setname():
global Mname, entryformartname
Mname = entryformartname.get()
and im using a global variable Mname to display title of the program.
ive set the variable Mname = "Gatlabs" and the user can change it through entry.
but everytime i try to set the title it doesnt change :(
i hope to get better at coding but i suck. pls help im stuck
I think the problem here is that you are thinking that using -:
root.title(var)
would make it so that anytime you change the var the title will change, but actually its that the title is changed only once and to the value of the var at the time it was supplied.
So if you want it to change everytime you change your var, then rather put it in the same function as the one where you change your var.
def update_title(title) :
global var
var = title
root.title(title)
return
and now every time you change the title run this down with the desired title as the argument.
I hope this solves your problem.
Also i hope you're safe in the time of an ongoing pandemic.
Change setname function like this:
def setname():
global Mname, entryformartname, setmartname
Mname = entryformartname.get()
parent_name = setmartname.winfo_parent()
parent = setmartname._nametowidget(parent_name)
parent.title(Mname)
In your code, you just update Mname variable and window title stays unchanged.
Update:
You can get the master from button widget which is the window itself. Then, change its title.
Related
I am making a simple GUI using Python's tkinter module, and I'm having a lot of trouble with radiobuttons. I wish to have the first selected by default, but the other two are selected at the start. Additionally, when I just pass the cursor over the window, the first one becomes checked (I do not click) so all 3 show as selected. My code:
import tkinter as tk
class openGUI(object):
def __init__(self):
# title of window
window.title("DUNE LArTPC Simulator")
# label for choices
self.question = tk.Label(window, text = "Do you want to create new or analyse existing data?")
self.question.grid(row = 0, column = 0, columnspan = 3)
# buttons corresponding to choices
self.createBtn = tk.Button(window, text = "Create", command = self.createData)
self.analyseBtn = tk.Button(window, text = "Analyse", command = self.analyseData)
self.createBtn.grid(row = 1, column = 0)
self.analyseBtn.grid(row = 1, column = 2)
def analyseData(self):
"""
Not implemented yet.
"""
pass
def createData(self):
# edit window to display new widgets (irritating to have lots of windows open!)
window.title("Select variable")
self.question.destroy()
self.createBtn.destroy()
self.analyseBtn.destroy()
# text in window
variableQ = tk.Label(window, text = "Please select Independent variable for dataset:")
variableQ.grid(row = 0, column = 0, columnspan = 3)
# radioselect variable
selection = tk.StringVar()
selection.set("lifetime")
# radioselect buttons
lifetimeBtn = tk.Radiobutton(window, variable = selection, value = "lifetime", text = "Lifetime")
elecNoiseBtn = tk.Radiobutton(window, variable = selection, value = "electronic", text = "Electronic Noise")
radioactivityBtn = tk.Radiobutton(window, variable = selection, value = "radioactive", text = "Radioactivity")
lifetimeBtn.grid(row = 1, column = 0)
elecNoiseBtn.grid(row = 1, column = 1)
radioactivityBtn.grid(row = 1, column = 2)
# create window
window = tk.Tk()
# create class object with methods to populate
# window with widgets
initWin = openGUI()
# enter mainloop
window.mainloop()
Running the above gives me:
I have tried using lifetimeBtn.select() method instead of setting the StringVar(), but this does not seem to work either. What have I missed?
EDIT: added rest of code to show how I am using class and functions to manipulate the window.
It is because selection is a local variable inside createData() function and it will be garbage collected after function completes.
Change selection to instance variable self.selection.
I am very new to Tkinter ( I find it very difficult to learn). I have a python script working based on user input. I would like to wrap a GUI around it and eventually put it on web. In any case for user input I would like to get this from the GUI with a combination of Entry widgets and some buttons. First thing is I was reading and some people mentioned to use a class so I have the following. I have a few questions
I would like to check to see if indeed the users entered a value before he hits the GO button. How do I do this?
I would like the value entered to be made accessible by the rest of the program in the main body. How do I do this?
Thanks,
from Tkinter import *
class MainWindow():
def get_fc(self):
a = self.fc_gui.get()
return a
def __init__(self, master):
self.master = master
self.master.title('TEST')
self.fc_gui = DoubleVar(self.master, value = 500.00)
self.fclabel1 = Label(self.master, text = 'Please Enter a value', fg = 'black', bg = 'yellow')
self.fclabel1.grid(row = 0, column = 0)
self.fcedit1 = Entry(self.master, textvariable = self.fc_gui, bd = 5 )
self.fcedit1.grid(row = 1, column = 0)
fcbutton1 = Button(self.master, text='GO', command = self.get_fc)
fcbutton1.grid(row = 1, column = 1)
master = Tk()
MainWindow(master)
master.mainloop()
It doesn't make sense to return to a Button. The Button can't do anything with the value. Instead, save the value as an instance variable.
You don't have a mainloop().
You can't really check if the user entered a value before they hit "Go" - at the start of the program, of course they haven't entered anything yet. If you needed to track the contents of this field, there are ways to do that, but it's not necessary for a simple validation. Just check the value when they hit the button.
from Tkinter import *
class MainWindow():
def get_fc(self):
a = self.fc_gui.get()
if a: # this block will execute if a has content
self.a = a # save it for future use
def __init__(self, master):
self.master = master
self.master.title('TEST')
self.fc_gui = DoubleVar(self.master, value = 500.00)
self.fclabel1 = Label(self.master, text='Please Enter a value',
fg = 'black', bg = 'yellow')
self.fclabel1.grid(row = 0, column = 0)
self.fcedit1 = Entry(self.master, textvariable = self.fc_gui, bd = 5 )
self.fcedit1.grid(row = 1, column = 0)
fcbutton1 = Button(self.master, text='GO', command = self.get_fc)
fcbutton1.grid(row = 1, column = 1)
master = Tk()
MainWindow(master)
master.mainloop() # don't forget mainloop()
first off im very new to programing Python 3.4.3, im trying to call 5 entrys and put them into and array and display that, but im stuck at GPA1 not defined, but it is defined in for the entry app
import sys
from tkinter import *
def save_data():
fileD.write("GPA1:\n")
fileD.write("%s\n" % GPA1.get())
fileD.write("GPA2:\n")
fileD.write("%s\n" % GPA2.get())
fileD.write("GPA3:\n")
fileD.write("%s\n" % GPA3.get("1.0", END))
app = Tk()
app.title('Student Grade Report')
gpa1=str(GPA1.get())
gp1=float(gpa1)
gpa2=str(GPA2.get())
gp2=float(gpa2)
gpa3=str(GPA3.get())
gp3=float(gpa3)
gpa4=str(GPA4.get())
gp4=float(gpa4)
gpa5=str(GPA5.get())
gp5=float(gpa5)
gpas=gp1+gp2+gp3+gp4+gp5
avg=gpas/5
def DisplayMsg():
DL=str("Dean's list")
AP=str("Academic Probation")
note=("No Message")
if (avg>3.5):
note=DL
else:
if (avg<2.0):
note=AP
return str(note)
classi = StringVar()
classi.set(None)
Label(app, text = "Classification:").pack()
Classification = StringVar()
Classification.set(None)
Radiobutton(app, variable = classi, text = "freshman", value = "freshman").pack()
Radiobutton(app, variable = classi, text = "sophmore", value = "sophmore").pack()
Radiobutton(app, variable = classi, text = "junior", value = "junior").pack()
Radiobutton(app, variable = classi, text = "senior", value = "senior").pack()
Label(app, text = "GPA1:").pack()
GPA1= StringVar()
GPA1.set(None)
GPA1= Entry(app,textvariable=Gpa1).pack()
Label(app, text = "GPA2:").pack()
GPA2= StringVar()
GPA2.set(None)
GPA2 = Entry(app)
Label(app, text = "GPA3:").pack()
GPA3= StringVar()
GPA3.set(None)
GPA3= Entry(app)
Label(app, text = "GPA4:").pack()
GPA4= StringVar()
GPA4.set(None)
GPA4= Entry(app)
Label(app, text = "GPA5:").pack()
GPA5= StringVar()
GPA5.set(None)
GPA5= Entry(app)
Button(app, text= "Message", command = DisplayMsg).pack()
Button(app, text = "Save", command = save_data).pack()
app.mainloop()
The program published above does have some problems with indentation, but I suspect that this happened when inserting into the editor.
Also, I suspect your error says Gpa1 undefined, not GPA1. This is because you assign a text variable to the Entry which is not initialized yet (i.e. it does not exist).
The way you pack() the widgets, make them appear vertically. If you want them in a spreadsheet like table, you have to use a packer such as .grid(), and specify the column and row where you want the widget to appear.
Here's the code, slightly cleaned up (Note that I had to use Tkinter to find the module - not tkinter):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from Tkinter import *
def save_data():
fileD.write("GPA1:\n")
fileD.write("%s\n" % GPA1.get())
fileD.write("GPA2:\n")
fileD.write("%s\n" % GPA2.get())
fileD.write("GPA3:\n")
fileD.write("%s\n" % GPA3.get("1.0", END))
app = Tk()
app.title('Student Grade Report')
gpa1=str(GPA1.get())
gp1=float(gpa1)
gpa2=str(GPA2.get())
gp2=float(gpa2)
gpa3=str(GPA3.get())
gp3=float(gpa3)
gpa4=str(GPA4.get())
gp4=float(gpa4)
gpa5=str(GPA5.get())
gp5=float(gpa5)
gpas=gp1+gp2+gp3+gp4+gp5
avg=gpas/5
def DisplayMsg():
DL=str("Dean's list")
AP=str("Academic Probation")
note=("No Message")
if (avg>3.5):
note=DL
elif (avg<2.0):
note=AP
return str(note)
def main():
app = Tk()
app.title('Student Grade Report')
classi = StringVar()
classi.set(None)
Label(app, text = "Classification:").pack()
Classification = StringVar()
Classification.set(None)
Radiobutton(app, variable = classi, text = "freshman", value = "freshman").pack()
Radiobutton(app, variable = classi, text = "sophmore", value = "sophmore").pack()
Radiobutton(app, variable = classi, text = "junior", value = "junior").pack()
Radiobutton(app, variable = classi, text = "senior", value = "senior").pack()
Gpa1 = None
Label(app, text = "GPA1:").pack()
GPA1= StringVar()
GPA1.set(None)
GPA1= Entry(app,textvariable = Gpa1).pack()
Label(app, text = "GPA2:").pack()
GPA2= StringVar()
GPA2.set(None)
GPA2 = Entry(app)
Label(app, text = "GPA3:").pack()
GPA3= StringVar()
GPA3.set(None)
GPA3= Entry(app)
Label(app, text = "GPA4:").pack()
GPA4= StringVar()
GPA4.set(None)
GPA4= Entry(app)
Label(app, text = "GPA5:").pack()
GPA5= StringVar()
GPA5.set(None)
GPA5= Entry(app)
Button(app, text= "Message", command = DisplayMsg).pack()
Button(app, text = "Save", command = save_data).pack()
app.mainloop()
main()
NOTE: Sorry! I added a NOTE to the original post, instead of my answer. Here's the correct note: You are not done yet! There are still issues to be resolved. Eg. The fileD.write won't work if you don't open the file first.
You need to fix all the problems described in jcoppens' very thorough answer, but the actual problem you're asking about is another one, that you also need to fix. (I'm assuming that your actual indentation and structure looks like what he's guessed in his answer. If this doesn't apply to your actual code… well, it applies to the code in his answer, which your code will hopefully be a lot like once you fix all the other problems.)
Inside save_data, you do this:
fileD.write("%s\n" % GPA1.get())
But there's no global variable named GPA1, and no local variable inside that function named GPA1.
There is a local variable inside main with that name, but that doesn't help; the whole point of local variables is that they're local—the only live inside one function.
You could fix this by making GPA1 global, by just adding global GPA1 to the top of your main function. This is the quickest solution, but usually not the best.
A better solution is to create a class, and make GPA1 an attribute of that class. Whichever Tkinter docs or tutorial you're using will probably have lots of good examples of this.
You could also change save_data to take GPA1 as a parameter, and then use functools.partial(save_data, GPA1) instead of just save_data, as a callback.
Or you could put all of these functions inside another function and make GPA1 a nonlocal variable instead of a global one. (I wouldn't recommend this, just including it for completeness…)
Of course whatever you do, you need to do the same for GPA2 or you'll just get the same error again two lines later.
Needless to say, there's no guarantee this is the last bug in your program.
I am programming a simple game using tkinter and want an option at the end to be able to replay the game, but I am not sure how I would go about doing it. I would like to be able to go back to the beginning where i define init. Also is there a way I could do this and not have to quit it so I could save scores as the player keeps playing.
from tkinter import *
import random
class App:
def __init__(self, master):
player_dice = []
for i in range(1,6):
x = random.randint(1,6)
player_dice.append(x)
self.label = Label(master, text = x , fg = "red").grid(row =0, column =i+1)
self.label = Label(master, text = "Dice:" , fg = "red").grid(row =0, column =1)
self.hi_one = Button(master, text="one", command= lambda: say_one(player_dice)).grid(row = 1, column = 1)
self.hi_two = Button(master, text="two", command= lambda: say_two(player_dice)).grid(row = 1, column = 2)
Here is where I would like to add a button to loop back to init.
def num(var, die, dlist):
new_window = Toplevel(root)
if die == 1:
if guess == total:
result = Message(new_window, text = "You Win").grid(row = 1, column = 1)
else:
result = Message(new_window, text = "You Lose").grid(row = 1, column = 1)
restart = Button(new_window, text = "Play Again", command = ?????).grid(row=1, column = 2)
Easiest way:
Just add a function resetBoard that resets your game.
Obviously there are various parts of the UI that don't need to be re-set, so those can go into __init__, the rest can go into resetBoard() and you can (possibly) call resetBoard() from within __init__.
Correct way:
Implement an MVC or MVP pattern: Separate your data and logic from your UI. Your view (UI) should reflect whatever is in your model, then reseting the game is just a question of reseting the model and firing the correct events so the view is updated (highly simplistic, but the very useful model-view-XXX patterns cannot be properly explained in just a few words.)
Sorry if this is a rather specific problem, but let me try and explain it well.
I've got a text box that a user can add text to by typing in a box and hitting 'Send'.
The problem is that I need to clean out the textbox after fifteen lines have been used.
Here is what I tried to do:
Whenever the user hits send, to add the text to the textbox, it add's a number to a Variable called textlimiter. Because every send button creates a new line as well. I can use a variable to record the number of times something is 'sent' to the textbox.
When the variable exceeds 15, a thread that is watching the variable will wipe the textbox clean.
Thing is, It never seems to work. I've tried asking for help and I got a little from an awesome guy who suggested I rewrite everything into 'frames', so that I can class all my functions, widgets, and variables into one class.
It appears I've got a conflict ion with variable class's. So I tried to set the variable to 'global' inside my class's, and functions using the variable. But that didn't seem to work either.
I can go and rewrite it all into frames I suppose, but I was just going to ask if anyone has a quick fix they can think of here. (I also don't know when the guy can help me once I'm done and if issues arise)
If my question is inappropriate, or somehow not allowed, Tell me and I'll take it down tomorrow when I get up. Sorry if it's bad.
I've got the code here:
# [Importing Modules]
from tkinter import *
import os
import threading
#_________________| Setting Variables
global textlimiter
textlimiter = 0
#____________| Defining Functions
def CONVERT():
chatbox.insert(INSERT,"You: "+USER_ENTRY.get()+ "\n")
INPUT_BOX.set("")
global textlimiter
textlimiter += 1
#_______| Creating Window |
chat = Tk()
chat.title("Net Send Client [0.4]")
chat.geometry('550x500+200+200')
#________| Title |
title = StringVar()
title.set("Net Send Chat\n Type in box to send.")
title_widget = Label(chat,textvariable = title, height = 4)
title_widget.pack()
#_______________________| User Input Box|
INPUT_BOX = StringVar()
USER_ENTRY = Entry(chat,textvariable = INPUT_BOX)
USER_ENTRY.pack(side=TOP, padx = 10, pady = 20)
#___________________________________________________________________| Send Button|
send_button = Button(chat, text="Send",width = 20, command = CONVERT)
send_button.pack(padx = 10, pady = 10)
#_______________________________________________________| Text Box Widget |
chatbox = Text(width = 60, height = 15, relief = SUNKEN)
left = Frame(chatbox)
right = Frame(chatbox)
s_start = Scrollbar(right)
s_start.pack(side=RIGHT)
chatbox.grid(row = 0, column = 0, columnspan = 3)
chatbox.pack()
#__________________________________________| Chat Wizard Checks Text Limit|
class Chatwizard(threading.Thread):
def Chatmonitor():
global textlimiter
if textlimiter >= 15:
chatbox.set(None)
chatbox.insert(INSERT,"Console: Limit Reached, Chat Wiped" + "\n")
Chatwizard.start
chat.mainloop()
As you can see I've tried setting my variables to Global, but nothing seems to change.
If you try running the program, remember you need to enter and send something 15 times for it to supposedly wipe the chatbox.
Thanks for taking a look if you do. I'm really a little stumped right now.
You definitely do not need a thread to monitor the Text widget
(chatbox), because the chatbox itself can tell you how many lines
of text it contains:
numlines = len(chatbox.get("1.0",END).splitlines())
Moreover, Tkinter is not threadsafe. All GUI widgets should be
touched by one and only one thread.
from Tkinter import *
import os
import threading
def CONVERT():
numlines = len(chatbox.get("1.0",END).splitlines())
if numlines > 2:
chatbox.delete("1.0",END)
chatbox.insert(INSERT,"Console: Limit Reached, Chat Wiped" + "\n")
chatbox.insert(INSERT,"You: "+USER_ENTRY.get()+ "\n")
INPUT_BOX.set("")
chat = Tk()
chat.title("Net Send Client [0.4]")
chat.geometry('550x500+200+200')
title = StringVar()
title.set("Net Send Chat\n Type in box to send.")
title_widget = Label(chat,textvariable = title, height = 4)
title_widget.pack()
INPUT_BOX = StringVar()
USER_ENTRY = Entry(chat,textvariable = INPUT_BOX)
USER_ENTRY.pack(side=TOP, padx = 10, pady = 20)
send_button = Button(chat, text="Send",width = 20, command = CONVERT)
send_button.pack(padx = 10, pady = 10)
chatbox = Text(width = 60, height = 15, relief = SUNKEN)
left = Frame(chatbox)
right = Frame(chatbox)
s_start = Scrollbar(right)
s_start.pack(side=RIGHT)
chatbox.grid(row = 0, column = 0, columnspan = 3)
chatbox.pack()
chat.mainloop()