Qt module alternative for PyQt6 - python

I'm just migrating my application from PyQt5 to PyQt6. I understand that the Qt module has been removed in Qt6. I have stuff like 'Qt.AlignCenter', 'Qt.ToolButtonTextUnderIcon', 'Qt.LeftToolBarArea', which are no longer working. Is there any alternative for this functionality in Qt6?

The Qt module only exists in PyQt5 (not in Qt5) that allowed access to any class or element of any submodule, for example:
$ python
>>> from PyQt5 import Qt
>>> from PyQt5 import QtWidgets
>>> assert Qt.QWidget == QtWidgets.QWidget
That module is different from the Qt namespace that belongs to the QtCore module, so if you want to access Qt.AlignCenter then you must import Qt from QtCore:
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QLabel
def main():
app = QApplication(sys.argv)
w = QLabel()
w.resize(640, 498)
w.setAlignment(Qt.Alignment.AlignCenter)
w.setText("Qt is awesome!!!")
w.show()
app.exec()
if __name__ == "__main__":
main()
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication, QMainWindow, QStyle, QToolBar
def main():
import sys
app = QApplication(sys.argv)
toolbar = QToolBar()
toolbar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon)
icon = app.style().standardIcon(QStyle.StandardPixmap.SP_DesktopIcon)
toolbar.addAction(icon, "desktop")
w = QMainWindow()
w.addToolBar(Qt.ToolBarAreas.LeftToolBarArea, toolbar)
w.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

Currently, the AlignCenter and others can be found under AlignmentFlag enum:
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QPushButton, QVBoxLayout
def create_widget():
layout = QVBoxLayout()
button = QPushButton('Cancel')
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(button)

Related

How to use QTest.keySequence?

I'm trying to test if a shortcut is working using PyQt5 and QTest. Here is my code:
Main.py
from PyQt5.QtGui import QKeySequence
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, QPushButton
class Window(QWidget):
def __init__(self):
super().__init__()
self.more_btn = QPushButton("More")
self.more_btn.clicked.connect(self.on_clicked)
self.more_btn.setShortcut(QKeySequence.Undo)
vbox = QVBoxLayout()
vbox.addWidget(self.more_btn)
self.setLayout(vbox)
def on_clicked(self):
print("Item clicked")
test_main.py
import sys
import unittest
from PyQt5.QtGui import QKeySequence
from PyQt5.QtTest import QTest
from PyQt5.QtWidgets import QApplication
from Main import Window
class MainTestCase(unittest.TestCase):
def test_main(self):
app = QApplication(sys.argv)
form = Window()
QTest.keySequence(form, QKeySequence.Undo)
When I run test_main, item_clicked should be printed, but it doesn't. I tried to debug the program and set the breatpoint at the print("Item clicked") line, it didn't stop. It seems that QTest.keySequence didn't work. Why? How should I make it work?

QT_DEVICE_PIXEL_RATIO is deprecated

I get the following warning when I run the code below
Warning: QT_DEVICE_PIXEL_RATIO is deprecated. Instead use:
QT_AUTO_SCREEN_SCALE_FACTOR to enable platform plugin controlled per-screen factors.
QT_SCREEN_SCALE_FACTORS to set per-screen DPI.
QT_SCALE_FACTOR to set the application global scale factor.
code:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QDialog, QStackedWidget
from PyQt5.uic import loadUi
class WelcomeScreen(QDialog):
def _init_(self):
super(WelcomeScreen, self)._init_()
loadUi("screen1.ui", self)
# main
app = QApplication(sys.argv)
welcome = WelcomeScreen()
widget = QStackedWidget()
widget.addWidget(welcome)
widget.setFixedHeight(500)
widget.setFixedWidth(800)
widget.show()
# app.exec_()
try:
sys.exit(app.exec())
except:
print("exiting")

PyQt embed QWebEngineView in Main Window

I'm coming from a tkinter background where everything can be put in a frame.
How can I get my current working codes result (which launches a WebEngine View of a page, google in this instance) to sit inside a main window like shown in the image? Going by the image I want the WebEngine to be housed in the "Green" Box for example.
Working code including all versions used
"""
Python version - 3.7.3
PyQt5 5.15.3
PyQt5-Qt 5.15.2
PyQt5-sip 12.8.1
PyQtWebEngine 5.15.3
PyQtWebEngine-Qt 5.15.2
"""
import sys
from PyQt5.QtWebEngineWidgets import QWebEnginePage
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
url = 'https://google.com'
app = QApplication(sys.argv)
# QWebEngineView
browser = QWebEngineView()
browser.load(QUrl(url))
browser.show()
sys.exit(app.exec_())
You have to use a QGridLayout:
import sys
from PyQt5.QtWidgets import QApplication, QGridLayout, QMainWindow, QTextEdit, QWidget
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
url = "https://google.com"
app = QApplication(sys.argv)
w = QMainWindow()
browser = QWebEngineView()
browser.load(QUrl(url))
central_widget = QWidget()
w.setCentralWidget(central_widget)
lay = QGridLayout(central_widget)
lay.addWidget(browser, 0, 0, 2, 1)
lay.addWidget(QTextEdit(), 0, 1)
lay.addWidget(QTextEdit(), 1, 1)
lay.setColumnStretch(0, 1)
lay.setColumnStretch(1, 1)
lay.setRowStretch(0, 1)
lay.setRowStretch(1, 1)
w.show()
sys.exit(app.exec_())
You could use a vertical layout to hold the two red boxes. And then use a horizontal layout to hold the QWebEngineView and the vertical layout. Zetcode has a good tutorial for layouts. Code heavily borrowed from #eyllanesc:
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow,
QHBoxLayout, QVBoxLayout,
QTextEdit, QWidget)
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
url = "https://google.com"
app = QApplication(sys.argv)
w = QMainWindow()
browser = QWebEngineView()
browser.load(QUrl(url))
central_widget = QWidget()
w.setCentralWidget(central_widget)
vertical = QVBoxLayout()
vertical.addWidget(QTextEdit())
vertical.addWidget(QTextEdit())
horizontal = QHBoxLayout(central_widget)
horizontal.addWidget(browser)
horizontal.addLayout(vertical)
w.show()
sys.exit(app.exec_())

