I want to check if the desktop of Windows 7 is shown (e.g. after clicking control+D or the showDesktop-Button).
It is meant for an application where I've set the QtCore.Qt.FramelessWindowHint to make the decorations disappear. After the desktop is shown and everything is minimized, I want to reshow the app (This should be optional and the user can set or unset this behaviour).
I tested this in IDLE. I want to detect a change if I show the desktop, but still there is the "1" printed. Only if I close(destroy) the window, it changes to "0", but thats not what I am searching for...
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import win32gui
import time
class Main(QWidget):
def __init__(self, app):
QtGui.QWidget.__init__(self)
self.app=app
self.window=QWidget()
self.window.resize(200,100)
self.window.setWindowTitle("Dummy")
#self.window.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.window.show()
self.check_Minimized_Thread=Worker(self)
self.check_Minimized_Thread.start()
self.app.exec_()
class Worker(QThread):
def __init__(self, parent = None):
QThread.__init__(self, parent)
self.exiting = False
def __del__(self):
self.exiting = True
self.wait()
def run(self):
while True:
time.sleep(0.5)
hwnd=win32gui.FindWindow(None,"Dummy")
A=win32gui.IsWindowVisible(hwnd)
print(A)
self.exit()
if __name__ == '__main__':
app=QApplication(sys.argv)
Main(app)
Related
So my expected outcome is for the login.ui to show when the login button is clicked. My code reached the def gotologin function and the class LoginScreen , but it doesn't load the ui
import sys
from PyQt5.uic import loadUi
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QDialog, QApplication
class WelcomeScreen(QDialog):
def __init__(self):
super(WelcomeScreen, self).__init__()
loadUi('welcomescreen.ui', self)
self.login.clicked.connect(self.gotologin)
def gotologin(self):
login = LoginScreen()
widget.addWidget(login)
widget.setCurrentIndex(widget.currentIndex()+1)
class LoginScreen(QDialog):
def __init__(self):
super(LoginScreen, self).__init__()
loadUi('login.ui', self)
app = QApplication(sys.argv)
welcome = WelcomeScreen()
widget = QtWidgets.QStackedWidget()
widget.addWidget(welcome)
widget.setFixedHeight(800)
widget.setFixedWidth(1200)
window = WelcomeScreen()
window.show()
try:
sys.exit(app.exec_())
except:
print('Exiting')
Your logic is strange since you are creating 2 WelcomeScreen: One added to the QStackedWidget and the second as a window. Besides that, the QStackedWidget has never been shown. And as the icing on the cake you don't limit the scopes of the variables.
Considering the above, it is better to create a controller that implements the logic of switching widgets and limits scopes.
import sys
from functools import cached_property
from PyQt5.uic import loadUi
from PyQt5.QtWidgets import QApplication, QDialog, QStackedWidget
class WelcomeScreen(QDialog):
def __init__(self):
super(WelcomeScreen, self).__init__()
loadUi("welcomescreen.ui", self)
class LoginScreen(QDialog):
def __init__(self):
super(LoginScreen, self).__init__()
loadUi("login.ui", self)
class Controller:
def __init__(self):
self.stacked_widget.addWidget(self.welcome)
self.stacked_widget.addWidget(self.login)
self.welcome.login.clicked.connect(self.goto_login)
#cached_property
def stacked_widget(self):
return QStackedWidget()
#cached_property
def welcome(self):
return WelcomeScreen()
#cached_property
def login(self):
return LoginScreen()
def goto_login(self):
self.stacked_widget.setCurrentWidget(self.login)
def main(args):
app = QApplication(args)
controller = Controller()
controller.stacked_widget.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main(sys.argv)
And finally, do not silence the exceptions since their reason for being is to indicate that something is wrong. I prefer that when the program fails then it shouts at me that a silent error since the latter is the cause of many bugs.
I am programming a simple GUI, that will open a opencv window at a specific point. This window has some very basic keyEvents to control it. I want to advance this with a few functions. Since my QtGui is my Controller, I thought doing it with the KeyPressedEvent is a good way. My Problem is, that I cannot fire the KeyEvent, if I am active on the opencv window.
So How do I fire the KeyEvent, if my Gui is out of Focus?
Do I really need to use GrabKeyboard?
The following code reproduces my Problem:
import sys
from PyQt5.QtWidgets import (QApplication, QWidget)
from PyQt5.Qt import Qt
import cv2
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.first = True
def openselect(self):
im = cv2.imread(str('.\\images\\Steine\\0a5c8e512e.jpg'))
self.r = cv2.selectROI("Image", im)
def keyPressEvent(self, event):
if event.key() == Qt.Key_Space and self.first:
self.openselect()
self.first = False
print('Key Pressed!')
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
The keyPressEvent method is only invoked if the widget has the focus so if the focus has another application then it will not be notified, so if you want to detect keyboard events then you must handle the OS libraries, but in python they already exist libraries that report those changes as pyinput(python -m pip install pyinput):
import sys
from PyQt5 import QtCore, QtWidgets
from pynput.keyboard import Key, Listener, KeyCode
class KeyMonitor(QtCore.QObject):
keyPressed = QtCore.pyqtSignal(KeyCode)
def __init__(self, parent=None):
super().__init__(parent)
self.listener = Listener(on_release=self.on_release)
def on_release(self, key):
self.keyPressed.emit(key)
def stop_monitoring(self):
self.listener.stop()
def start_monitoring(self):
self.listener.start()
class MainWindow(QtWidgets.QWidget):
pass
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
monitor = KeyMonitor()
monitor.keyPressed.connect(print)
monitor.start_monitoring()
window = MainWindow()
window.show()
sys.exit(app.exec_())
I am new in multi threading. The video file I use work fine and the progress-bar at the start shows a percent in progress-bar. When I want to change the progress-bar value continuously for example the current cpu usage value the below code keeps crashing when i run the code. Why is the code not working??
I think the problem is emit and connect. If so what can i do? And how do I correct this? Thanks in advance for the help.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QObject, pyqtSignal
import sysinfo
from multi import Ui_Form
class main(QtWidgets.QWidget ,Ui_Form):
cpu_value = pyqtSignal()
def __init__(self, parent = None):
super(main,self).__init__(parent)
self.setupUi(self)
self.threadclass = ThreadClass()
self.threadclass.start()
self.cpu_value.connect(self.updateProgressBar)
def updateProgressBar(self):
val = sysinfo.getCPU()
self.progressBar.setValue(val)
class ThreadClass(QtCore.QThread):
def __init__(self, parent = None):
super(ThreadClass,self).__init__(parent)
def run(self):
while 1:
val = sysinfo.getCPU()
self.cpu_value.emit(val)
if __name__ == '__main__':
a = QtWidgets.QApplication(sys.argv)
app = main()
app.show()
a.exec_()
env: python3.5 + pyqt5.9
I use a timer to update the CPU info like that:
#!/usr/bin/python3
# 2017.12.10 13:20:11 CST
# 显示 CPU
import sys
from PyQt5 import QtCore, QtWidgets
import psutil
class CPU(QtWidgets.QProgressBar):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("CPU Info")
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(lambda : self.setValue(psutil.cpu_percent()))
self.timer.start(1000)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
win = CPU()
win.show()
app.exec_()
I am running into an issue when I am taking in values over serial and then attempting to update my Gui with those values. Unfortunately, even though the values update correctly, I am unable to get to the screen to refresh unless I click off of it and then back on to it. I have tried repaint, update, and processEvents() but have been unable to solve the problem.
Here is the code I am working with:
import sys
import serial
import time
import requests
import PyQt5
from PyQt5.QtWidgets import *
from PyQt5.QtCore import*
from PyQt5.QtGui import *
import mainwindow_auto
CUSTOM_EVENT = 1000
ser = serial.Serial('/dev/ttyACM0', 9600)
class TestThread(QThread):
def __init__(self, target):
QThread.__init__(self)
self.target = target
def run(self):
while True:
QApplication.postEvent(self.target, QEvent(QEvent.Type(CUSTOM_EVENT)))
QApplication.processEvents()
QThread.sleep(15)
class MainWindow(QMainWindow, mainwindow_auto.Ui_MainWindow):
def __init__(self):
super(self.__class__, self).__init__()
self.setupUi(self)# gets defined in the UI file
self.thread = TestThread(self)
self.thread.start()
def event(s, e):
if(e.type() == CUSTOM_EVENT):
print("Readline: ",int(ser.readline()))
SOC = int(ser.readline())
s.lcdNumber.display(SOC)
s.progressBar.setValue(SOC)
print("SOC: ",SOC)
print(s.lcdNumber.value())
return True
def main():
app = QApplication(sys.argv)
form = MainWindow()
form.lcdNumber.display(30)
form.progressBar.setValue(30)
form.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Thanks in advance!
Since you already have an I/O thread, let it handle the I/O and sent the received value to the main thread via a signal.
No need for a custom event, no I/O on the main thread.
Just adding a signal to the thread subclass and connecting a slot to that before starting the thread.
Rather than rewriting the code that I had above, I ended up fixing it by force redrawing using s.hide() and s.show() after updating the values in the event code. It forced a redraw that otherwise refused to work.
s.lcdNumber.display(SOC)
s.progressBar.setValue(SOC)
s.hide()
s.show()
As suggested by #KevinKrammer, this is simple to do with a custom signal:
class TestThread(QThread):
serialUpdate = pyqtSignal(int)
def run(self):
while True:
QThread.sleep(1)
value = int(ser.readline())
self.serialUpdate.emit(value)
class MainWindow(QMainWindow, mainwindow_auto.Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
self.thread = TestThread(self)
self.thread.serialUpdate.connect(self.handleSerialUpdate)
self.thread.start()
def handleSerialUpdate(self, value):
print("Readline: ", value)
self.lcdNumber.display(value)
self.progressBar.setValue(value)
There is an endless block when xml.etree.ElementTree.fromstring() function is called in the QThread. Also lots of other calls makes the QThread blocked like multiprocessing.Process().
Important to say that it is a pure block, no exception or break.
Here is the code (a little edited but same principle as the source):
from PyQt4.QtGui import *
from Ui_mainwindow import Ui_MainWindow
import sys
import xml.etree
class Bruton(QThread):
def __init__(self, mw):
super(Bruton, self).__init__(mw)
self.mw = mw
def run(self):
print("This message I see.")
tree = xml.etree.ElementTree.fromstring("<element>text</element>")
print("But this one never.")
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.init_bruton()
# When the form is shown...
def showEvent(self, arg1):
self.bruton.start()
def init_bruton(self):
self.bruton = Bruton(self)
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
The code as posted doesn't actually run, but with a couple minor changes it runs and works fine. Here is the code with modifications:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
import xml.etree.ElementTree
class Bruton(QThread):
def __init__(self, mw):
super(Bruton, self).__init__(mw)
self.mw = mw
def run(self):
print("This message I see.")
tree = xml.etree.ElementTree.fromstring("<element>text</element>")
print("But this one never.")
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.init_bruton()
# When the form is shown...
def showEvent(self, arg1):
self.bruton.start()
def init_bruton(self):
self.bruton = Bruton(self)
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
And here is the output:
$ python test.py
This message I see.
But this one never.
This is with Python 2.6.6, PyQt4 4.8.3, on Debian Unstable.
Can you try it in your environment and see if my modified example works for you? If so, you are on the road to a solution for your real code. =)
The code I've shown here is shortened (the source is divided to two files and __ini__.py). I noticed that the main module must be the module that starts the QApplication. So I added app.exec_() to the __init__.py which is the main module of my program.