I am running tkinter library in the Odoo15 for a specific purpose.
I have created a custom python interpreter to run python code inside odoo.
To handle user inputs i specially designed a concept and via tkinter i am taking inputs from user.
In a code there may be more than one inputs and so i need to open the window more than one time. for example taken one input, Entered, closed window and then repeat the same process till final user input.
So in that case, at some movement my server getting terminated with a runtime error:
Tcl_AsyncDelete: cannot find async handler
Aborted (core dumped)
can anyone guide me how can i resolve this please ?
import tkinter as tk
import gc
root=tk.Tk()
root.geometry('800x200+600+300')
name_var=tk.StringVar()
var_1 = ''
def submit():
name=name_var.get()
global %s
var_1 = name
root.destroy()
name_label = tk.Label(root, text = 'Enter value', font=('calibre',10, 'bold'))
name_entry = tk.Entry(root,textvariable = name_var, font=('calibre',10,'normal'))
sub_btn=tk.Button(root,text = 'Submit', command = submit)
name_label.grid(row=0,column=0)
name_entry.grid(row=0,column=1)
sub_btn.grid(row=2,column=1)
root.mainloop()
when there is a line like value = input("Enter value")
i am replacing that line with the above code to take user input.
Looking forward to hear on this .. thanks
Without a minimal reproducible example it is more of a guessing than an answer.
But due to your request, I'll try my best guess. The information how you code this section below, can be crucial.
In a code there may be more than one inputs
and so i need to open the window more than
one time. for example taken one input,
Entered, closed window and then repeat the
same process till final user input.
If you destroy the root window, the instance of tkinter.Tk() and you try to retrieve the users input (data located in tkinter) of the destroyed instance you could run into trouble. Instead of creating new instances of tkinter.Tk use tkinter.Toplevel. You could hide the root window in many ways. I.e with overrideredirect and transparency.
TL;DR
Make sure you use the same instance of tkinter.Tk() through out the whole session and or connect the new instance with your server and vice versa.
Hope it will work out for you, especially because I don't know about odoo.
So I'm building this program
def buffer():
global buf
frame2 = ttk.Frame(notebk, relief = RAISED)
if buf==0:
notebk.add(frame2, text = 'Buffer pH')
notebk.select(frame2)
buf=1
else:
notebk.select(frame2)
import buffer
buffer.main(frame2)
This part of the code is supposed to call another program I've written somewhere in a separate file on a new tab.
def main(x):
g=x
op=Label(g,text="Hello") #...and so on
The program works but the widgets on the new tab appear either significantly late or after the window is configured in some way (moved/resized).
Any tips on how I can fix this?
My question is in the context of a GUI. I'm trying to create a program that sends simply emails with a GUI where a user can enter their email, pass and recipient email. I've coded both the GUI and the logic in a single file, separated by functions and both of them are in the same class. Is this a good idea?
Anyway, moving on. I want to set the "Send" command to the "send_email" method I created in the class, but it says it has not been declared. My code (with all the irrelevant stuff removed for this purpose) is below:
class Application(Frame):
init, other widget creation\packing stuffs
def create_widgets(self):
widget creation methods...
#For the send button
self.send = Button(self.framepack, text="Send", width=10, command=send_email)
self.send.pack(padx=5, pady=5)
def send_email(self):
email sending code...
Unfortunately a setup like this raises a NameError where the send_email(self) function has not been defined. The ONLY other way I can get my code to work is when I use a config method for the send button to add in the command as follow:
root = Tk()
app = Application(root)
app.send.config(command=app.send_email)
Is my program badly structured? How would you do it? Would you simply write this procedurally and skip the whole OOP approach? (Saves a LOT of repititive "self" mentions when creating\referring to variables this way).
This is probably what you want:
self.send = Button(self.framepack, text="Send", width=10, command=self.send_email)
I'm writing a 'wizard' type Python Tkinter GUI that collects information from the user and then performs several actions based on the user's entries: file copying, DB updates, etc. The processing normally takes 30-60 seconds and during that time, I want to:
Provide the user with text updates on the activity and progress
Prevent the user from closing the app until it's finished what it's doing
I started on the route of having the text updates appear in a child window that's configured to be trainsient and using wait_window to pause the main loop until the activities are done. This worked fine for other custom dialog boxes I created which have OK/cancel buttons that call the window's destroy method. The basic approach is:
def myCustomDialog(parent,*args):
winCDLG = _cdlgWin(parent,*args)
winCDLG.showWin()
winCDLG.dlgWin.focus_set()
winCDLG.dlgWin.grab_set()
winCDLG.dlgWin.transient(parent)
winCDLG.dlgWin.wait_window(winCDLG.dlgWin)
return winCDLG.userResponse
class _cdlgWin():
def __init__(self,parent,*args):
self.parent = parent
self.dlgWin = tk.Toplevel()
self.userResponse = ''
def showWin(self):
#Tkinter widgets and geometry defined here
def _btnOKClick(self):
#self.userResponse assigned from user entry/entries on dialog
self.dlgWin.destroy()
def _btnCancelClick(self):
self.dlgWin.destroy()
However this approach isn't working for the new monitor-and-update dialog I want to create.
First, because there's no user-initiated action to trigger the copy/update activities and then the destroy, I have to put them either in showWin, or in another method. I've tried both ways but I'm stuck between a race condition (the code completes the copy/update stuff but then tries to destroy the window before it's there), and never executing the copy/update stuff in the first place because it hits the wait_window before I can activate the other method.
If I could figure out a way past that, then the secondary problem (preventing the user from closing the child window before the work's done) is covered by the answers below.
So... is there any kind of bandaid I could apply to make this approach work the way I want? Or do I need to just scrap this because it can't work? (And if it's the latter, is there any way I can accomplish the original goal?)
self.dlgWin.overrideredirect(1) will remove all of the buttons (make a borderless window). Is that what you're looking for?
As far as I know, window control buttons are implemented by the window manager, so I think it is not possible to just remove one of them with Tkinter (I am not 100% sure though). The common solution for this problem is to set a callback to the protocol WM_DELETE_WINDOW and use it to control the behaviour of the window:
class _cdlgWin():
def __init__(self,parent,*args):
self.parent = parent
self.dlgWin = tk.Toplevel()
self.dlgWin.protocol('WM_DELETE_WINDOW', self.close)
self.userResponse = ''
def close(self):
tkMessageBox.showwarning('Warning!',
'The pending action has not finished yet')
# ...
I'm very interested in the Twisted web framework. As far as I know the framework
uses the Hollywood principle. I just know the term but totally have no
idea about this design pattern.
I have done a lot of Google searching on the implementation of the
Hollywood principle in Python. But there were few results.
Could any one show me some simple python code to describe this design pattern?
I've actually never heard the phrase "Hollywood principle" before, nor am I familiar with Twisted (though I feel I should be). But the concept of inversion of control isn't so difficult. I think GUI programming is a good way to introduce it. Consider the following from here (slightly modified).
import Tkinter
class App(object):
def __init__(self, master):
frame = Tkinter.Frame(master)
frame.pack()
self.button = Tkinter.Button(frame, text="QUIT", fg="red", command=frame.quit)
self.button.pack(side=Tkinter.LEFT)
self.hi_there = Tkinter.Button(frame, text="Hello", command=self.say_hi)
self.hi_there.pack(side=Tkinter.LEFT)
def say_hi(self):
print "hi there, everyone!"
root = Tkinter.Tk()
app = App(root)
root.mainloop()
This is a very simple example of inversion of control. It uses callbacks -- hence the Hollywood principle moniker (thanks Sven for the link). The idea is that you write a function, but you never call it. Instead, you hand it over to another program and tell that program when to call it. Then you give control to that program. Here's a detailed explanation of the code:
import Tkinter
class App(object):
We start with a class definition, which will hold our callbacks and pass them to the appropriate parts of what I'll call the "master program."
def __init__(self, master):
Our class needs a "master program"; the master program is what will call the functions we define. In this case, it's the root window of the GUI. More properly, in the context of GUI programming, we might say that master is the parent of frame.
frame = Tkinter.Frame(master)
frame.pack()
These two lines create a Frame object, which is essentially a box that contains widgets. You'll see what a widget is in a second. As you can see, it also has a parent -- the same one as our App's: master.
self.button = Tkinter.Button(frame, text="QUIT", command=frame.quit)
self.button.pack(side=Tkinter.LEFT)
self.button is a widget. When you create it with Tkinter.Button, you give it some properties, like a label (text="QUIT"). You also tell it what its parent is -- in this case, not master, but frame. So now we have a hierarchy -- master -> frame -> button. But the most important thing we do is this: command=frame.quit. This tells the button what to do when it is activated by a mouse click. This is, in short, a callback. Here, we pass it the frame's quit method, which in this case causes the whole program to quit. Note that the function is not followed by () -- that's because we don't want to call it. We just want to hand it over to button.
self.hi_there = Tkinter.Button(frame, text="Hello", command=self.say_hi)
self.hi_there.pack(side=Tkinter.LEFT)
This is another widget that is almost identical to the first, the only exception being that instead of passing self.quit as a callback, we've passed self.say_hi. Since this is defined below, you could substitute any function you wanted here. (In both the above sets of lines, self.button.pack just tells the Button where it should go in frame.)
def say_hi(self):
print "hi there, everyone!"
say_hi is where you define what the Hello button does.
root = Tkinter.Tk()
app = App(root)
Now we invoke our class, creating an instance. We create the root window, and then create an App instance with root as its parent.
root.mainloop()
And then we're done. We pass control to Tkinter, which does the rest of the work.
Twisted is designed with an asynchronous approach. Your program causes something to happen, but instead of waiting for that thing to happen, it passes control back to the twisted event loop ('reactor' in twisted parlance). When the reactor finds that something needs your attention, it will invoke your program with the 'callback' you supplied when you originally invoked the action. The basic workflow looks like this. First,
something_deferred = make.twisted.do.something()
the something_deferred is usually a twisted.internet.defer.Deferred instance that represents the result of something(). Usually, something() takes some time to complete, and so the deferred object doesn't yet have the results, even though something() returned immediately. What you then have to do is define a function that twisted can call once the result is actually ready.
def something_callback(result):
do_something_else(result)
In most cases, you should also define a function that handles the case that an error occured in something(),
def something_errback(fault):
cleanup_something()
Finally, you have to tell twisted that you want it to use those functions when something() is finally ready.
something_deferred.addCallbacks(something_callback, something_errback)
Note that you don't call the functions yourself, you just pass their names to addCallbacks(). Twisted is itself responsible for calling your functions.
Not every example follows this exact pattern, but in most cases, you put an instance method in a class that implements a twisted defined interface, or pass a callable to twisted functions that produce events.
The "hollywood principle" is so named because, in the movie industry in Hollywood, nervous first-time actors sometimes call the studio over and over again after an audition, to see if they got the part. In software development we call this polling, and it's super inefficient. In the Hollywood metaphor, it wastes even a successful applicant's time (because they may call repeatedly before the selection has been made) and it wastes the studios time (because many applications who were not selected will nevertheless call them).
Here's a Python file which hopefully illuminates the principle in action:
First, we have an Actor, who can perform for an audition, or get a part:
class Actor(object):
def __init__(self, name):
self.name = name
def youGotThePart(self):
print self.name, "got the part."
def perform(self):
print self.name, "performs an audition."
Then, we have the casting process:
applicants = []
def audition(actor):
actor.perform()
applicants.append(actor)
def cast():
import random
selection = random.choice(applicants)
selection.youGotThePart()
An audition asks an actor to perform, and when casting happens, an actor is selected (at random - as a non-participant in Hollywood's process, I suspect this is probably the most realistic simulation). That actor then gets notified (the studio "calls" them).
And finally, here's the whole casting process:
alice = Actor("alice")
bob = Actor("bob")
carol = Actor("carol")
dave = Actor("dave")
audition(alice)
audition(bob)
audition(carol)
audition(dave)
cast()
As you can see, this is very simple and doesn't involve GUIs or networks or any other external sources of input. It's just a way to structure your code to avoid wasteful checking and re-checking of the same state. If you think about structuring this program to not follow the principle in question, you'd have a loop something like this:
while True:
for actor in alice, bob, carol, dave:
if actor.didIGetThePart():
break
maybeGiveSomeoneThePart()
which is of course very wasteful, since who knows how many times the actors might make those calls before the studio chooses?