How to control the checkbox using the Python itself, and not by a mouse click?

I created a checkbox using PyQT, which normally works using mouse clicks.
I want to know if there is a way with which I can uncheck and check the checkbox using the program itself, and not a mouse click.
Basically I want to check and uncheck the box 10 times in 20 seconds and display it happening.
Here is my code for just the checkbox:
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QLabel, QCheckBox, QWidget
from PyQt5.QtCore import QSize
class ExampleWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMinimumSize(QSize(140, 40))
self.setWindowTitle("Checkbox")
self.b = QCheckBox("Yes",self)
self.b.move(20,20)
self.b.resize(320,40)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = ExampleWindow()
mainWin.show()
sys.exit( app.exec_() )
checked : bool
This property holds whether the button is checked
Only checkable buttons can be checked. By default, the button is unchecked.
The QTimer class provides repetitive and single-shot timers.
More ... https://doc.qt.io/qt-5/qtimer.html
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QLabel, QCheckBox, QWidget
from PyQt5.QtCore import QSize
class ExampleWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMinimumSize(QSize(140, 40))
self.setWindowTitle("Checkbox")
self.b = QCheckBox("Yes",self)
self.b.move(20,20)
self.b.resize(320,40)
self.num = 0
self.timer = QtCore.QTimer()
self.timer.setInterval(2000) # msec
self.timer.timeout.connect(self.update_now)
self.timer.start()
def update_now(self):
self.b.setChecked(not self.b.isChecked()) # +++
self.num += 1
if self.num == 10: self.timer.stop()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = ExampleWindow()
mainWin.show()
sys.exit( app.exec_() )

PySide2 QUiLoader returns an empty window

PySide2(5.6.0~a1) Qt UI file loader returns an empty window whereare PyQt5 loader works fine. Could you explained to me where I am wrong.
Non Working PySide2 version:
import sys
from PySide2.QtWidgets import QDialog, QApplication
from PySide2 import QtUiTools
class AppWindow(QDialog):
def __init__(self):
super().__init__()
self.ui = QtUiTools.QUiLoader().load("dialog1.ui")
self.show()
app = QApplication(sys.argv)
w = AppWindow()
sys.exit(app.exec_())
Working PyQt5 version:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5 import uic
class AppWindow(QDialog):
def __init__(self):
super().__init__()
self.ui = uic.loadUi("dialog1.ui", self)
self.show()
app = QApplication(sys.argv)
w = AppWindow()
sys.exit(app.exec_())
Using this function also does not work :
def loadUiWidget(uifilename, parent=None):
loader = QtUiTools.QUiLoader()
uifile = QtCore.QFile(uifilename)
uifile.open(QtCore.QFile.ReadOnly)
ui = loader.load(uifile, parent)
uifile.close()
return ui
In PySide2 there's no function to QMainWindow class overwrite itself. It's necessary to show the ui:
import sys
from PySide2.QtWidgets import QDialog, QApplication
from PySide2 import QtUiTools
class AppWindow(QDialog):
def __init__(self):
super().__init__()
self.ui = QtUiTools.QUiLoader().load("dialog1.ui")
self.ui.show()
app = QApplication(sys.argv)
w = AppWindow()
sys.exit(app.exec_())
QUiLoader().load() returns the widget as an object so if you assign it to a variable it will not do anything, you should use show():
import sys
from PySide2.QtWidgets import QApplication
from PySide2 import QtUiTools
app = QApplication(sys.argv)
w = QtUiTools.QUiLoader().load("dialog1.ui")
w.show()
sys.exit(app.exec_())
If you want to load QMainWindow from designer *.ui file you can use
import sys
from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtUiTools import QUiLoader
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setCentralWidget(QUiLoader().load("form.ui"))
but slot-signal bindings, which are set in the designer in *.ui file, are not working anyway.
So, for full-function use of designer GUI and slot-signal bindings, the only way I found is to compile *.ui file to python module with pyside UI compiler:
pyside2-uic mainwindow.ui > ui_mainwindow.py
and then include produced ui_mainwindow. In this method the slot-signal pairs from Qt UI designer will work well.
import sys
from PySide2.QtWidgets import QApplication, QMainWindow
from ui_mainwindow import Ui_MainWindow
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)

Categories

Resources