The Shortcut in a PySide2 MenuItem prevents window from showing - python

I'm trying to create a very simple ApplicationWindow using PySide2 (Qt for Windows) and QML.
main.py
import sys
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QUrl
from PySide2.QtQml import QQmlApplicationEngine
if __name__ == "__main__":
app = QApplication(sys.argv)
url = QUrl("mainWindow.qml")
engine = QQmlApplicationEngine()
engine.load(url)
sys.exit(app.exec_())
qml file
import QtQuick.Controls 2.4
ApplicationWindow {
id: mainWindow
visible: true
title: "MainWindow"
width: 640
height: 480
menuBar: MenuBar {
id: menuBar
Menu {
id: editMenu
title: "&Edit"
MenuItem {
id: copyItem
text: "Copy"
// This doesn't work:
// shortcut: "Ctrl+C"
// This doesn't work either:
// shortcut: StandardKey.Copy
}
}
}
}
As shown, the code runs and displays an ApplicationWindow with a MenuBar and the Menu. But if I outcomment either of the two shortcut variants the window isn't shown at all. I don't understand, why. My example follows the Qt documentation on MenuItems.

In QML there are 2 types of items: Qt Quick Controls 1 and Qt Quick Controls 2. Both groups have items with the same name but they differ in their properties, in your case MenuItem of Qt Quick Controls 2 does not have a shortcut property but instead Qt Quick Controls 1 if it has it so the solution is to change the import:
import QtQuick 2.11 // <---
import QtQuick.Controls 1.4 // <---
ApplicationWindow {
id: mainWindow
visible: true
title: "MainWindow"
width: 640
height: 480
menuBar: MenuBar {
id: menuBar
Menu {
id: editMenu
title: "&Edit"
MenuItem {
id: copyItem
text: "Copy"
shortcut: StandardKey.Copy
onTriggered: console.log("copy")
}
}
}
}

Related

Emit python list in Signal to Qml ui

I am trying to communicate a python script to a qml ui using signal/slot and, while it works for some types (str) it seems to not be working when I try emitting a list:
Python:
from PySide6.QtCore import QObject, Signal, Slot
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
import time, sys
class PythonSignalEmitter(QObject):
getListTest = Signal(list)
#Slot()
def callList(self):
print("HELLO from python ")
test = ["a", "b", "c"]
self.getListTest.emit(test)
if __name__ == '__main__':
app = QGuiApplication([])
engine = QQmlApplicationEngine()
signal_emitter = PythonSignalEmitter()
engine.rootContext().setContextProperty("signalEmitter", signal_emitter)
engine.load("main.qml")
sys.exit(app.exec())
Fragment of the main.qml file:
Connections {
target: signalEmitter
function onSignal(res) {
console.log(`------------`);
console.log(`qml list is ${res}`);
console.log(`------------`);
}
}
The output of this just gives:
HELLO from python
So the app runs with no problem, and after a click on a specified component, the slot is called, but the log in the QLM side is not even printed, seems like the signal is not even emitted.
[EDIT]
You need to rename onSignal with onGetListTest. The rest is fine.
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Window
ApplicationWindow {
id: main
title: qsTr("Hello World")
width: 640
height: 480
visible: true
Frame {
anchors.centerIn: parent
RowLayout {
Button {
text: qsTr("Quit")
onClicked: Qt.callLater(Qt.quit)
}
Button {
text: qsTr("Test")
onClicked: signalEmitter.callList()
}
}
}
Connections {
target: signalEmitter
function onGetListTest(res) {
console.log(`------------`);
console.log(`qml list is ${res}`);
console.log(`------------`);
}
}
}

Is there anyway to add a child element to a parent QML using Python

I'm trying to design a QtQuick application. I have a root QML window in which i have to add a child element without editing the parent QML file using python script
Python Code:
class RootQmlWindow():
def __init__(self):
self.engine = QQmlApplicationEngine()
self.engine.quit.connect(app.quit)
self.engine.load('QML/MainScreen.qml')
self.root = self.engine.rootObjects()[0]
app = QApplication(sys.argv)
window = RootQmlWindow()
sys.exit(onClose())
QML file:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
id: root
visible: true
width: 600
height: 300
title: "Main Window"
}

module `Qt.labs.qmlmodels` is not installed

