Send string signal from combobox in qml - qml

I'm trying to send a string from combobox to an api. Unfortunately nothing is being sent.
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
id: mainWindow
width: 1120
height: 680
visible: true
Rectangle {
id: mainBody
color: "#F4F4F5"
anchors.fill: parent
ComboBox {
id: comboBox
x: 219
y: -9
width: 504
height: 40
model: [ "hp", "lenovo", "acer"]
}
Button {
id: bt
width: 24
height: 24
onClicked: backend.add(comboBox.text)
}
}
Connections {
target: backend
}
}
main.py
# This Python file uses the following encoding: utf-8
import os
# from pathlib import Path
import sys
import json
import requests
from PySide2.QtWidgets import QApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import Slot, Signal, QObject
class MainWindow(QObject):
def __init__(self):
QObject.__init__(self)
signalcombo = Signal(str)
#Slot(str, str, str)
def add(self, getCombo):
putdata1 = {"category_name": getCombo}
data1 =
requests.post("random api", json=putdata1)
print(data1.text)
if __name__ == "__main__":
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
# engine.load(os.fspath(Path(__file__).resolve().parent / "qml/main.qml"))
engine.load(os.path.join(os.path.dirname(__file__), "qml/main.qml"))
# Get Context
main = MainWindow()
engine.rootContext().setContextProperty("backend", main)
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
Now the problem is that when data1.text is printed it says "Inserted Successfully", but there is nothing in the database not even blank space. No data is being sent. Can anyone help me. This approach is working for textField but not for combobox.

There are various problems with your code.
First of all, the slot decorator for add has the wrong number of arguments. In the QML you're calling it with only one argument, but the slot has three. Change it to:
#Slot(str)
def add(self, getCombo):
# ...
Then, ComboBox has no property named text, but currentText (or any other valid property available for it, like displayText).
Button {
id: bt
width: 24
height: 24
onClicked: backend.add(comboBox.currentText)
}
Finally, while not critical, you should first set the context, and then load the QML:
main = MainWindow()
engine.rootContext().setContextProperty("backend", main)
engine.load(os.path.join(os.path.dirname(__file__), "qml/main.qml"))

Related

QtQuick 3D: Scene3DView is not a type

Before I start pulling my hair out, I thought I might try asking for help here.
On a Fedora 36 installation with a stock Qt5 installation, the following code for the main.qml works with no issues.
import QtQuick 2.12
import QtQuick.Layouts 1.15
import QtQuick.Window 2.12
import QtQuick.Scene3D 2.15
Window {
id: mainWindow
width: 840
height: 840
visible: true
title: qsTr("My 3D World")
color: "blue"
Scene3D {
id: mainScene
anchors.fill: parent
compositingMode: Scene3D.FBO
}
Scene3DView {
id: viewport
x: 5
y: 5
width: parent.width * 0.80
height: parent.height * 0.80
scene3D: mainScene
MyScene {
id: myscene
}
}
}
On Windoze 10 however, with versions Qt 6.2.4, 6.3.1, and 6.4 I get this runtime error:
QQmlApplicationEngine failed to load component
qrc:/main.qml:20:5: Scene3DView is not a type
Does Scene3DView no longer exist in Qt6? Has it been moved to a different module? Am I missing something stupidly simple?
Many thanks in advance.

Why does my old folium app stopped show maps [duplicate]

I wrote a python test program like this to show openstreetmap:
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
import sys
def mainPyQt5():
url = 'file:///./index.html'
app = QApplication(sys.argv)
browser = QWebEngineView()
browser.load(QUrl(url))
browser.show()
sys.exit(app.exec_())
mainPyQt5()
index.html fetched by QWebEngineView simply calls openstreetmap:
<title>OSM and Leaflet</title>
<link rel = "stylesheet" href = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<div id = "map" style = "width: 900px; height: 580px"></div><script src = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script>
// Creating map options
var mapOptions = {
center: [45.641174, 9.114828],
zoom: 10
}
// Creating a map object
var map = new L.map('map', mapOptions);
// Creating a Layer object
var layer = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
// Adding layer to the map
map.addLayer(layer);
</script>
If I fetch index.html with a ordinary browser the map is shown as expected but if I call the simple python program using QWebEngineView no tiles are downloaded from openstreetmap. If I replace openstreetmap with maps.stamen.com everything is fine both with a browser or the python script.
By default QtWebEngine does not set default headers like popular browsers do. In this case the openstreetmap server needs to know the "Accept-Language" to produce the maps since for example the names of the cities will depend on the language to filter non-browser traffic. The solution is to implement a QWebEngineUrlRequestInterceptor that adds that header:
import os.path
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
from PyQt5.QtWebEngineWidgets import QWebEngineView
class Interceptor(QWebEngineUrlRequestInterceptor):
def interceptRequest(self, info):
info.setHttpHeader(b"Accept-Language", b"en-US,en;q=0.9,es;q=0.8,de;q=0.7")
def mainPyQt5():
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
filename = os.path.join(CURRENT_DIR, "index.html")
app = QApplication(sys.argv)
browser = QWebEngineView()
interceptor = Interceptor()
browser.page().profile().setUrlRequestInterceptor(interceptor)
browser.load(QUrl.fromLocalFile(filename))
browser.show()
sys.exit(app.exec_())
if __name__ == "__main__":
mainPyQt5()

Qt Quick Controls 2 TextArea `tabChangesFocus`, how to use Tab key to change focus, not type Tab character

