I have a wxPython gui that sometimes has weird behavior. I have a button that creates a dialog, then calls dia.Show() and dia.Center(). At this point dia.IsShownOnScreen, dia.IsActive, and dia.Shown are all "true", but the dialog is actually nowhere to be found.
Does anyone know any reasons why IsShownOnScreen would come up as true, but be incorrect?
I am trying to isolate this problem in the code, but the codebase is large and this problem may take a while to reproduce.
Any help is appreciated.
Edit:
If the following code is not run while initializing, my dialog window shows up without a problem:
TEXT="choose directory. No spaces are allowed in path!"
dia = wx.DirDialog(self, message=TEXT,defaultPath = os.getcwd() ,style=wx.DD_DEFAULT_STYLE )
result=dia.ShowModal()
if result == wx.ID_OK:
self.WD=str(dia.GetPath())
dia.Destroy()
This piece of code is used if the user runs:
$ program.py
instead of specifying a directory in the command line:
$ program.py -WD directory
The code above has no obvious relationship to the button and dialog in the main frame of my gui, but this code is definitely what is breaking things.
Related
I'm writing a program where most of user interaction happens in Windows Command line, however I use Tkinter for some File and Directory selection dialogs.
When I start up program by clicking .py file (In IDLE the problem doesn't occur), command line is launched and when Tk root window is instantiated, it takes over the focus from command line, even if I withdraw it.
This behaviour requires extra action from user to focus back on command line window.
Here is some code sample to reproduce the problem.
from tkinter import Tk
root_window = Tk()
root_window.withdraw()
name = input("Enter your name:\n")
print("Nice to meet you, " + name)
How do I keep Windows Command line in focus?
Strange enough, now your example works for me in the intended way - even though, ten minutes ago, it showed the problem you have reported. The only other thing I tried out inbetween was to add a latency to the withdraw call:
root_window.after(1, lambda: root_window.withdraw())
It seemed to also work as intended with a latency argument of zero, but now I am not sure what exactly changed the behaviour.
I’m building a program in python that will copy large files using robocopy. Since the gui freezes while the copy is done i only have two options:
1. Learn how to do multithreading and design the gui to show the progress and not freeze.
2. Keep the console on after compiling with pyinstaller as an alternative to show robocopy progress while the gui freezes.
I am open to doing multithreading but i’m a beginner and is pretty hard to understand how to make another subprocess for robocopy and from there extract the progress into a label from gui. The option i thought about is to have the cmd console active only while the copy is done. Is it possible? The scenario will be like this:
Open the program (the console will be hidden)
Press the copy button (console pops up and shows the copy progress while the gui freezes)
After the copy is done hide the console again
As i said above. I’m not totally excluding adding multithreading but for that i will need some help.
Thanks!
Please try this code, should be working, please let me know if something wrong:
import tkinter as tk
import os
import subprocess
import threading
main = tk.Tk()
main.title('Title')
frame_main = tk.Frame(main)
frame_main.grid(columnspan=1)
src = 'D:/path/to/the/folder'
dest = 'D:/path/to/the/folder2'
selection_platf = len(os.name)
def copy_build_button():
if selection_platf < 11:
subprocess.call(["robocopy", src, dest, r"/XF", 'BT V_SyncPackage.zip', "/S"])
else: #for linux
subprocess.call(["robocopy", src, dest, "/S"])
def copy_thread():
thread_1 = threading.Thread(target=copy_build_button)
thread_1.start()
button_main1 = tk.Button(frame_main, text="copy_build_button", width=50, height=5, fg="green", command=copy_thread)
button_main1.grid(column=0, sticky='N'+'S'+'E'+'W')
main.mainloop()
I am making a simple program that also incorporates the use of TKinter. The inclusion is to have it copy and paste to my clipboard and also to check the contents of my keyboard. However, without much change from me, the console spits out an error :
can't invoke "event" command: application has been destroyed while executing
"event generate $w <<ThemeChanged>>" (procedure "ttk::ThemeChanged" line 6)
invoke from within "ttk::ThemeChanged"`
My questions:
I do not understand what the error means;
I do not understand how to fix it.
From my understanding, these error usually pop up from the use of matplotlib, which I am not using. The python console still can function after this message but it is annoying and distracting.
here is the code that i think is affecting it.
from Tkinter import Tk
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append(finalbib)
r.destroy()
#os.startfile("TEMPPY.py")
clipbardtest=True
while clipbardtest:
r=Tk()
clippytest = r.clipboard_get()
r.destroy()
if clippytest==finalbib:
os.system('cls')
print "Successfully copied to clipboard"
#os.remove("TEMPPY.py")
clipbardtest=False
morebibdef()
else:
time.sleep(1.2)
#os.startfile("TEMPPY.py")
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append(finalbib)
r.destroy()
See one of the comments from this question
If you use this in a console script this might lead to an error, that
the .destroy() function will not work ("can't invoke "event" command:
application has been destroyed while executing [...]"). To prevent
this, call r.update() before r.destroy.
The error means that all of the tkinter windows have been destroyed, but that something is trying to generate an event. In order to generate an event you must have a window.
I have written an application in python 2.7 and tkinter. I created a tool bar with several buttons that open up respective top windows that display various options. I used ttk.Checkbutton with the 'toolbutton' style as an indicator to show whether the option windows are open or closed.
The problem is that the option windows will go to the back if another window is selected. Currently, if one selects the toolbutton again, the option window will close. However, I only want to close the window if it is on top. If the option window is not on top, I want the window to moved to the front.
Some of the code I have working:
class MainWindow:
def __init__(self,application):
self.mainframe=tk.Frame(application)
application.geometry("900x600+30+30")
self.otherOptionsSelect=tk.IntVar()
self.otherOptions_Button=ttk.Checkbutton(application,style='Toolbutton',variable=self.otherOptionsSelect,
onvalue=1, offvalue=0,image=self.optionsIcon, command=self.otherOptions)
def otherOptions(self):
if self.otherOptionsSelect.get()==0:
self.otherOptions.destroy()
return
self.otherOptions=tk.Toplevel()
self.otherOptions.title("IsoSurface Options")
self.otherOptions.geometry("200x165+"+str(int(application.winfo_x())+555)+"+"+str(int(application.winfo_y())+230))
self.otherOptApply_button=ttk.Button(self.otherOptions,text="Apply",command=self.showFrame)
self.otherOptApply_button.place(x=20,y=80,width=50,height=30)
self.otherOptClose_button=ttk.Button(self.otherOptions,text="Close",command=self.otherOptionsClose)
self.otherOptClose_button.place(x=80,y=80,width=50,height=30)
def otherOptionsClose(self):
self.otherOptionsSelect.set(0)
self.otherOptions.destroy()
Here is a picture of the entire application I have written:
In the above image, each window has their respective ttk.checkbutton. At the moment, toggling the checkbutton either opens or closes the window. However, what I really want it to do is close the window if the window is in front of the application, or bring the window to the front if it is behind the application.
Hopefully this clears some things up.
Thanks in advance!
It is in fact possible to check stacking order of windows. Using Tkinter, you have to do some funny tcl evals to get at the information. I found the answer at TkDoc in the section on Windows and Dialogs, scroll down until you get to "Stacking Order". The code baffled me until I started playing around with it interactively. My test code was:
import Tkinter as tk
root = tk.Tk()
root.title('root')
one = tk.Toplevel(root)
one.title('one')
two = tk.Toplevel(root)
two.title('two')
I then manipulated the windows so that two was on top, one under that and root below them all. In that configuration, the following weirdness can tell you relative layering of windows:
root.tk.eval('wm stackorder '+str(two)+' isabove '+str(root))
returns 1, meaning "Yes, window two is above window root." While the following:
root.tk.eval('wm stackorder '+str(root)+' isabove '+str(two))
returns 0, meaning "No, window root is not above window two." You can also use the command:
root.tk.eval('wm stackorder '+str(root))
Which gives back the full window stacking order in the form of a weird string something like this:
'. .68400520L .68401032L'
Which starts to make sense when you run the commands:
str(root)
str(one)
str(two)
and figure out that root has the internal name '.', one is '.68400520L' and two is '.68401032L'. You read the output of root.tk.eval('wm stackorder '+str(root)) backwards so it's saying two is on top, one is under that and root is below both.
My app has a GtkFileChooserButton that you can use to open a chooser widget and pick a single file .. and then perform operations on that file. This works.
I've added drag & drop functionality to the button as well. It works, but it's buggy.
In short, the first dnd to the FileChooserButton triggers the file-set signal and appears to have worked, -- the name changes from "( None )" to the file's name and if you then click on the button, it pops up a chooser widget showing the proper file selected; HOWEVER, as you can see from the debug output below, get_filename() does not return the filename! Not the first time, anyway.
The second time we dnd a file onto the button (whether it's a different file or the same file again), all goes well and get_filename() returns the file's name. Why?
Here's the debug output from my program when I drag three files on to the button, one at a time:
[on_file-set] FileChooserButton.get_filename() output:
None
[on_file-set] FileChooserButton.get_filename() output:
'/home/ryran/Desktop/priv.txt'
[on_file-set] FileChooserButton.get_filename() output:
'/home/ryran/Desktop/kinamppost'
PS: When I did this, the 1st and 2nd dnd were actually the same file.
If you want to see the full app in action, it's at http://github.com/ryran/pyrite, and I'd love to post code, but there's not really anything to post!! I'm not doing drag_dest_set() because FileChooserButton already supports dnd. So ALL I'm doing is defining a cb for the FileChooserButton's file-set signal. So uhh.. here's that:
def action_chooserbtn_file_set(self, widget):
print "[on_file-set] FileChooserButton.get_filename() output:\n{!r}\n".format(widget.get_filename())
For the record I also tried doing all this in concert with defining drag_dest_set, but came up with the same results.
What else to say? I'm starting to think this is a bug.
Turns out this really is a GTK+ bug. Talked to a developer on IRC. He helped me realize that and then encouraged me to post a bug report, which I did -- https://bugzilla.gnome.org/show_bug.cgi?id=669718