tkMessageBox popup invisible when run from desktop, visible when run from boot - python

I am trying to write a program that allows the user to press different buttons in a full screen Tkinter GUI. The operations these buttons preform does not matter for my question, but I am having trouble creating a popup dialogue (askokcancel) to confirm that the user wants to press a button, then run the rest of that buttons code normally if "ok" is pressed. Currently, I have this program running from boot through the /etc/profile file, accessed via
sudo nano /etc/profile
Here I change the directory to the folder containing my python file and have it load my code, and upon booting up it loads my buttons correctly and upon pressing the correct button the popup window appears over the full screen window. However, when I try to run my code through the desktop shell, upon pressing the button, the popup window DOES appear, but is hidden behind the root window. I am not able to click anywhere else, and pressing "tab" and "enter" allows me to navigate between the two choices and pick one, but without being able to see it. I have buttons printing words in the shell, so I know the popup window is actually there.
The full screen makes use of the overrideredirect function, hiding the task bar and other options. When this is set to FALSE, the popup works as intended, but I am trying to make the GUI be the only thing on the screen.
Here is a condensed version of my code:
from Tkinter import*
import tkMessageBox
class Application(Frame):
def run(self):
tkMessageBox.askokcancel("Run Confirmation!", "Are you sure?")
print "RUN Code Intitates"
def createWidgets(self):
self.button1 = Button(self,height=15,width=20)
self.button1["command"] = self.run
self.button1.pack({"side": "left"})
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
root = Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (800, 480))
app = Application(master=root)
app.mainloop()
root.destroy()
I am by no means a computer science major and have only been working with raspberry pi, tkinter, and python for a couple weeks, so if I am missing something basic I apologize. I am using an 8" touchscreen display made for raspberry pi as my screen.

According to the tcl/tk documentation:
Setting the override-redirect flag for a window causes it to be
ignored by the window manager; among other things, this means that the
window will not be reparented from the root window into a decorative
frame and the user will not be able to manipulate the window using the
normal window manager mechanisms
So the window does not always behave has expected (it is less the case in Windows). For instance, in Linux, the window does not get keyboard focus (python tkinter overrideredirect; cannot receive keystrokes (Linux)).
If what you really care about is to have a fullscreen GUI, just replace
root.overrideredirect(1)
by
root.attributes('-fullscreen', True)
and the window will behave normally so the message box will appear on top of the main window.
Another possibility in Linux is to replace
root.overrideredirect(1)
by
root.attributes('-type', 'dock')
This tells the window manager to treat the window as a dock, and at least in XFCE, it results in a window with no decorations, always on top of the other windows, but the message box does appear on top of it.

Related

How to make a program that doesnt close when X is pressed and still runs in backroun? [duplicate]

This question already has answers here:
Running a Tkinter window and PysTray Icon together
(3 answers)
Closed 10 months ago.
I want to make a script that runs every hour but i don't want the GUI to be visible in taskbar. I don't mind if the GUI is visible when the program is first opened but if the user decides to press the X i want the program to disappear from the taskbar and be visible in the bottom right corner(Skype, discord, ccleaner behaviour)
The GUI is made with tkinter.
How can i do this behaviour? If at all.
To detect if the close button is pressed in tkinter, use the following right before you run root.mainloop()
root.protocol("WM_DELETE_WINDOW", on_closing)
this will call the on_closing function when the user presses the close button, which you can use the following code to make it into a button
root.iconify()
This will minimize it to the taskbar as a button.
Note this will not work on Mac as the window will just be hidden and you will have no way to actually closing it unless killing it manually
so something like this
from tkinter import tk
root = tk.Tk()
#define widgets and other things here
def on_closing():
root.iconify()
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()
If you want it to be on the system tray, tkinter have no support for that, so you'll have to use something like pystray

RPI Tkinter Window, I want to use a command like overrideredirect and maintain entry box functionality

When using overrideredirect or something like root.wm_attributes('-type', 'splash') my entry box cannot get focus on user's click.
I am developing a GUI which I want to maintain the style of previous windows and not have this window stand out with the window header. How do I get rid of the RPI window bar but maintain entry box functionality.
When using the splash window type (Linux only), you can make the entry get the keyboard focus by using focus_force(), e.g. binding it to the left click.
import tkinter as tk
root = tk.Tk()
root.wm_attributes('-type', 'splash')
e = tk.Entry(root)
e.pack()
# force focus on left click:
root.bind('<1>', lambda ev: ev.widget.focus_force())
root.mainloop()

How to open a root window, close it and then open another window in tkinter after a few seconds?

