PyQt5 - pythonw.exe crash on handling clicked event - python

I'm new to PyQt5 and I've got an error (pythonw.exe not working anymore) with the following code:
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(self.q)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.show()
def q():
print('test')
sys.exit()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
app.exec_()
First it works, but only until I push the "quit" button. Then the error message pops up.
If I put the q() function outside the class (and change "self.q" into "q") it works fine.
What's the problem?
Thanks in advance.
Windows 7
Python 3.4.3 (x86)
PyQt 5.5.1 (x86)

that's because when q() is inside the class it's expects a compulsory argument as the first parameter, this is usually called self and is passed for you implicitly by python when you're calling the method (q() not q(self)). just as you've done with the initUI method in your class, when you put it outside the class, it's just a normal function and not a method again (function in a class), so it's fine to define the function without self
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(self.q)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.show()
def q(self):
print('test')
sys.exit()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
app.exec_()

Related

PyQt - how to rerender window

I am new to PyQt and Qt at all and I have a problem with window rendering or updating or how to call it. Problem is that when I call QWidget.show(), none of added components after are displayed. Here is a simple code, where in init(), there is called self.show(). First QLabel item is displayed and the second one is not. What am I doing wrong?
Code:
from PyQt6.QtWidgets import QApplication, QWidget, QLabel
import sys
class MyGui(QWidget):
box = {}
def __init__(self) -> None:
super().__init__()
self.setFixedSize(200, 400)
self.setStyleSheet("background-color:#000000")
self.box["top"] = QLabel(self)
self.box["top"].setFixedSize(200, 200)
self.box["top"].setStyleSheet("background-color:red")
self.box["top"].move(0,0)
self.show()
self.box["botom"] = QLabel(self)
self.box["botom"].setFixedSize(200, 200)
self.box["botom"].setStyleSheet("background-color:green")
self.box["botom"].move(0,200)
if __name__ == "__main__":
app = QApplication(sys.argv)
my_app = MyGui()
my_app.show()
try:
sys.exit(app.exec())
except SystemExit:
print("Closing window..")
Screenshots of GUI window:
With self.show()
Without self.show()

adding an Icon next to title doesn't work on Mac

I would like to add A LOGO next to Icon but it doesn't seem to work on Mac , any suggestions for [this]
code :
import sys
import os
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Icon')
self.setWindowIcon(QIcon('icon-cutout.png'))
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
path = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'icon-cutout.png')
app.setWindowIcon(QIcon(path))
ex = Example()
sys.exit(app.exec_())
it only appears in [here]

Timers cannot be stopped from another thread - Remove Focus

import sys
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit
class Worker(QThread):
def __init__(self, textBox):
super().__init__()
self.textBox = textBox
def run(self):
while True:
if self.textBox.text() == "close":
app.quit()
break
if self.textBox.text() == "removeFocus":
self.textBox.clearFocus()
class window(QWidget):
def __init__(self):
super().__init__()
vBox = QVBoxLayout()
self.setLayout(vBox)
self.resize(600, 400)
textBox = QLineEdit()
vBox.addWidget(textBox)
worker = Worker(textBox)
worker.start()
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = window()
sys.exit(app.exec())
When I type "close" in the textBox it works very fine but when I type "removeFocus", it still works but I get this error:
QObject::killTimer: Timers cannot be stopped from another thread
Why am I getting such an error even though the program is running?
(Since the process I want to do is very simple, I don't think I can go into much detail. I've just started learning Python. This is the first time I use this site. I'm sorry if I made a mistake while creating a post. Thank you)
In Qt you must not access or modify the GUI information from another thread (see this for more information) since it does not guarantee that it works (the GUI elements are not thread-safe), in your case luckily you have no problems but It is dangerous to use your approach in real.
In your case it is also unnecessary to use threads since it is enough to use the textChanged signal from QLineEdit.
import sys
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit
class Window(QWidget):
def __init__(self):
super().__init__()
vBox = QVBoxLayout(self)
self.resize(600, 400)
self.textBox = QLineEdit()
vBox.addWidget(self.textBox)
self.textBox.textChanged.connect(self.on_text_changed)
#pyqtSlot(str)
def on_text_changed(self, text):
if text == "close":
QApplication.quit()
elif text == "removeFocus":
self.textBox.clearFocus()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())

Child dialog doesn't show up in PyQt5

Hi, I'm trying to make simple GUI application using PyQt5, Python 3.4 and Windows 7.
Below code works properly.
# coding: utf-8
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog
class MainWnd(QMainWindow):
def __init__(self):
super().__init__()
self.popup_dlg = None
self.init_ui()
def init_ui(self):
self.setGeometry(100, 100, 300, 200)
self.show()
self.popup_dlg = ChildWnd()
class ChildWnd(QDialog):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.resize(200, 100)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWnd()
sys.exit(app.exec_())
Two windows are created. One is main window and the other is child window(popup window). But what I want is to make child window's default location is centered of main window.
So I've modified the code like this.
# coding: utf-8
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog
class MainWnd(QMainWindow):
def __init__(self):
super().__init__()
self.popup_dlg = None
self.init_ui()
def init_ui(self):
self.setGeometry(100, 100, 300, 200)
self.show()
self.popup_dlg = ChildWnd(self) # make instance with parent window argument.
class ChildWnd(QDialog):
def __init__(self, parent_wnd):
super().__init__()
self.setParent(parent_wnd) # set child window's parent
self.init_ui()
def init_ui(self):
self.resize(200, 100)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWnd()
sys.exit(app.exec_())
But this code makes problem. Child window doesn't show up. Only main window(=parent window) shows. In Qt's QDialog's manual, I found this.
but if it has a parent, its default location is centered on top of the
parent's top-level widget (if it is not top-level itself).
This is why I added the setParent().
What should I do?
Please help me!!
As specified in the documentation calling setParent will just change the ownership of the QDialog widget. If you want the QDialog widget to be centered within it's parent, you need to pass the parent widget instance to the super constructor of your QDialog:
class ChildWnd(QDialog):
def __init__(self, parent_wnd):
super().__init__(parent_wnd)
self.init_ui()
def init_ui(self):
self.resize(200, 100)
self.show()

PyQt - Must construct a QApplication before a QWidget

I've realized when creating a class variable to hold a QWidget, it crashes complaining that there is no QApplication. I could break it down to do this minimal example.
import sys
from PyQt4 import QtGui, QtCore
class ThumbContextMenu(QtGui.QMenu):
def __init__(self):
super(ThumbContextMenu, self).__init__()
class Example(QtGui.QWidget):
menu = ThumbContextMenu()
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Commenting #menu will launch the application, or putting #menu as an instance variable won't crash too.
Maybe you want to use delayed initialization? Something like this, maybe:
class Example(QtGui.QWidget):
menu = None
def __init__(self):
...
if Example.menu is None:
Example.menu = ThumbContextMenu()
The problem is that menu is class variable, so it is being initialized when Example definition is evaluated, i.e. before you call QApplication constructor.

Categories

Resources