Open a PyGTK program but do not activate it - python

I have a PyGTK program which is hidden most of the time, but with a keypress it shall come up as a popup. Therefore I want the program not to be activated when its opened. I tried several options to to that, with no success:
self.window.show()
self.window.set_focus(None)
Activates the program, but sets no focus.
self.window.set_accept_focus(False)
self.window.show()
self.window.set_accept_focus(True)
With the last command, the window gets activated.
self.window.show()
self.window.unset_flags(gtk.HAS_FOCUS)
Does nothing...
Btw. I am using Ubuntu 9.10 (metacity)

Build the window but don't call show() on it until it is ready to be activated. Then use self.window.present().
EDIT:
If you never want the window to be activated, why not try a notification popup? You need libnotify for this. There are Python bindings. Here is an example: http://roscidus.com/desktop/node/336
In combination with a toolbar applet, this could do what you want -- i.e. the notification is raised when the user either clicks on the applet or presses the key combination.

I figured out how to do it. See the example below:
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
import gobject
class HelloWorld:
window=None
def hello(self, widget, data=None, data2=None):
HelloWorld.window.set_accept_focus(True)
HelloWorld.window.present()
def __init__(self):
HelloWorld.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.button = gtk.Entry(50)
self.button.connect("focus-in-event", self.hello, None)
HelloWorld.window.add(self.button)
self.button.show()
HelloWorld.window.set_accept_focus(False)
self.button.connect('button-press-event', self.hello)
HelloWorld.window.show()
def main(self):
gtk.main()
if __name__ == "__main__":
hello = HelloWorld()
hello.main()

Related

Pyqt Terminal hangs after excuting close window command