I have made a GUI using Tkinter for my Python script for a Voice Assistant. It is working pretty well. But I want to add an animation window to display an animation that I have created using After Effects as an intro to the app. I want it to open without the default close(x), maximize and minimize buttons. The window should stay till the animation is completed, and then it would disappear. The main window would then open normally to launch the GUI. To disable the close, maximize and minimize buttons I have used the root.overrideredirect(True) method. But I am not being able to simultaneously open the two windows one after the other as mentioned. I would be highly obliged if somebody would help me out with this! I have tested it with a code on a simple GUI. I am providing the code below for help with the problem!
from tkinter import *
import time
root = Tk()
root.geometry('500x300')
root.overrideredirect(True) # To disable the default Window decoration
time.sleep(5) # Assuming that the animation runs for 5 seconds
root.destroy() # This window destroys after being on screen for 5 seconds
root.mainloop()
root2 = Tk() # After the previous window is destroyed, this window opens up. Assume that this is the main window
root2.geometry('500x300')
root.mainloop()
Please help me out!
The thing you call "animation window" is actually called "splash". There is a way to do what you want. You need to create a root window for the app (a Tk instance), and then you should hide (root.withdraw()) it. Now create a Toplevel for the splash, wait for 5 seconds, destroy it, and show (root.deiconify()) the Tk window again.
Note: time.sleep(5) should never be used with Tkinter, use root.after(ms, func) instead.
from tkinter import *
def show_splash():
splash = Toplevel()
splash.geometry('500x300')
splash.overrideredirect(True) # To disable the default Window decoration
splash.after(5000, splash.destroy) # This window destroys after being on screen for 5 seconds
splash.wait_window()
root = Tk()
root.withdraw()
show_splash()
root.deiconify()
root.mainloop()
PS: Procedural programming is not a good idea for pretty complex Tkinter-based apps. You should consider using OOP instead.
PPS: Take a look at this and this answers.

Tkinter tkMessageBox displays over root window when run from boot, but NOT when run from desktop

I am trying to write a program that allows the user to press different buttons in a full screen Tkinter GUI. The operations these buttons preform does not matter for my question, but I am having trouble creating a popup dialogue (askokcancel) to confirm that the user wants to press a button, then run the rest of that buttons code normally if "ok" is pressed. Currently, I have this program running from boot through the /etc/profile file, accessed via
sudo nano /etc/profile
Here I change the directory to the folder containing my python file and have it load my code, and upon booting up it loads my buttons correctly and upon pressing the correct button the popup window appears over the full screen window. However, when I try to run my code through the desktop shell, upon pressing the button, the popup window DOES appear, but is hidden behind the root window. I am not able to click anywhere else, and pressing "tab" and "enter" allows me to navigate between the two choices and pick one, but without being able to see it. I have buttons printing words in the shell, so I know the popup window is actually there.
The full screen makes use of the overrideredirect function, hiding the task bar and other options. When this is set to FALSE, the popup works as intended, but I am trying to make the GUI be the only thing on the screen.
Here is a condensed version of my code:
from Tkinter import*
import tkMessengerBox
class Application(Frame):
def run(self):
tkMessageBox.askokcancel("Run Confirmation!", "Are you sure?")
print "RUN Code Intitates"
def createWidgets(self):
self.button1 = Button(self,height=15,width=20)
self.button1["command"] = self.run
self.button1.pack({"side": "left"})
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
root = Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (800, 480))
app = Application(master=root)
app.mainloop()
root.destroy()
I am by no means a computer science major and have only been working with raspberry pi, tkinter, and python for a couple weeks, so if I am missing something basic I apologize.

Giving window focus in Gtk3

I'm using Python 2.7.4 with Gtk3 on Ubuntu 13.10.
I'm using the Keybinder library to hide and show my Gtk window using a hotkey. Now, when my window does show up using the hotkey, it does not always receive focus.
The concerned code is below:
def toggle(self, key, data):
if self.hidden:
self.hidden = False
self.set_keep_above(True)
self.set_accept_focus(True)
self.present()
self.enteredName.grab_focus()
else:
self.hidden = True
self.hide()
Here, self refers to the Gtk window and self.enteredName is a widget of type Gtk.Entry().
Normally, the combination of set_accept_focus(), set_keep_above(), followed by present() works. Without the set_keep_above, my window doesn't rise to the top. Without the set_accept_focus, my window doesn't get keyboard focus.
The above set up works when I just start my app and then test it using the hotkey (hiding and showing it). My window always receives keyboard focus. Howver, let's say I have a GVim window opened and I've given keyboard focus to it. On pressing the hotkey, my window shows up on the top (even on top of the GVim window), but the keyboard focus still lies with the GVim window.
I've tried several combinations (by adding activate), and grabbing focus on a text widget. But it's not working as expected.
Anything I'm missing here?

Categories

Resources