I use KDE on Manjaro linux. I have this script in python to turn off touchpad:
#!/usr/bin/python
import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
from PyQt5.QtCore import QCoreApplication
from subprocess import call
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
qbtn = QPushButton('On', self)
qbtn.clicked.connect(self.handleButtonOn)
qbtn.resize(qbtn.sizeHint())
qbtn.move(25, 50)
qbtn = QPushButton('Off', self)
qbtn.clicked.connect(self.handleButtonOff)
qbtn.resize(qbtn.sizeHint())
qbtn.move(125, 50)
self.setGeometry(300, 300, 250, 100)
self.setWindowTitle('Touchpad On/Off')
self.show()
def handleButtonOn(self, event):
print ('On')
call(["synclient", "touchpadoff=0"])
call(["notify-send", "Your touchpad is set to ON"])
self.destroy()
def handleButtonOff(self, event):
print ('Off')
call(["synclient", "touchpadoff=1"])
call(["notify-send", "Your touchpad is set to OFF"])
self.destroy()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
It's works almost perfect (turn off my touchpad) but when I start script it's turn off my power button so I can't turn off computer by this button.
There is a problem with Yakuake too, can't write in this terminal. Finally i've start some other terminal for example "konsole" and turn off computer by shutdown command.
I'm new in python. How to make this work OK. I need turn off my touchpad, I use external mouse.
I can't reproduce your issue with power button, but I found out that self.destroy() is causing your script to freeze in some corrupted-not-responding-to-SIGINT state. Replacing self.destroy() with self.close() makes it work on my machine.
Please try replacing self.destroy() with self.close().
Related
Using PyQt5, I want to implement a two windows displaying one after another automatically, without the user interacting with any window. Something like this:
While True:
Show Window1
wait 2 seconds
Close Window1
Show Window2
wait 2 seconds
Close Window2
The problem I am having is that the main UI thread is stuck in app.exec_() function, so it cannot implement the opening and closing logic.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
class Win1(QMainWindow):
def __init__(self):
super(Win1, self).__init__()
uic.loadUi('win1.ui', self)
self.show()
class Win2(QMainWindow):
def __init__(self):
super(Win2, self).__init__()
uic.loadUi('win2.ui', self)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
while True:
win = Win1()
time.sleep(1)
win.close()
win = Win2()
time.sleep(1)
win.close()
app.exec_() # <--------- Program blocks here
I would appreciate if someone can share a minimal example for this working without blocking. Or please point to the mechanism that should be used.
If you are going to work with Qt then you should forget about sequential logic but you have to implement the logic using events. For example, in your case you want one window to be shown every time T and another to be hidden, so that can be implemented with a QTimer and a flag:
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import uic
class Win1(QMainWindow):
def __init__(self):
super(Win1, self).__init__()
uic.loadUi('win1.ui', self)
self.show()
class Win2(QMainWindow):
def __init__(self):
super(Win2, self).__init__()
uic.loadUi('win2.ui', self)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
timer = QTimer()
timer.setProperty("flag", True)
win1 = Win1()
win2 = Win2()
def on_timeout():
flag = timer.property("flag")
if flag:
win1.show()
win2.close()
else:
win2.show()
win1.close()
timer.setProperty("flag", not flag)
timer.timeout.connect(on_timeout)
timer.start(1 * 1000)
on_timeout()
app.exec_()
You should not use while loop or time.sleep since they block the eventloop in which the GUI lives, that is: they freeze the windows
I try to change cursor icon when the Ctrl button is pressed. The problem is, that if you press and hold down a button, the keyPressEvent method is not called. If you press two buttons at once, e.g. Ctrl+Shift, then it works as expected.
Test environment: system SUSE 12.2, python 3.6.4, pyqt5 5.11.3 (also tested pyqt5 5.9.2).
This is a minimal (not)working example:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import QApplication, QWidget
class Example(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(300, 300, 300, 220)
self.show()
def keyPressEvent(self, event):
print('Press')
def keyReleaseEvent(self, event):
print('Release')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Once pressing and holding Ctrl button, the 'Press' should be printed. However, it is not until you release the button or click another one simultaneously.
I noticed different behavior for different keys. Both left and right Ctrl behave the same, also the left Shift, but the right Shift behaves as desired.
def keyPressEvent(self, event):
print('Press')
QApplication.setOverrideCursor(Qt.WaitCursor)
def keyReleaseEvent(self, event):
print('Release')
QApplication.restoreOverrideCursor()
I am trying to write a simple menu driven GUI program.
Following are the environment:
PyQt5 ver.5.10.1
Python 3.6.4
Mac OS Sierra
PyQt5 was installed using pip3.
Here is the code I am using:
from PyQt5.QtWidgets import (QMainWindow, QApplication,
QWidget, QPushButton, QAction)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class myApp(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'Some App'
self.left = 10
self.top = 10
self.width = 480
self.height = 260
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.statusBar()
pkMenuBar = self.menuBar()
mnuFile = pkMenuBar.addMenu("File")
mnuFile.addAction("Create New")
mnuQuit = QAction(QIcon("ico1.png"), " Quit", self)
mnuQuit.setShortcut("Ctrl+Q")
mnuQuit.setStatusTip("Quit Application")
mnuFile.addAction(mnuQuit)
mnuFile.triggered[QAction].connect(self.triggerAct)
self.show()
def triggerAct(self, x):
if x.text() == "Create New":
print("Trigger Create New...")
elif x.text() == " Quit":
mnuQuit.triggered.connect(self.close)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
ex = myApp()
sys.exit(app.exec_())
On executing the code (using IDLE) the GUI loads and the menu items (Actions) are also working as expected.
When the menu item "Quit" is called the app closes as well as the python icon (from the system tray). But after about 5-10 seconds I keep getting a message saying "Python quit unexpectedly".
I have been trying to figure out the problem using possible solns. by following leads on the net (like sys.exit(), app.quit() ) but every time I face the same result.
I have coding experience on ABAP/4 and VB.Net but this is very early stages for me so far as GUI coding on Python/PyQt is concerned.
Will appreciate if a lead is provided so that I may progress in this new endeavor of mine.
Thanks
The problem is really simple: mnuQuit is a variable not a member of the class so it can not be accessed by other methods of the class, plus I see it unnecessary to use that line of code, just call close():
def triggerAct(self, x):
if x.text() == "Create New":
print("Trigger Create New...")
elif x.text() == " Quit":
self.close()
# mnuQuit.triggered.connect(self.close)
It is not appropriate to call exit() within the GUI because the GUI has to free memory and if you call exit() it does not give you the time to do it. with close() the GUI closes correctly.
def triggerAct(self, x):
if x.text() == "Create New":
print("Trigger Create New...")
elif x.text() == " Quit":
exit()
I think exit() will work fine in your case.
Could you please explain why the quit push button does not work properly in this case:
import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
from PyQt5.QtCore import QCoreApplication
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
qbtn = QPushButton('Quit', self)
qbtn.clicked.connect(QCoreApplication.instance().quit)
qbtn.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.show()
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
But works if I include the last three lines in a function:
def fun():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
fun()
I don't understand the mechanics :(
I ran into the same problem while using linux. This code comes from a tutorial
on zetcode.com for PyQt5 in the quitButton.py file. Here is the solution that I found works:
Instead of using:
qbtn.clicked.connect(QCoreApplication.instance().quit)
Replace it with this:
qbtn.clicked.connect(self.close)
After this, you shouldn't need to call it in a separate function. Hope this helps!
I tried this recently. I need a sure exit from within spyder and this always seems a problem with pyqt. I found
qbtn.clicked.connect(QCoreApplication.instance().quit) will quit and leave window open.
qbtn.clicked.connect(self.close) will close the window but leave the process running.
qbtn.clicked.connect(QCoreApplication.instance().quit) and
qbtn.clicked.connect(self.close) sequentially will quit and close window.
This is pyqt5 on Python 3.8.8. Hope this is helpful.
Is there a way to minimize to tray in PyQt4? I've already worked with the QSystemTrayIcon class, but now I would like to minimize or "hide" my app window, and show only the tray icon.
Has anybody done this? Any direction would be appreciated.
Using Python 2.5.4 and PyQt4 on Window XP Pro
It's pretty straightforward once you remember that there's no way to actually minimize to the system tray.
Instead, you fake it by doing this:
Catch the minimize event on your window
In the minimize event handler, create and show a QSystemTrayIcon
Also in the minimize event handler, call hide() or setVisible(false) on your window
Catch a click/double-click/menu item on your system tray icon
In your system tray icon event handler, call show() or setVisible(true) on your window, and optionally hide your tray icon.
Code helps, so here's something I wrote for an application, except for the closeEvent instead of the minimize event.
Notes:
"closeEvent(event)" is an overridden Qt event, so it must be put in the class that implements the window you want to hide.
"okayToClose()" is a function you might consider implementing (or a boolean flag you might want to store) since sometimes you actually want to exit the application instead of minimizing to systray.
There is also an example of how to show() your window again.
def __init__(self):
traySignal = "activated(QSystemTrayIcon::ActivationReason)"
QtCore.QObject.connect(self.trayIcon, QtCore.SIGNAL(traySignal), self.__icon_activated)
def closeEvent(self, event):
if self.okayToClose():
#user asked for exit
self.trayIcon.hide()
event.accept()
else:
#"minimize"
self.hide()
self.trayIcon.show() #thanks #mojo
event.ignore()
def __icon_activated(self, reason):
if reason == QtGui.QSystemTrayIcon.DoubleClick:
self.show()
Just to add to the example by Chris:
It is crucial that you use the Qt notation when declaring the signal, i.e.
correct:
self.connect(self.icon, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.iconClicked)
and not the PyQt one
incorrect and won't work:
self.connect(self.icon, SIGNAL("activated(QSystemTrayIcon.ActivationReason)"), self.iconClicked)
Note the :: in the signal string. This took me about three hours to figure out.
Here's working code..Thanks Matze for Crucial, the SIGNAL took me more hours of curiosity.. but doing other things. so ta for a #! moment :-)
def create_sys_tray(self):
self.sysTray = QtGui.QSystemTrayIcon(self)
self.sysTray.setIcon( QtGui.QIcon('../images/corp/blip_32.png') )
self.sysTray.setVisible(True)
self.connect(self.sysTray, QtCore.SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.on_sys_tray_activated)
self.sysTrayMenu = QtGui.QMenu(self)
act = self.sysTrayMenu.addAction("FOO")
def on_sys_tray_activated(self, reason):
print "reason-=" , reason
This was an edit of vzades response, but it was rejected on a number of grounds. It does the exact same thing as their code but will also obey the minimize event (and run without syntax errors/missing icons).
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
style = self.style()
# Set the window and tray icon to something
icon = style.standardIcon(QtGui.QStyle.SP_MediaSeekForward)
self.tray_icon = QtGui.QSystemTrayIcon()
self.tray_icon.setIcon(QtGui.QIcon(icon))
self.setWindowIcon(QtGui.QIcon(icon))
# Restore the window when the tray icon is double clicked.
self.tray_icon.activated.connect(self.restore_window)
def event(self, event):
if (event.type() == QtCore.QEvent.WindowStateChange and
self.isMinimized()):
# The window is already minimized at this point. AFAIK,
# there is no hook stop a minimize event. Instead,
# removing the Qt.Tool flag should remove the window
# from the taskbar.
self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.Tool)
self.tray_icon.show()
return True
else:
return super(Example, self).event(event)
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(
self,
'Message',"Are you sure to quit?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
self.tray_icon.show()
self.hide()
event.ignore()
def restore_window(self, reason):
if reason == QtGui.QSystemTrayIcon.DoubleClick:
self.tray_icon.hide()
# self.showNormal will restore the window even if it was
# minimized.
self.showNormal()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This is the correct way to handle double click on a tray icon for PyQt5.
def _create_tray(self):
self.tray_icon = QSystemTrayIcon(self)
self.tray_icon.activated.connect(self.__icon_activated)
def __icon_activated(self, reason):
if reason in (QSystemTrayIcon.Trigger, QSystemTrayIcon.DoubleClick):
pass
This is the code and it does help i believe in show me the code
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import QDialog, QApplication, QPushButton, QLineEdit, QFormLayout, QSystemTrayIcon
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.icon = QSystemTrayIcon()
r = self.icon.isSystemTrayAvailable()
print r
self.icon.setIcon(QtGui.QIcon('/home/vzades/Desktop/web.png'))
self.icon.show()
# self.icon.setVisible(True)
self.setGeometry(300, 300, 250, 150)
self.setWindowIcon(QtGui.QIcon('/home/vzades/Desktop/web.png'))
self.setWindowTitle('Message box')
self.show()
self.icon.activated.connect(self.activate)
self.show()
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message', "Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
self.icon.show()
self.hide()
event.ignore()
def activate(self, reason):
print reason
if reason == 2:
self.show()
def __icon_activated(self, reason):
if reason == QtGui.QSystemTrayIcon.DoubleClick:
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()