I have read lots of threads online, but still I could not find the solution. My question should be very simple: how to close a Pyqt window WITHOUT clicking a button or using a timer.
The code I tried is pasted below
from PyQt4 import QtGui, QtCore
import numpy as np
import progressMeter_simple
import sys
import time
import pdb
class ProgressMeter(progressMeter_simple.Ui_Dialog, QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
progressMeter_simple.Ui_Dialog.__init__(self)
self.setupUi(self)
self.progressBar.setRange(0, 0)
QtGui.QApplication.processEvents()
def termination(self):
time.sleep(5)
self.close()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
Dialog = ProgressMeter()
Dialog.show()
Dialog.termination()
sys.exit(app.exec_())
My Pyqt GUI is designed using Qt designer, and it is nothing but a progress bar that keeps moving from left to right (busy indication).
However, when I run the code above, the terminal still hangs after the Pyqt window is closed. Ctrl+C also couldn't kill the process.
In short, how can I properly close/terminate a Pyqt window without clicking a button or using a timer?
It's not working because you're calling GUI methods on the dialog (close()) outside of the event loop. The event loop doesn't start until you call app.exec_().
If you really want to close the dialog immediately after it opens without using a QTimer, you can override the showEvent() method and call termination() from there, which gets called when the dialog is first displayed.
class ProgressMeter(progressMeter_simple.Ui_Dialog, QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
progressMeter_simple.Ui_Dialog.__init__(self)
self.setupUi(self)
self.progressBar.setRange(0, 0)
def showEvent(self, event):
super(ProgressMeter, self).showEvent(event)
self.termination()

Standalone Gtk.Menu popup not working without event.time

I'm trying to port a program I made with pygtk, it's a popup menu launched via global shortcut (using keybinder) to run specific programs and commands. There is no main window in this program, the point is have a simple, fast and light "launcher" available anywhere, whenever I need it.
The old menu.popup used to work even when using 0 as event.time (since keybinder doesn't give an event I'd request a time for), but now I'm getting this error:
Warning: The property GtkStatusIcon:stock is deprecated and shouldn't be used anymore. It will be removed in a future version.
self.icon.new_from_stock(Gtk.STOCK_OPEN)
This is an example I made up to show the problem:
from gi.repository import Gtk, Gdk
from gi.repository import Keybinder
menu_shortcut = "<Super>m"
class TestMenu:
def __init__(self):
self.menu = Gtk.Menu()
item = Gtk.MenuItem('various items')
self.menu.add(item)
item = Gtk.MenuItem('Quit')
item.connect('activate', Gtk.main_quit)
self.menu.append(item)
self.menu.show_all()
self.icon = Gtk.StatusIcon()
self.icon.new_from_stock(Gtk.STOCK_OPEN)
self.icon.set_tooltip_text('MyMenu')
self.icon.connect('popup-menu', self.popup, self.menu)
Keybinder.init()
Keybinder.bind(menu_shortcut, self.popup, 0, 0, self)
def popup(self, widget, button, time, menu):
self.menu.popup(None, None, None, None, button, time)
menu = TestMenu()
Gtk.main()
With this example I'm able to click the status icon and get the menu, but the keyboard shortcut just gives me the aforementioned error.
Note: the stock icon doesn't work, I'm still learning the new API.

Python Webkit-Browser: Problems on attaching the developer-toolbar

I want to dive in Python by building a simple browser-application. I've mad a minimalistic webkitbrowser with a tutorial and now want to extend the program, but I'm stuck at some tiny problems I cannot solve.
Python 3.3.3
using Glade for the UI
The first step is to simply add a second scrolledWindow in which the developer-tools should load, immediately.
Here is my .ui-file so far, and this is the python-code:
from gi.repository import Gtk, WebKit
UI_FILE = "browser.ui"
class Browser:
"""A simple Webkit-Browser in GTK+"""
def __init__(self):
self.builder = Gtk.Builder()
self.builder.add_from_file(UI_FILE)
self.builder.connect_signals(self)
self.back = self.builder.get_object("back")
self.forward = self.builder.get_object("forward")
self.adress = self.builder.get_object("adress")
self.webview = WebKit.WebView()
scrolled_window = self.builder.get_object("scrolledwindow")
scrolled_window.add(self.webview)
self.settings = WebKit.WebSettings()
self.settings.set_property('enable-developer-extras', True)
self.webview.set_settings(self.settings)
self.devtools = WebKit.WebInspector()
scrolled_window_dev = self.builder.get_object("scrolledwindowDev")
scrolled_window_dev.add(self.devtools)
^^^^^
self.webview.connect("title-changed", self.on_title_changed)
self.window = self.builder.get_object("window")
self.window.show_all()
def on_title_changed(self, webview, frame, title):
self.window.set_title(title)
def on_button_clicked(self, button):
if button.get_stock_id() == Gtk.STOCK_GO_FORWARD:
self.webview.go_forward()
elif button.get_stock_id() == Gtk.STOCK_GO_BACK:
self.webview.go_back()
def on_entry_activate(self, widget):
url = widget.get_text()
if not "http://" in url:
url = "http://"+url
self.webview.load_uri(url)
def destroy(self, window):
Gtk.main_quit()
def main():
app = Browser()
Gtk.main()
if __name__ == "__main__":
main()
I get the error
TypeError: argument widget: Expected Gtk.Widget, but got
gi.repository.WebKit.WebInspector
Okay, this is stated in the reference of Webkit, that WebInspector is a GObject and not a GtkWidget. But I don't know what to do now.
So, can I make a GtkWidget from a GObject (if yes - how) or should I attach the dev-tools in a complete different way?
The inspector, as you noted, isn't a widget. It's a web page, so you need to create another webview for it. You do this by getting self.window.props.web_inspector (don't create a new inspector) and connecting to its inspect-web-view signal. Inside that signal handler, you need to create a new webview, add that webview to a window or wherever you want to display it, and return it.
You'll probably also want to handle the show-window, attach-window, detach-window, and close-window signals.
More documentation here: inspect-web-view
Example of running Inspector in separate window. Webkit-gtk.
This gist without many signals connected.
https://gist.github.com/alex-eri/53518825b2a8a50dd1695c69ee5058cc

QDialog - Prevent Closing in Python and PyQt

I have a login screen dialog written using pyqt and python and it shows a dialog pup up when it runs and you can type in a certin username and password to unlock it basicly. It's just something simple I made in learning pyqt. I'm trying to take and use it somewhere else but need to know if there is a way to prevent someone from using the x button and closing it i would like to also have it stay on top of all windows so it cant be moved out of the way? Is this possible? I did some research and couldn't find anything that could help me.
Edit:
as requested here is the code:
from PyQt4 import QtGui
class Test(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
self.textUsername = QtGui.QLineEdit(self)
self.textPassword = QtGui.QLineEdit(self)
self.loginbuton = QtGui.QPushButton('Test Login', self)
self.loginbuton.clicked.connect(self.Login)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.textUsername)
layout.addWidget(self.textPassword)
layout.addWidget(self.loginbuton)
def Login(self):
if (self.textUsername.text() == 'Test' and
self.textPassword.text() == 'Password'):
self.accept()
else:
QtGui.QMessageBox.warning(
self, 'Wrong', 'Incorrect user or password')
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
if Test().exec_() == QtGui.QDialog.Accepted:
window = Window()
window.show()
sys.exit(app.exec_())
Bad news first, it is not possible to remove the close button from the window, based on the Riverbank mailing system
You can't remove/disable close button because its handled by the
window manager, Qt can't do anything there.
Good news, you can override and ignore, so that when the user sends the event, you can ignore or put a message or something.
Read this article for ignoring the QCloseEvent
Also, take a look at this question, How do I catch a pyqt closeEvent and minimize the dialog instead of exiting?
Which uses this:
class MyDialog(QtGui.QDialog):
# ...
def __init__(self, parent=None):
super(MyDialog, self).__init__(parent)
# when you want to destroy the dialog set this to True
self._want_to_close = False
def closeEvent(self, evnt):
if self._want_to_close:
super(MyDialog, self).closeEvent(evnt)
else:
evnt.ignore()
self.setWindowState(QtCore.Qt.WindowMinimized)
You can disable the window buttons in PyQt5.
The key is to combine it with "CustomizeWindowHint",
and exclude the ones you want to be disabled.
Example:
#exclude "QtCore.Qt.WindowCloseButtonHint" or any other window button
self.setWindowFlags(
QtCore.Qt.Window |
QtCore.Qt.CustomizeWindowHint |
QtCore.Qt.WindowTitleHint |
QtCore.Qt.WindowMinimizeButtonHint
)
Result with QDialog:
Reference: https://doc.qt.io/qt-5/qt.html#WindowType-enum
Tip: if you want to change flags of the current window, use window.show()
after window.setWindowFlags,
because it needs to refresh it, so it calls window.hide().
Tested with QtWidgets.QDialog on:
Windows 10 x32,
Python 3.7.9,
PyQt5 5.15.1
.
I don't know if you want to do this but you can also make your window frameless. To make window frameless you can set the window flag equal to QtCore.Qt.FramelessWindowHint

Python GTK window in Thread

I have a CLI application, which is digging some data, in case of need, fires up a thread which creates GTK window with some information. However the CLI (main thread) still analyzes the data in the background, so there could be numerous windows created. In case I close the window, the destroy event is actually fired up, I got a debug line in CLI, but the window locks up.
Some magical command that I have to use ?
I create window like this in the main thread:
gtk.gdk.threads_init()
notifyWindow = NotifyWindow()
notifyWindow.start()
This is NotifyWindow(Thread).destroy
def destroy(self, widget, data=None):
print "destroy signal occurred"
gtk.main_quit()
This is NotifyWindow(Thread).run
def run(self):
self.window = gtk.glade.XML( "hadinfo.glade" )
self.window_main = self.window.get_widget("window_main")
if (self.window_main):
self.window_main.connect("destroy", self.destroy)
self.window_main.connect("delete_event", self.delete_event)
self.button_cancel = self.window.get_widget("button_cancel")
self.button_cancel.connect("clicked", self.destroy)
self.window.get_widget("window_main").show()
gtk.main()
using a gtk.threads_enter() and leave around your main call should help.
Take a look at the PyGtk Faq : PyGtk FAQ

Categories

Resources