"execfile" doesn't work properly - python

I'm trying to make a launcher for my Python program with Tkinter. I used the execfile function, and fortunately it opened the target GUI. However, none of the buttons would work, and it would say the global variable most functions reference isn't defined.
The code to launch the program:
def launch():
execfile("gui.py")
That works. The base code for the target program:
from Tkinter import *
gui = Tk()
gui.title("This is a GUI")
EDIT:
Example of a button:
def buttonWin():
buttonWindow = Toplevel(gui)
button = Button(buttonWindow, text = "Button", width = 10, command = None)
button.pack()
When it references that 'gui' variable for Toplevel, it comes up with an error. I tried defining the 'gui' variable in the Launcher script, but that only caused the target script to open first, instead of the Launcher:
gui = Tk()
launcher = Tk()
launcher.title("Launcher")
def launch():
return execfile("gui.py")
launchButton = Button(launcher, text = "Launch", width = 10, command = launch)
When I try pressing one of this program's buttons, I get a NameError:
$NameError: Global variable 'gui' is not defined$
Also this is in Python 2.7.5.
Thank you anyone who answers, and sorry for any errors with the code blocks; I'm new.

The problem is that you have structured the Tkinter program incorrectly.
In "gui.py" you should have something like:
from Tkinter import *
gui= Tk()
gui.mainloop()
You can add buttons to perform functions and customize it:
from Tkinter import *
gui = Tk()
gui.title("This is a GUI")
def launch():
execfile("gui.py")
launchbutton = Button(gui, text='Launch Program', command=launch)
launchbutton.pack()
gui.mainloop()
I think with your function buttonWin you were trying to do what is normally handled by a class; see unutbu's answer here.
I'm not sure if I've addressed your problem, but this should be a start.

Related

Is there some way I can pass information to a tkinter application after calling .mainloop()?

This is a very simple version of my application. Basically I have a Tkinter application I want to start from another python application, but I do not have the option to have tkinter as my main window.
So my question is, if it's possible to pass some information from my main class to my tkinter application. Not once, but repeatedly.
I tried something like this, but this does not work, probably because of the .mainloop() method.
Right now I just try to print the variable "labelContent" whenever the button is pressed.
Is there some way I can pass information to my tkinter application after calling .mainloop() (besides using external files like .txt because this would obviously work)?
gui.py
import tkinter
class BasicWindow:
def __init__(self):
tk = tkinter.Tk()
label = tkinter.Label(tk, text="Hello World!")
label.pack()
self.labelContent = ""
button = tkinter.Button(tk,text="OK",command=self.buttonMethod)
button.pack(side="bottom")
tk.mainloop()
def buttonMethod(self):
print(self.labelContent)
main.py
from gui import BasicWindow
import time
class Main:
def __init__(self):
self.gui = BasicWindow()
self.gui.labelContent = "This is the new label content"
mainApp = Main()
while True:
mainApp.gui.labelContent = time.time()
Thanks in advance! :)

Python Tkinter pop-up not being displayed

I am trying to get a Tkinter popup to display when a button is clicked.My issue is that every thing runs just fine except the popup will not produce. I have tried multiple ways to create the popup using tkMessagebox and Toplevel() but still not luck. The program runs but when the button is click nothing happens. I have referenced similar post but still can not find the issue in my code. Any thoughts?
from tkinter import *
def new():
root2 = Tk()
root2.geometry('250x250')
l = Label(root2,text="Please Scan Tag").pack()
root2.mainloop()
# setting main frame
root = Tk()
root.geometry('800x650')
root.title("Pass")
root.configure(background= "white")
label_0 = Label(root, text="Pass",width=10,font=("bold", 50),fg= "green",bg="white")
label_0.place(x=186,y=76)
Button(root,command="new", text='new',font=
("bold",15),width=15,height=4,bg='blue',fg='white').place(x=155,y=300)
root.mainloop()
The command option requires a reference to a callable function, not a string.
Button(root,command=new, ...)

How do I get the Tkinter event-listener to work?

