Python/Tkinter: erratic behaviour using root.overridedirect(True) - python

The following code disables the tkinter title bar, creates a replacement title bar, and enables the user to re-position the app on the screen by selecting and holding the replacement title bar and moving the mouse.
import tkinter as tk
root = tk.Tk()
root.geometry("1275x675+50+70")
root.overrideredirect(True) # remove tkinter title bar
def movewindow(event): # event bound to new title bar
root.geometry(f'+{event.x_root}+{event.y_root}')
titlebar = tk.Frame(root,borderwidth = 0, bg="lightblue",
width=1275,height=30)
titlebar.place(x=0,y=0)
titlebar.bind("<B1-Motion>",movewindow)
root.mainloop()
The code works perfectly in my main monitor. But if I move the app to my second monitor, it will disappear. Strangely, if I click anywhere on the second monitor it will re-appear, and after that, the app can be moved seamlessly across both monitors.
I should note that, when I click on the titlebar and begin to move the app, the cursor jumps to the left, so that I'm moving the app with the mouse pointer at the left hand corner of the title bar. The trouble begins the moment the mouse pointer leaves the main monitor.
If I initialize the root geometry on startup to +1600 instead of +50, the app will launch in the second monitor. And it can then be moved seamlessly between both monitors. Unfortunately, I want the app to launch in the main monitor, so that is not a workable fix.
Is there any fix that could be applied here?

Related

Weird white border top left of whole tkinter application

This is the first tkinter application I've ever made and I'm sure there are other issues with it but it works well for me. The only issue I have is for some reason on my 4k monitor there is a little white border on the top left side of the application. This does not appear on my 1080p monitor. Edit: It appears this is due to adding an icon. When I have an icon it happens. When I remove the icon part it goes away. This obviously isn't a solution though since I still want an icon for my application. I'll leave a picture of the issue and the code for the application here.
I'm not allowed to post images yet so here is a link for it
from tkinter import *
#Main Section
app = Tk()
app.title('Rust Furnace Calculator')
app.iconbitmap('Rust.ico')
app.configure(background='#33393B')
app.resizable(False, False)
app.geometry("500x500")
#Program Loop
app.mainloop()

How can I deactivate mouse motion (<Motion-1>) on windows taskbar while I am dragging my frameless window?

I am working on a Frameless window for modern GUI with Tkinter. I have implemented a drag window feature but It is also working when window is behind of the taskbar, it is a big problem when I am trying to recover my window from behind of taskbar. So I want to disable the drag feature when the mouse reaches on taskbar's border.
def drag(event):
act = str(event.type)
if act == 'Motion':
global _app
#_app is a reference to root in other py file
t = _app.geometry().split('+')[1:]
xval = int(t[0])
yval = int(t[1])
_app.geometry('+'+
str(xval + event.x -400)+
'+'+str(yval + event.y -20))
#window size is fixed i.e. 800x480
When you makes a window border-less using overrideredirect() method, then this method says to operating system's windows manager to just ignore your tkinter's GUI window.
When you do this then the windows manager now takes no any responsibility for your GUI window. Each and every task like window dragging, minimization and maximization, closing event etc should be handled by you manually.
Now to solve you dragging problem on windows taskbar there are two ways.
1) As I told you before that do everything manually, then you should to locate your windows taskbar manually and then modify your drag function to prevent your mouse motion after the borders of your taskbar.
2) The simplest way is to make your GUI window a top level window by which you will able to drag your window onto the taskbar without any window hiding problem.
To make the window top level you should just set an Attribute i.e. topmost = True.
root.attributes('-topmost',1)

Python capture events when console has focus with Tkinter