I'm trying to run the example of item selection for a TableView, but it needs Qt.labs.qmlmodels. The problem is, that doesn't appear to be installed, and I can't find the correct package.
main.qml:
import Qt.labs.qmlmodels
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
ApplicationWindow {
visible: true
width: 1000
height: 700
title: "Test"
TableView {
id: tableView
anchors.fill: parent
clip: true
model: TableModel {
rows: [{
"name": "Harry"
}, {
"name": "Hedwig"
}]
TableModelColumn {
display: "name"
}
}
selectionModel: ItemSelectionModel {
model: tableView.model
}
delegate: Rectangle {
required property bool selected
implicitWidth: 100
implicitHeight: 30
color: selected ? "blue" : "lightgray"
Text {
text: display
}
}
}
}
main.py:
import sys
import signal
from PyQt6.QtGui import QGuiApplication
from PyQt6.QtQml import QQmlApplicationEngine
# Make app respond to Ctrl-C
signal.signal(signal.SIGINT, signal.SIG_DFL)
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.quit.connect(app.quit) # type: ignore
engine.load("main.qml")
sys.exit(app.exec())
Running main.py gives me this error:
QQmlApplicationEngine failed to load component
file:///home/user/test2/main.qml:1:1: module "Qt.labs.qmlmodels" is not installed
OS: Arch Linux
Qt version: 6.3.1-1
please read this:
qt-6.4-qml-python-missing-liberary-module-qt5compat-graphical-effects-is-not-installed
Just now, I try to change matplotlib-backends' version. I find that the pyqt6 folder doesn't have the Qt folder.
So I copy that in pyside6 lib to pyqt lib.
For me is:from D:\Python\Python39\Lib\site-packages\PySide6\qml\Qt to D:\Python\Python39\Lib\site-packages\PyQt6\Qt6\qml.
Please try this, hope it work.

Embedding a QQuickWidget in a Layout (or in a QWidget) in Python

I use Python and Pyside2, I try to insert a QQuickWidget inside a Qwidget or inside a Layout but I haven't find a solution.
I try with this code:
view = QQuickWidget()
view.setSource(QUrl.fromLocalFile("main.qml"))
but QQuickWidget start in another windows.
I try use:
Layout.addWidget(view)
but it required a QWidget and don't work with QQuickWidget.
I found this similar question (in C) but it don't work in Python:
Adding QQuickWidget in QStackedWidget
I have try QQmlApplicationEngine and QQuickView, but problem is the some.
Can you help me ?
Edit:
main.qml file is:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtLocation 5.6
import QtPositioning 5.6
Window {
width: 300
height: 300
visible: true
Plugin {
id: mapPlugin
name: "esri"
}
Map {
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(39.2160, 9.1344)
zoomLevel: 16
}
}
The problem is that the root element is a Window that will create a window, the solution is to use an Item:
import QtQuick 2.0
import QtLocation 5.6
import QtPositioning 5.6
Item {
width: 300
height: 300
Plugin {
id: mapPlugin
name: "esri"
}
Map {
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(39.2160, 9.1344)
zoomLevel: 16
}
}

multiple qml files in pyqt

I am using pyqt and I have the following directory structure:
root
----> apps/
----> ui/
I have a simple qml based application in the app folder as:
apps/testqt.py
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView, QQuickWindow
from PyQt5.QtQml import qmlRegisterType, QQmlApplicationEngine
import sys
app = QApplication(sys.argv)
engine = QQmlApplicationEngine('ui/window.qml')
topLevel = engine.rootObjects()[0]
win = QQuickWindow(topLevel)
win.show()
app.exec_()
ui/window.qml
The qml file defines the app window and uses a StackView as follows:
import QtQuick 2.0
import QtQuick.Window 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
ApplicationWindow {
id: rootWindow
objectName: "window"
visible: true
width: 800
height: 480
title: "Window"
Component.onCompleted: {
setX(Screen.width / 2 - width / 2);
setY(Screen.height / 2 - height / 2);
}
property Component loginView: LoginView {}
StackView {
id: stackView
anchors.fill: parent
Component.onCompleted:
{
stackView.push(loginView)
}
}
}
This uses the LoginView component which is defined as:
apps/LoginView.qml
import QtQuick 2.0
import QtQuick.Window 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.0
ControlView {
ColumnLayout {
anchors.centerIn: parent
spacing: 25
width: 200
TextField {
id: username_fld
placeholderText: qsTr("User name")
Layout.fillWidth: true
}
TextField {
id: password_fld
placeholderText: qsTr("Password")
Layout.fillWidth: true
echoMode: TextInput.Password
}
RowLayout {
Button {
id: login_button
text: "Log In"
Layout.fillWidth: true
}
Button {
id: cancel_button
text: "Cancel"
Layout.fillWidth: true
}
}
}
}
Now when I use qmlscene, the view loads just fine. However, running python results in the application hanging while trying to load the QQmlApplicationEngine. I have a feeling it has something to do with the qml paths perhaps, so I included import ../ui into the window.qml imports but that did not change anything.
I am using Python 2.7 with Qt 5.6 in an Anaconda environment. Qt was installed from here: https://anaconda.org/anaconda/pyqt
Similarly i use multiple qml files along with multiple python files. When i access application it loads perfectly two qml files successfully but when stacked through third qml page, the application crashes. It throws segmentation fault.
I use Stackview to push and pop through QML pages, during debugging i found that it works when push and pop are done for just for two pages.
I have came across if i use Swipeview too. What i guess is that the engine that was created can be loaded with two stack QML files.

Categories

Resources