Python GTK - Pass mouse click to window below - python

I am creating an Ubuntu program that creates a transparent popup window. I would like it to act similarly to the notify-osd popups. When the mouse hovers over the window it fades even more. When the user click the dialog, the event is sent to the window underneath so the user clicks through the popup.
How can I achieve this using Gtk from gi.repository?

Try this:
from gi.repository import Gtk, Gdk
w1 = Gtk.Window()
w2 = Gtk.Window()
def w2_hide(widget, event):
w2.set_opacity(0.25)
def w2_show(widget, event):
w2.set_opacity(0.75)
def w2_click(widget, event):
w2.hide()
w1.set_size_request(600, 400)
w2.set_transient_for(w1)
w2.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
w1.show()
w2.show()
w2_show(w2, None)
w1.connect("destroy", Gtk.main_quit)
w2.connect("leave-notify-event", w2_hide)
w2.connect("enter-notify-event", w2_show)
w2.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
w2.connect("button-press-event", w2_click)
Gtk.main()

Related

Can a Gtk.Entry (part of a Gtk.SpinButton) "have-focus" if it's in a Gtk.Menu?

I'm making an application that can change certain parameters through a Gtk.Menu. I have a Gtk.MenuButton that pops down a Gtk.Menu with other submenus in it. One of those submenus has Gtk.MenuItems with Gtk.SpinButtons in them. I have gotten the Gtk.SpinButtons to receive input by bringing their associated Gdk.Windows to the front of the Z-order with Gdk.Window.show(), but I can't get the Gtk.Entry part of the Gtk.SpinButton to receive keyboard focus.
I have tried to use Gtk.Widget.grab_focus() and other related methods to no avail. It does highlight the Gtk.Entry text, and I can type in new text, but if I click away or press enter, it doesn't actually update/change the Gtk.SpinButton value. I have connected to the "change-value" and "value-changed" signals but typing anything into the Gtk.SpinButton doesn't fire them.
I've found out that a widget can be the "focus widget" but not have the "global input focus" if its toplevel Gtk.Window doesn't also have the global focus. Therefore, I'm stuck. Is there any way around this? Can I make the Gtk.SpinButton entry field have the keyboard focus if it's in a Gtk.Menu?
Here is a minimal example:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
class Menu(Gtk.Menu):
def __init__(self):
Gtk.Menu.__init__(self)
menu_item = Gtk.MenuItem(label="Submenu")
menu_item2 = Gtk.MenuItem(label="Item")
self.append(menu_item)
self.append(menu_item2)
submenu = Gtk.Menu()
sub_mi = Gtk.MenuItem()
spin_button = Gtk.SpinButton()
spin_adj = Gtk.Adjustment(value=0,lower=0, upper=10, step_increment=1)
spin_button.set_adjustment(spin_adj)
sub_mi.add(spin_button)
submenu.append(sub_mi)
menu_item.set_submenu(submenu)
spin_button.connect("realize", self.on_realize)
spin_button.connect("map-event", self.on_map_event)
submenu.connect("button-release-event", self.on_button_release)
submenu.connect("enter-notify-event", self.on_enter)
self.show_all()
def on_realize(self, spin_button):
spin_button.add_events(Gdk.EventMask.STRUCTURE_MASK)
def on_map_event(self, spin_button, event):
for win in spin_button.get_window().get_children():
win.show()
def on_button_release(self, menu, event):
return True
def on_enter(self, menu, event):
mouse = event.get_device()
mouse.ungrab(event.time)
win = Gtk.Window()
win.set_default_size(100, 20)
win.connect("destroy", Gtk.main_quit)
mb = Gtk.MenuButton()
win.add(mb)
menu = Menu()
mb.set_popup(menu)
win.show_all()
Gtk.main()
I realize this is convoluted, and there's probably a better solution (like not using a Gtk.Menu for this...), but I've come up with a workaround anyway.
Since I can't activate or fully focus the Gtk.SpinButton I am just forcing it to update the text field whenever there is a leave-notify-event fired from it.
spin_button.connect("leave-notify-event", self.on_leave)
def on_leave(self, spin_button, event):
value = spin_button.get_text()
spin_button.set_value(float(value))
spin_button.update()

In python code using gtk and glade: How to handle a click on the screen if buttons are also there?

