How to make round edges for the main window in PyQt? - pyqt

The question is extremely simple, but I am not succeeding at it at the moment:
What is the simplest way to make round edges to the main window in PyQt/PySide code? I have tried lots of things that can be found online but none works. Here is th simplest example (that is supposed to work in my opinion, but doesn't):
from PySide6.QtWidgets import QApplication, QMainWindow
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setStyleSheet("border-radius: 10px;")
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())

Related

Why does the label show only the last set image? (PyQt5) [duplicate]

I have got this problem. I´m trying to set text on a lineEdit object on pyqt4, then wait for a few seconds and changing the text of the same lineEdit. For this I´m using the time.sleep() function given on the python Time module. But my problem is that instead of setting the text, then waiting and finally rewrite the text on the lineEdit, it just waits the time it´s supposed to sleep and only shows the final text. My code is as follows:
from PyQt4 import QtGui
from gui import *
class Ventana(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.button.clicked.connect(self.testSleep)
def testSleep(self):
import time
self.lineEdit.setText('Start')
time.sleep(2)
self.lineEdit.setText('Stop')
def mainLoop(self, app ):
sys.exit( app.exec_())
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Ventana()
window.show()
sys.exit(app.exec_())
You can't use time.sleep here because that freezes the GUI thread, so the GUI will be completely frozen during this time.
You should probably use a QTimer and use it's timeout signal to schedule a signal for deferred delivery, or it's singleShot method.
For example (adapted your code to make it run without dependencies):
from PyQt4 import QtGui, QtCore
class Ventana(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setLayout(QtGui.QVBoxLayout())
self.lineEdit = QtGui.QLineEdit(self)
self.button = QtGui.QPushButton('clickme', self)
self.layout().addWidget(self.lineEdit)
self.layout().addWidget(self.button)
self.button.clicked.connect(self.testSleep)
def testSleep(self):
self.lineEdit.setText('Start')
QtCore.QTimer.singleShot(2000, lambda: self.lineEdit.setText('End'))
def mainLoop(self, app ):
sys.exit( app.exec_())
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Ventana()
window.show()
sys.exit(app.exec_())
Also, take a look at the QThread sleep() function, it puts the current thread to sleep and allows other threads to run. https://doc.qt.io/qt-5/qthread.html#sleep
You can't use time.sleep here because that freezes the GUI thread, so the GUI will be completely frozen during this time.You can use QtTest module rather than time.sleep().
from PyQt4 import QtTest
QtTest.QTest.qWait(msecs)
So your code should look like:
from PyQt4 import QtGui,QtTest
from gui import *
class Ventana(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.button.clicked.connect(self.testSleep)
def testSleep(self):
import time
self.lineEdit.setText('Start')
QtTest.QTest.qWait(2000)
self.lineEdit.setText('Stop')
def mainLoop(self, app ):
sys.exit( app.exec_())
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Ventana()
window.show()
sys.exit(app.exec_())

Creating new window using keyboard keys [duplicate]

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_())

PySide2 How to unassign current layout and assign a new one to a window widget? .count() gives attribute error?

I'm new to PySide2, started using it yesterday. I'm teaching myself from the API documentation and info I find online. I'm trying to make a small app with it to teach myself. My idea for the app was using a View like model, as you go pressing on certain buttons I delete the current layout on the window and present you with an entire new one. This foments modularity as each layout wouldn't be dependent on each other but instead fully individual. (Each part of the app is broadly different and requires almost all widgets to be deleted).
However whenever I search how to delete a layout or remove all of its widgets I always encounter a piece of code like this (This is actually from a question asked 6 months ago):
def clearLayout(self, layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.deleteLater()
else:
self.clearLayout(item.layout())
Yet when I implement something like that, even the exact same function and then call it using, self.clearLayout(self.layout) I get the following error:
File "GUI.py", line 45, in home
self.clearLayout(self.layout)
File "GUI.py", line 16, in clearLayout
while layout.count():
AttributeError: 'builtin_function_or_method' object has no attribute 'count'
I'm assuming I probably forgot to import something important, but I can't just seem to find what. Here is a list with my imports.
import sys
from PySide2.QtWidgets import QApplication, QLabel, QLineEdit, QWidget
from PySide2.QtWidgets import QDialog, QPushButton, QVBoxLayout, QLayout
I also installed PySide2 using pip install PySide2 on command line (Anaconda). Do I have to do something else?
Thank you so much, sorry post is so long, just wanted to give you the whole information from the beginning :)
EDIT:
Further testing has led me to realise I cannot use any of the virtual functions of QLayout, or its subclasses. Apparently I have to implement them myself within the code. I believe it could be this. I don't know how to implement them though. I'm going to keep trying.
EDIT 2: Some people asked for a reporducible example so here is the code that doesn't work.
import sys
from PySide2.QtWidgets import QApplication, QLabel, QLineEdit, QWidget
from PySide2.QtWidgets import QDialog, QPushButton, QVBoxLayout, QLayout
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Program")
self.setGeometry(300, 300, 300, 300)
self.start()
def clearLayout(self, layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.deleteLater()
else:
self.clearLayout(item.layout())
def start(self):
self.startbutton = QPushButton("Start App")
layout = QVBoxLayout()
layout.addWidget(self.startbutton)
self.setLayout(layout)
self.startbutton.clicked.connect(self.home)
def home(self):
self.clearLayout(self.layout)
self.message=QLabel("Welcome to homepage")
layout=QVBoxLayout()
layout.addWidget(self.message)
self.setLayout(layout)
if __name__ == "__main__":
app = QApplication([])
window=Window()
window.show()
sys.exit(app.exec_())

PyQt5 - How to draw a dot on mouse click position?

I am trying to draw a dot on my main window, but the dot is not shown.
I've tried bounding mousePressEvent to paintEvent, but it didn't work as well. Here's current version of my code(which is not working too). Also I tried place a point with drawPoint method and it didn't work too.
import sys
from PyQt5 import QtWidgets, QtGui, QtCore, uic
class GUI(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi('gui.ui', self)
self.setFixedSize(self.size())
self.show()
def mousePressEvent(self, e):
print(e.pos())
qp = QtGui.QPainter()
qp.begin(self)
qp.setPen(QtCore.Qt.red)
qp.drawEllipse(e.pos().x(), e.pos().y(), 10, 10)
qp.end()
self.update()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = GUI()
sys.exit(app.exec_())
I know that mousePressEvent is working since I get coords of the click.
I am okay to change methods of dot-placing or type of dots to place, but it should have customizable color and size.
You should only draw within the paintEvent method, and this paint does not save memory so if you want to graph several points you must store them in some container, for example using QPolygon.
paintEvent() is called every time you call update() or repaint(), for example it is called every time it is resized, the window is moved, etc.
import sys
from PyQt5 import QtWidgets, QtGui, QtCore, uic
class GUI(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi('gui.ui', self)
self.setFixedSize(self.size())
self.show()
self.points = QtGui.QPolygon()
def mousePressEvent(self, e):
self.points << e.pos()
self.update()
def paintEvent(self, ev):
qp = QtGui.QPainter(self)
qp.setRenderHint(QtGui.QPainter.Antialiasing)
pen = QtGui.QPen(QtCore.Qt.red, 5)
brush = QtGui.QBrush(QtCore.Qt.red)
qp.setPen(pen)
qp.setBrush(brush)
for i in range(self.points.count()):
qp.drawEllipse(self.points.point(i), 5, 5)
# or
# qp.drawPoints(self.points)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = GUI()
sys.exit(app.exec_())

one single scroll bar for two QTextEdit, pyqt4, python

How to make one single scroll bar for two QTextEdit, pyqt4, python. Or how to synchronize two scrollbars of two QTextEdit. For simultaneous scrolling texts.
Pyqt4, python.
Cross-connect the value changed signals of all the scrollbars:
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.edit1 = QtGui.QTextEdit(self)
self.edit2 = QtGui.QTextEdit(self)
layout = QtGui.QHBoxLayout(self)
layout.addWidget(self.edit1)
layout.addWidget(self.edit2)
self.edit1.horizontalScrollBar().valueChanged.connect(
self.edit2.horizontalScrollBar().setValue)
self.edit1.verticalScrollBar().valueChanged.connect(
self.edit2.verticalScrollBar().setValue)
self.edit2.horizontalScrollBar().valueChanged.connect(
self.edit1.horizontalScrollBar().setValue)
self.edit2.verticalScrollBar().valueChanged.connect(
self.edit1.verticalScrollBar().setValue)
text = '\n'.join(name for name in dir(QtCore))
self.edit1.setText(text)
self.edit2.setText(text)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 600, 400)
window.show()
sys.exit(app.exec_())

Resources