I'm using Tkinter for the GUI of a little tool I wrote with Python. Basically I just want a callback-method to be executed as soon as the contents of an entry widget have changed. This can be done with Tkinter's own variable classes (StringVar, BooleanVar, etc. - see documentation for details: http://effbot.org/tkinterbook/variable.htm).
So I couldn't get the mechanism to work and I found a snippet online, where it works perfectly fine. Now I'm trying to figure out why my version does not work.
As you can see in the two code examples the only difference is, that I'm using the event-listening functionality inside a class, whereas the snippet I found online only demonstrates it in a straight top-to-bottom manner.
Here's what I've already tried:
I instantiated the Tk instance directly in the constructor of my GUI class - same behaviour.
I inherited directly from the Tk class (instead of Frame) - same behaviour.
I placed the callback outside of the class - same behaviour.
The only idea I have is that the problem might be scope related, which I tried to verify.
Working code snippet:
from tkinter import *
import tkinter as tk
def text_changed(*args):
print("Text changed.")
top = tk.Tk()
string_listener = StringVar()
string_listener.set("Init Text")
string_listener.trace("w", text_changed)
entry_widget = tk.Entry(top, textvariable = string_listener)
entry_widget.pack()
top.mainloop()
Not working code snippet
from tkinter import *
import tkinter as tk
root = tk.Tk()
class GUI(tk.Frame):
def __init__(self, master=root):
super(GUI, self).__init__(master)
string_listener = StringVar()
string_listener.set("Init Text")
string_listener.trace("w", self.text_changed_callback)
entry_widget = tk.Entry(master, textvariable=string_listener)
entry_widget.pack()
def text_changed_callback(self, *args):
print("Text changed.")
gui = GUI()
gui.mainloop()
Like in the working example, my code ought to print Text changed., everytime a character is either deleted from or appended to the string in the extry-widget.
The problem is that string_listener is a local variable, and python is destroying the variable when __init__ finishes running. This doesn't happen in your original code since the variable is created in the global scope.
A simple solution is to save a reference as an attribute of the class:
import tkinter as tk
root = tk.Tk()
class GUI(tk.Frame):
def __init__(self, master=root):
super(GUI, self).__init__(master)
self.string_listener = tk.StringVar()
self.string_listener.set("Init Text")
self.string_listener.trace("w", self.text_changed_callback)
entry_widget = tk.Entry(master, textvariable=self.string_listener)
entry_widget.pack()
def text_changed_callback(self, *args):
print("Text changed.")
gui = GUI()
gui.mainloop()
note: I also changed StringVar to tk.StringVar so that I could remove the redundant wildcard import of tkinter.

how to call a function from another script inside an imported class

I am building my first larger Python application using tkinter, python 3.6.3 and window OS. The GUI for the application consists of a Notebook with several tabs. Each of the tabs in turn contains a Labelframe which in turn contains a number of other widgets.
When searching Stackflow, I found the idea to lets each labelFrame be a class. Thereafter import the class in the main.py and finally creating an instance of the class.
Now when pressing the button 'Start' in tab1 I would like to execute the 'printThis' function. Ideally I would like to use the function defined in the script main.py. It would also be interested in knowing how to call the 'printThis' method withing the Run_Test_Window class. Unfortunately I have not solved either problem.
Interestingly the program actually prints "Now successful" without that I do anything but when I press the 'Start'-button nothing happens.
Grateful for help! Thanks!
main.py
import tkinter as tk
import tkinter.ttk as ttk
import RunTestClass as RT
def printThis():
print('Successful')
root = tk.Tk()
note = ttk.Notebook(root)
note.grid()
tab1 = ttk.Label(note, width = -20)
note.add(tab1, text = " Run Test ")
window1 = RT.Run_Test_Window(tab1)
root.mainloop()
RunTestClass.py
import tkinter as tk
import tkinter.ttk as ttk
# from main import printThis
class Run_Test_Window:
def printThis(self):
print('Now successful!')
def __init__(self,tab1):
runTestLabelFrame = ttk.LabelFrame(text ="Run Test", padding =10)
runTestLabelFrame.grid(in_ = tab1, padx = 20, pady = 20)
self.startButton = ttk.Button(runTestLabelFrame, text="START",command=self.printThis())
self.startButton.grid(row=5, column=1, padx = 10)
If I'm correct you want the button to use the printThis() from main. This can be done by adding the following in your main:
rt = RT.Run_Test_Window(tab1)
rt.startButton.configure(command=printThis)
To call the printThis() defined in RunTestClass, use (also in main)
rt.printThis()
Note: leave the brackets when creating the button in the command argument. So change it to this:
self.startButton = ttk.Button(runTestLabelFrame, text="START",command=self.printThis)

No errors but wont run

So I have this code:
try:
# for Python2
from Tkinter import *
except ImportError:
# for Python3
from tkinter import *
class Injector():
def __openInjector(self):
root = Tk()
root.geometry('600x400')
root.title('Toontown Rewritten Injector')
root.resizable(False, False)
def __init__(self):
self.code = ''
self.__openInjector()
def runInjectorCode(self):
exec(self.code.get(1.0, 'end'), globals())
def __openInjector(self):
root = Tk()
root.geometry('600x400')
root.title('Toontown Rewritten Injector')
root.resizable(False, False)
frame = Frame(root)
self.code = Text(frame, width=70, height=20)
self.code.pack(side='left')
Button(root, text='Inject!', command=self.runInjectorCode).pack()
scroll = Scrollbar(frame)
scroll.pack(fill='y', side='right')
scroll.config(command=self.code.yview)
self.code.config(yscrollcommand=scroll.set)
frame.pack(fill='y')
Injector()
In the IDLE console it works fine and does everthing I want it to do. But whenever I run the .py file on my Desktop. The black window appears, then just closes and nothing happens. Any help?
First, you have two methods in your class with the same name. The first one gets overwritten by the second one. At the end of that second one, you need the following line:
root.mainloop()
This will actually run the GUI. It's needed when running from a script, but not when running within the interactive interpreter.
Add it at the end of the second __openInjector:
...
self.code.config(yscrollcommand=scroll.set)
frame.pack(fill='y')
root.mainloop()
At the end of your second __openInjector method, add the line: root.mainloop().
This is necessary for Tkinter to run your code. mainloop is really nothing more than an infinite loop that waits for events. An event may be a user interaction, such as clicking a button.
My guess is you don't need mainloop when running interactively for purely convenience reasons.

Categories