QML TextArea from Qt Quick Controls 1.x (http://doc.qt.io/qt-5/qml-qtquick-controls-textarea.html) had a property called tabChangesFocus, which could be set to toggle the behaviour of the Tab key between two possible actions:
true: enter Tab character in the TextArea
false: move the focus to next item in the tab Chain
This property doesn't seem to exist for TextArea in Quick Controls 2.x (https://doc.qt.io/qt-5/qml-qtquick-controls2-textarea.html).
The default is the true behaviour, but I would like the false behaviour (focus change).
Does anyone know a simple way to achieve the same effect for Quick Controls 2?
Another way is to use Item::nextItemInFocusChain(). This way, you don't need to know the next item in focus chain:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
id: window
width: 300
height: 300
visible: true
Column {
spacing: 20
TextArea {
id: textArea1
focus: true
text: "TextArea1"
Keys.onTabPressed: nextItemInFocusChain().forceActiveFocus(Qt.TabFocusReason)
}
TextArea {
id: textArea2
text: "TextArea2"
objectName: text
Keys.onTabPressed: nextItemInFocusChain().forceActiveFocus(Qt.TabFocusReason)
}
}
}
This should probably be made more convenient in the future, but you can setup tab navigation with QML KeyNavigation:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
id: window
width: 300
height: 300
visible: true
Column {
spacing: 20
TextArea {
id: textArea1
focus: true
text: "TextArea1"
KeyNavigation.tab: textArea2
KeyNavigation.backtab: textArea2
KeyNavigation.priority: KeyNavigation.BeforeItem
}
TextArea {
id: textArea2
text: "TextArea2"
KeyNavigation.tab: textArea1
KeyNavigation.backtab: textArea1
KeyNavigation.priority: KeyNavigation.BeforeItem
}
}
}

Why does my custom TabBar lose it's content children in this example?

I am trying to create a TabBar has preview images of the connected layout's children. However after adding several tabs (the exact number depends on the number of elements within the tabs) QML throws an error and the PreviewTabBar loses all its content children.
The following is a minimal working example:
My main.qml:
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
StackLayout {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
}
Timer {
interval: 50; running: true; repeat: true
onTriggered: addTab()
}
function addTab() {
console.log("add Tab")
var component = Qt.createComponent("qrc:/TabContent.qml")
if(component.status !== Component.Ready)
console.log("component not ready")
var item = component.createObject(swipeView)
tabBar.addTab(item)
tabBar.currentIndex = tabBar.contentChildren.length - 1
console.log("current index " + tabBar.currentIndex)
}
header: PreviewTabBar {
id: tabBar
currentIndex: swipeView.currentIndex
}
}
The PreviewTabBar.qml containing previews of the content:
import QtQuick 2.8
import QtQuick.Controls 2.1
TabBar {
signal closeCurrentTab
clip: true
background: Rectangle {
color: "white"
}
function addTab(imageSource) {
var component = Qt.createComponent("PreviewTabButton.qml")
if(component.status !== Component.Ready)
console.log("component not ready")
else {
var item = component.createObject()
item.setSource(imageSource)
addItem(item)
}
}
function closeTab() {
console.log("closeTab")
closeCurrentTab()
}
}
and last but not least the PreviewButton.qml using a ShaderEffectSource to render the preview:
import QtQuick 2.8
import QtQuick.Controls 2.1
TabButton {
height: 80
width: 140
function setSource(source) {
preview.sourceItem = source
}
contentItem: ShaderEffectSource {
id: preview
}
}
This example gets to about 80 tabs on my machine, after that the PreviewTabBar loses all its children (not so the StackLayout). However in the real life example with more complicated tab contents I only get up to around 8 tabs. What could I be doing wrong?
Here is the relevant part of the application output:
qml: current index 99
qml: add Tab
file:///usr/lib/qt/qml/QtQuick/Controls.2/TabButton.qml:65: TypeError: Cannot read property of null
qml: current index 100
qml: add Tab
qml: current index 1
I tried finishing the dynamic component creation in a callback as described here:
http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html#creating-a-component-dynamically
however that brough no improvement.
Here is a link to the example project:
https://www.file-upload.net/download-12341284/tabtestshader.zip.html
The most probable cause is line 17 in PreviewTabBar.qml which reads:
var item = component.createObject()
As you have no parent set in the createObject()-function the GarbageCollector tends to run wild, and delete your object, even if it is still referenced.
Though not documented that way, you should always pass a parent object, to make sure it survives the GC.
A more stable way would be to generate the Tabs from a model, and add the according model entries in the addTab-functions.
As a little remark on the side: You create a new component everytime you call one of your addTab-functions. Why don't you declare it once like
Component {
id: myComp1
...
}
and create the objects from that?

QML Settings Type does not have effect in my app

I have decided to use Qt.labs.settings 1.0 to save the state of my window in this manner:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Window 2.2
import Qt.labs.settings 1.0
ApplicationWindow {
// Main configuration section for the application window
id: mainwindow
visible: true // Needed if loading from c++.
property string accentchosen: "#F4511E"
height: Units.dp(600)
minimumHeight: Units.dp(500)
maximumHeight: Units.dp(1200)
width: Units.dp(800)
minimumWidth: Units.dp(300)
maximumWidth: Units.dp(1080)
Settings {
id: settings
property alias x: mainwindow.x
property alias y: mainwindow.y
property alias width: mainwindow.width
property alias height: mainwindow.height
property alias accentchosen: mainwindow.accentchosen
}
}
This code will result in my application starting on the x and y position it was last on, but its width and height do not seem to follow their last state, instead they keep being 600x800.
According to the docs the second time, and each subsequent time after that, it should remember its state. Am I doing something wrong?