I'm trying to create a simple UI that has the functionality to close when I use the shortcut Ctrl+Q or when I use the Exit into the File menu, to make it clearer I've created a fairly simple UI that goes with the code:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, qApp
class MGen(QMainWindow):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
exit_action = QAction('Exit', self)
exit_action.setShortcut('Ctrl+Q')
exit_action.triggered.connect(qApp.quit)
menu_bar = self.menuBar()
file_menu = menu_bar.addMenu('&File')
file_menu.addAction(exit_action)
self.setGeometry(0, 0, 500, 500)
self.setWindowTitle('MGen')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
mgen = MGen()
sys.exit(app.exec_())
Could anyone point what I'm doing wrong?
Related
Force repainting does not repaint PyQt5 widget (Qlabel, QTextEdit, even QProgressBar and etc)
Tested platforms: Linux, MacOS
PyQt5 version: 5.15.7
Installed from pip
As example I created simple app that updating text in QLabel widget in for loop. Force repainting doesnt working
import sys
from time import sleep
from PyQt5.QtWidgets import (QWidget, QApplication, QPushButton, QLabel)
class Example(QWidget):
def __init__(self):
super().__init__()
self.text = QLabel('Test', self)
self.text.move(10, 10)
self.text.resize(60,20)
self.button = QPushButton('Run', self)
self.button.move(17,40)
self.button.clicked.connect(self.some_activity)
self.setGeometry(300, 300, 100, 80)
self.show()
def some_activity(self):
for i in range(100):
text = f'i = {i}'
self.text.setText(text)
# self.text.update() -> Nothing happens (it shouldnt: https://doc.qt.io/qt-5/qwidget.html#update)
self.text.repaint() # -> Nothing happens
self.repaint() # -> Nothing happens
print(f'Text updated: {text}')
sleep(0.03)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Video demonstration: link
Just needed to use QThread to use for loop in my program
Thanks #musicamante for helping.
import sys
from time import sleep
from PyQt5 import QtCore
from PyQt5.QtWidgets import (QWidget, QApplication, QPushButton, QLabel)
class Thread(QtCore.QThread):
signal = QtCore.pyqtSignal(str)
def __init__(self, parent=None): QtCore.QThread.__init__(self, parent)
def run(self):
for i in range(100):
text = f'i = {i}'
print(f'Text updated: {text}')
self.signal.emit(text)
sleep(.3)
class Example(QWidget):
def __init__(self):
super().__init__()
self.text = QLabel('Test', self)
self.text.move(10, 10)
self.text.resize(60,20)
self.thread = Thread()
self.thread.signal.connect(self.signal, QtCore.Qt.QueuedConnection)
self.button = QPushButton('Run', self)
self.button.move(17,40)
self.button.clicked.connect(self.thread.start)
self.setGeometry(300, 300, 100, 80)
self.show()
def signal(self, text): self.text.setText(text)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
so I'm currently working on a little project but I have an issue and all what I've tried did not work. I have 2 files :
Page1test :
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QWidget, QLabel
import sys
from page2test import Page2
class Page1(QWidget):
def __init__(self):
super(Page1, self).__init__()
self.setWindowTitle("Page 1")
label1 = QLabel(self)
label1.setText("\n PAGE 1")
self.btn_inMyApp = QPushButton ('Next page', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage1_OpenPage2)
self.show()
def closePage1_OpenPage2(self):
self.Open = Page2()
self.Open.showMaximized()
self.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = Page1()
window.showMaximized()
sys.exit(app.exec_())
And page2test :
from PyQt5.QtWidgets import QPushButton, QWidget, QLabel
from Page1test import Page1
class Page2(QWidget):
def __init__(self):
super(Page2, self).__init__()
self.setWindowTitle("Test window principale")
label1 = QLabel(self)
label1.setText("\n Page2")
self.btn_inMyApp = QPushButton ('previous Page', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage2_OpenPage1)
self.show()
def closePage2_OpenPage1(self):
self.Open = Page1()
self.Open.showMaximized()
self.close()
I run the code of Page1test : empty window with just a Qpushbutton "Next Page", goal : we click on it and it open Page 2 (and close Page 1). And, when we are in Page 2, we have A Qpushbutton with "Previous Page" and when we click on it, it opens page 1, and close Page 2. Like a loop.
But, when I run the code, it returns an error :
cannot import name 'Page2' from partially initialized module 'page2test' (most likely due to a circular import)
and I have no idea how to fix it...
If someone had an idea, it would be really helpful.
So, I've finally found the solution, that was not so difficult in the end. Here it is (if it can help someone) :
Instead of making 2 files, I've done just 1 file. Here is the code :
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QWidget, QLabel, QMainWindow
import sys
class MyApp(QWidget):
def __init__(self):
super(MyApp, self).__init__()
self.setWindowTitle("Page 1")
label1 = QLabel(self)
label1.setText("\n PAGE 1")
self.btn_inMyApp = QPushButton ('Page suivante', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage1_OpenPage2)
self.show()
def btn1_onClicked(self):
pass
def closePage1_OpenPage2(self):
self.Open = NewApp()
self.Open.showMaximized()
self.close()
class NewApp(QMainWindow):
def __init__(self):
super(NewApp, self).__init__()
self.setWindowTitle("Test window principale")
label1 = QLabel(self)
label1.setText("\n Page2")
self.btn_inMyApp = QPushButton ('previous Page', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage2_OpenPage1)
self.show()
def closePage2_OpenPage1(self):
self.Open = MyApp()
self.Open.showMaximized()
self.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MyApp()
window.showMaximized()
sys.exit(app.exec_())
```
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'm creating a PyQt5 application in which I want to put some of QLineEdit widgets inside a QGroupBox.
When I run my application, GroupBox is visible and LineEdit is not.
In CreateLinesEdit() I commented a line which sets the line edit visible, but it opens lineEdit in a new window.
from PyQt5.QtWidgets import QGroupBox, QApplication, QLineEdit, QVBoxLayout, QWidget, QHBoxLayout
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.InitWindow()
def InitWindow(self):
self.BoxLayout()
self.AddBox()
self.CreateLinesEdit()
self.show()
def BoxLayout(self):
self.groupBoxScreen = QGroupBox()
self.vbox = QVBoxLayout()
self.vbox_screenGame = QVBoxLayout()
self.hbox_lineEdit = QHBoxLayout()
def AddBox(self):
self.vbox_screenGame.addItem(self.hbox_lineEdit)
self.groupBoxScreen.setLayout(self.vbox_screenGame)
self.vbox.addWidget(self.groupBoxScreen)
self.setLayout(self.vbox)
def CreateLinesEdit(self):
self.lines_edit = []
for i in range(0, 4):
LineEdit = QLineEdit()
# LineEdit.setVisible(True)
self.lines_edit.append(LineEdit)
self.hbox_lineEdit.addWidget(self.lines_edit[i])
if __name__ == "__main__":
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
i'm new in Python and PyQt4.
I want to ask "How to back to previous Window ?"
i have 2 file in here, file 'login' and 'signup'
here file login.py
import sys
from PyQt4.QtGui import QWidget, QPushButton, QLineEdit, QLabel, \
QApplication, QGridLayout
from signup import SignUp
class Login(QWidget):
def __init__(self):
super(Login, self).__init__()
self.setWindowTitle("Login")
self.login_window()
def login_window(self):
self.login_layout = QGridLayout()
self.login_button = QPushButton("Login")
self.signup_button = QPushButton("Sign Up")
self.login_layout.addWidget(self.login_button, 2, 0)
self.login_layout.addWidget(self.signup_button, 2, 1)
self.signup_button.clicked.connect(self.signup_show)
self.setLayout(self.login_layout)
self.show()
def signup_show(self):
self.signupshow = SignUp()
self.hide()
self.signupshow.show()
def check_signup(self):
SignUp.check_signup()
self.show()
def main():
app = QApplication(sys.argv)
login = Login()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
and here is signup.py
import sys
from PyQt4.QtGui import QWidget, QPushButton, QLineEdit, QLabel, \
QApplication, QGridLayout
class SignUp(QWidget):
def __init__(self):
super(SignUp, self).__init__()
self.setWindowTitle("Sign Up")
self.signup_window()
def signup_window(self):
self.signup_layout = QGridLayout()
self.signup_button = QPushButton("Sign Up")
self.signup_layout.addWidget(self.signup_button, 2, 0, 1, 0)
self.signup_button.clicked.connect(self.check_signup)
self.setLayout(self.signup_layout)
self.show()
def check_signup(self):
self.close()
def main():
app = QApplication(sys.argv)
signup = SignUp()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
my problem is, when i push button signup from signup.py, it's close but window Login is not show.
i think i don't have any trigger in signup.py for check_signup in login.py
in this code, i delete some Line Edit and Label. I think it's not a problem.
i hope someone will help, Thank you before :)
and if you answer this questtion, i hope you will explain a little bit of the logic, thank you again :)
I'm not really sure what you are trying to achieve (your description is kind of confusing), but let's start here. I put all your code in one file, since you need to import each other (which leads to cyclic import). Then, I just added these two lines
self.login = Login()
self.login.show()
into check_signup method of SignUp class, which pops-up Login window. If this is not your desired result, please let us know and provide us a better description. The code follows:
import sys
from PyQt4.QtGui import QWidget, QPushButton, QLineEdit, QLabel, \
QApplication, QGridLayout
class Login(QWidget):
def __init__(self):
super(Login, self).__init__()
self.setWindowTitle("Login")
self.login_window()
def login_window(self):
self.login_layout = QGridLayout()
self.login_button = QPushButton("Login")
self.signup_button = QPushButton("Sign Up")
self.login_layout.addWidget(self.login_button, 2, 0)
self.login_layout.addWidget(self.signup_button, 2, 1)
self.signup_button.clicked.connect(self.signup_show)
self.setLayout(self.login_layout)
self.show()
def signup_show(self):
self.signupshow = SignUp()
self.hide()
self.signupshow.show()
def check_signup(self):
SignUp.check_signup()
self.show()
class SignUp(QWidget):
def __init__(self):
super(SignUp, self).__init__()
self.setWindowTitle("Sign Up")
self.signup_window()
def signup_window(self):
self.signup_layout = QGridLayout()
self.signup_button = QPushButton("Sign Up")
self.signup_layout.addWidget(self.signup_button, 2, 0, 1, 0)
self.signup_button.clicked.connect(self.check_signup)
self.setLayout(self.signup_layout)
self.show()
def check_signup(self):
self.login = Login()
self.login.show()
self.close()
def main():
app = QApplication(sys.argv)
signup = SignUp()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You should rather use signal-slot connections:
import sys
from PyQt4 import QtGui, QtCore
class WidgetA(QtGui.QWidget):
open_b = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(WidgetA, self).__init__(parent)
self.resize(100, 100)
self.l = QtGui.QVBoxLayout()
self.close_btn = QtGui.QPushButton('Close')
self.b_btn = QtGui.QPushButton('Open B')
self.b_btn.clicked.connect(self.b_btn_clicked)
self.l.addWidget(self.close_btn)
self.l.addWidget(self.b_btn)
self.setLayout(self.l)
def b_btn_clicked(self):
self.open_b.emit()
self.hide()
class WidgetB(QtGui.QWidget):
open_a = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(WidgetB, self).__init__(parent)
self.resize(100, 100)
self.l = QtGui.QVBoxLayout()
self.close_btn = QtGui.QPushButton('Close')
self.close_btn.clicked.connect(self.hide)
self.a_btn = QtGui.QPushButton('Open A')
self.a_btn.clicked.connect(self.a_btn_clicked)
self.l.addWidget(self.close_btn)
self.l.addWidget(self.a_btn)
self.setLayout(self.l)
def a_btn_clicked(self):
self.open_a.emit()
self.hide()
def main():
app = QtGui.QApplication(sys.argv)
a = WidgetA()
b = WidgetB()
a.open_b.connect(lambda: b.show())
b.open_a.connect(lambda: a.show())
a.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()