I'm building a console app, and would like to capture keystrokes in real time. The following code works perfectly until another window gets focus. From that point on, I'm not able to get back to a state where I can capture keystrokes and other events again with only the console visible.
import tkinter as tk
app = tk.Tk()
def handleKeypress(event):
key = event.char
if(key == 'q'):
app.destroy()
else:
print(key)
app.bind_all('<Key>', handleKeypress)
app.withdraw()
app.mainloop()
I've tried using various methods (grab and focus) to redirect the focus to my app. The best I was able to do was to get the Tkinter window visible and in focus with deiconify(), but I was not able to hide it again to make it as though the console is the only window.
Adding the following results in the Tkinter window appearing and disappearing repeatedly:
def lostFocus(event):
app.deiconify()
app.focus_force()
app.withdraw()
app.bind_all('<FocusOut>', lostFocus)
How can I go back to the state the application was in right after launch? Or even better, how can I force it to get all events without having to make the Tkinter window visible and in focus?
You can't do what you want. Tkinter is designed -- as are most GUI toolkits -- to only process events when it has the focus. That's the whole point of focus: for the OS to know where to send events.
The fact that it works initially is probably a bug in tkinter. Though, perhaps it can be explained by the fact that the window initially has focus, and when you withdraw the window the OS doesn't move the focus
The only way to restore focus is to make the window visible.

Tkinter application topmost, even over fullscreen

I'm using tkinter on Ubuntu.
I'd like my application to be on top of the screen, all the time. I'm aware of, and am currently using, wm_attributes("-topmost", 1). I've discovered that this is equal to right clicking on the menu bar of an application and selecting 'Always On Top', which works fine for most applications. However, this doesn't work when full-screen applications are launched (specifically, TF2). In such cases, my widget lies behind the game.
I'm also aware of overrideredirect(True), and this stays on top of the game even over full-screen, but this is not viable as the menu bar and being able to move the window are central to my application.
Is there a way to have tkinter remain on top of every application, including those that are full-screen? Basically the functionality of overrideredirect, but keeping the menu bar and the ability to move the window.

With PyGTK/win32, how do I place a new window near its parent but not off-screen?

With PyGTK running on Windows, I want to have a new window pop up near a parent window, but never off-screen.
I observed the behavior I want in Microsoft Wordpad in both Windows 7 and Windows XP. If you make the window very small and move it to the bottom right of the desktop, right click in the text field, and open the Paragraph menu, the dialog pops up fully visible. This happens even if the Wordpad window is partially off-screen. The child dialog does not pop up in a fixed position relative to the main window. It just pops up close, and fully visible.
My application consists of a main screen which spawns child windows that block the rest of the application until the user is finished using them. The user may have to open and close many child windows in sequence, so I want them to appear near where they click on the button, so the user doesn't have to move the mouse all over the screen.
I tried using gtk.WIN_POS_MOUSE, but when the main menu is near an edge of the screen; the child window that spawns often ends up partially off-screen.
I would expect that a call to set_transient_for(main_menu) on a child window should inform Windows that I want my window to be near its parent. However, Windows just places it at the top left of the desktop -- not even necessarily on the same screen as the main menu.
The following code will demonstrate the problem by popping up a window at the bottom left of your screen that contains a button which spawns a subwindow when clicked:
import gtk
class MyWindow(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.connect("delete-event",self.on_delete_event)
button = gtk.Button("Open Subwindow")
button.connect("clicked",self.open_sub_window)
self.add(button)
self.set_gravity(gtk.gdk.GRAVITY_SOUTH_EAST)
self.show_all()
width, height = self.get_size()
self.move(gtk.gdk.screen_width() - width, gtk.gdk.screen_height() - height)
def on_delete_event(self, widget=None, data=None):
gtk.main_quit()
def open_sub_window(self, widget=None, data=None):
w = gtk.Window()
w.set_size_request(200,200)
w.set_transient_for(self)
w.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
w.show()
if __name__=="__main__":
MyWindow()
gtk.main()
As you can see, the sub_window shows up partially off-screen.
If you comment out the line w.set_position(gtk.WIN_POS_CENTER_ON_PARENT) you will see that the Windows window manager just places the subwindow at the very top left of the desktop. Not very useful!
Is there a way to get the desired behavior without resorting to manually managing Window positioning by checking what location the window ends up at and then moving the window to a fully off-screen position?
UPDATE:
I filed a bug report for pyGTK on Feb 23, 2011: http://bugzilla.gnome.org/show_bug.cgi?id=643138
It has not yet had any responses from the devs or other users. If you are having this problem please chime in on the bug so it gets fixed (or so that we might get a workaround).

Categories