for example if you have a an image, button, and a label. If you don't click the button or anywhere on the screen/window in 10 seconds, then hide the button and the label. If you click the screen/window then it shows the button and label and resets
thanks to Gonzalo Odiard's suggest the issue now is only: How to handle a click on the screen with python gtk if buttons are also there? (how to call custom method "eventListener()" if screen is clicked)
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GLib
def button_pressed():
global clicked
clicked = 0
def eventListener():
global clicked
clicked = 0
btn.set_visible(True)
lbl.set_visible(True)#set visible
def hide():
global clicked
if(clicked >=10):
btn.set_visible(False) #set invisible
lbl.set_visible(False)
else:
clicked += 1
GLib.timeout_add_seconds(1, hide)
def callback(window, event):
global countToHide
countToHide = 0
btn.set_visible(True)
lbl.set_visible(True)
width, height= pyautogui.size()
builder = Gtk.Builder()
builder.add_from_file("main.glade")#this gets glade class for GUI
win = builder.get_object("Main_Page")#this sets screen/window to var for display later
global clicked
clicked = 0
btn= builder.get_object("button")#get object button from glade
btn.connect("clicked",button_pressed)#handle events of glade button
lbl= builder.get_object("label")#get Label from glade
#initialize event listener for if screen/window is clicked
#?how to do this
#call method if 10 second go by with out anything being clicked
#this method below
#hide()
GLib.timeout_add_seconds(10, hide)
win.connect('button-press-event', callback)
win.show() #show GUI
Gtk.main()

Why does the destroy signal not reach the children of a Gtk.ScrolledWindow?

Please consider this python code for a simple GTK window:
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
def on_destroy(widget):
print("Destroying {}".format(widget))
def on_click(button, scroll):
scroll.destroy()
scroll = Gtk.ScrolledWindow()
scroll.connect("destroy", on_destroy)
button = Gtk.Button.new_with_label("Self-destruct")
scroll.add(button)
button.connect("destroy", on_destroy)
button.connect("clicked", on_click, scroll)
window = Gtk.Window()
window.add(scroll)
window.connect("destroy", Gtk.main_quit)
window.set_size_request(200, 75)
window.show_all()
Gtk.main()
When pressing the button, I would expect to get two output lines reporting that the ScrolledWindow and the button got destroyed. In reality I only get one line reporting about the ScrolledWindow, the destroy signal never reaches the button. If I replace the ScrolledWindow with a normal Box, the destroy signal reaches the button. Why is this?
I really can't tell you much more than this code which does delete the button. Hopefully, you can adapt it to your needs. It does seem like the button unattaches itself from the Viewport and attaches itself to nothing, because the button's destroy handler runs on app shutdown, and causes weird errors. It would be interesting to post this on the Gtk mailing list for any other thoughts.
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
def on_destroy(widget, viewport):
print("Destroying {}".format(widget))
viewport.get_child().destroy()
def on_button_destroy(widget):
print("Destroying button {}".format(widget))
def on_click(button):
scroll = button.get_parent().get_parent()
scroll.destroy()
scroll = Gtk.ScrolledWindow()
button = Gtk.Button.new_with_label("Self-destruct")
scroll.add(button)
viewport = button.get_parent()
button.connect("destroy", on_button_destroy)
scroll.connect("destroy", on_destroy, viewport)
button.connect("clicked", on_click)
window = Gtk.Window()
window.add(scroll)
window.connect("destroy", Gtk.main_quit)
window.set_size_request(200, 75)
window.show_all()
Gtk.main()

Have a popup window stay centered on parent - Glade, GTK, Python

Can anyone tell me how I can have a preference pop-up stay centered on parent window even while moving the parent window? Thank you :)
Here is a very simple example, the preference window is centered and while moving it the parent will also move (but will depend on window manager):
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class AppWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Python Example")
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,spacing=6)
self.add(box)
button1 = Gtk.Button("Information")
button1.connect("clicked", self.on_button_clicked)
box.add(button1)
treeview = Gtk.TreeView()
treeview.set_size_request(640,480)
box.add(treeview)
def on_button_clicked(self, widget):
preferences_window = Gtk.Window (Gtk.WindowType.TOPLEVEL)
preferences_window.set_title ("Preferences Window")
preferences_window.set_modal (True)
preferences_window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
preferences_window.set_transient_for(self)
preferences_window.show_all()
preferences_window.connect("delete-event", preferences_window.destroy);
win = AppWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
Resulting in:

pygobject creating a drag and drop source

from gi.repository import Gtk, Gdk
def drag_data_get_cb(widget, drag_context, selection_data, info, time):
print selection_data.get_data_type()
print widget.get_text()
return widget.get_text()
def drag_begin_cb(widget, dragcontext):
print dragcontext, widget
return dragcontext
label = Gtk.Label()
label.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [], Gdk.DragAction.COPY)
label.set_text("Drag Me!")
label.connect("drag_data_get", drag_data_get_cb)
label.connect("drag_begin", drag_begin_cb)
window = Gtk.Window()
window.add(label)
window.connect("delete_event", Gtk.main_quit)
window.set_default_size(300, 250)
window.show_all()
Gtk.main()
ive been hitting my head against a wall over this for a few days now,
can anyone tell me why this doesnt allow me to drag text into other widgets? neither of the drag events fire at all
It says in this tutorial that you cannot use widgets without windows, such as Gtk.Label as drag and drop sources. You can replace the label with a button for instance:
label = Gtk.Button.new_with_label("Drag Me!")
in order for this example to work.

Categories

Resources