Reputation: 1417
I'm trying to use PySide with QML on Nokia N9, and for some reason, my test app looks unlike the native N9 apps. For example, here I get a double status bar (they both react to tapping).
Here's the code for this:
main.py
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtDeclarative import *
app = QApplication(sys.argv)
view = QDeclarativeView()
view.setResizeMode(QDeclarativeView.SizeViewToRootObject)
view.setSource('main.qml')
view.window().show()
app.exec_()
And the QML files:
main.qml
import QtQuick 1.1
import com.nokia.meego 1.1
PageStackWindow {
Component.onCompleted: {
var pageComponent = Qt.createComponent("PageX.qml")
pageStack.push(pageComponent)
}
}
PageX.qml
import QtQuick 1.1
import com.nokia.meego 1.1
Page {
id: pageOne
Text {
text: "Hello, this is page one"
}
}
The file main.qml
creates a PageStackWindow
, and I suspect it's the ...Window
part that makes the phone render the status bar again, like it tries to add a status bar to each window created (and here, maybe we have a window inside a window?). Also, there's a space between the window and the toolbar. Can someone point to the right way of doing this? I just want to use normal Pages inside a PageStack.
Upvotes: 1
Views: 531
Reputation: 525
Sorry I am new to QML. You can try a different QML Harmattan example and try again with python using this view.window().showFullScreen()
My application includes ListView and is based on an example application by Nokia Harmattan developer documentation site. First this is main.py for android:
#!/usr/bin/env python
# A simple PySide example
import sys
import os
import traceback
# log to file on Android
LOG_FOLDER = '/sdcard/'
fSock = open(os.path.join(LOG_FOLDER, 'pyside_example_log.txt'), 'w', 1)
rfSock = open(os.path.join(LOG_FOLDER, 'pyside_example_error_log.txt'), 'w', 1)
sys.stdout = fSock
sys.stderr = rfSock
print("** stdout diverted to file **")
# for some reason, the PySide bindings can't find the libshiboken.so and libshiboken,
# even though they are in a directory in LD_LIBRARY_PATH, resulting in errors like this:
#
# ImportError: Cannot load library: link_image[1965]: 157 could not load needed library
# 'libshiboken.so' for 'QtCore.so' (load_library[1120]: Library 'libshiboken.so' not found)
#
# if both are loaded to memory manually with ctypes, everything works fine
print('manual libshiboken.so and libpyside.so loading')
from ctypes import *
#PROJECT_FOLDER = '/data/data/org.modrana.PySideExample'
# PYSIDE_APPLICATION_FOLDER is set in main.h in the Example project
PROJECT_FOLDER = os.environ['PYSIDE_APPLICATION_FOLDER']
LIB_DIR = os.path.join(PROJECT_FOLDER, 'files/python/lib')
SHIBOKEN_SO = os.path.join(LIB_DIR, 'libshiboken.so')
PYSIDE_SO = os.path.join(LIB_DIR, 'libpyside.so')
print("path to libshiboken and libpyside:")
print(SHIBOKEN_SO)
print(PYSIDE_SO)
shibok = CDLL(SHIBOKEN_SO)
psde = CDLL(PYSIDE_SO)
print("manual loading done")
print("importing PySide")
from PySide import QtCore, QtGui
from PySide.QtCore import QObject
from PySide.QtGui import *
from PySide.QtDeclarative import *
print("PySide import done")
#print(os.environ)
# enable running this program from absolute path
os.chdir(os.path.dirname(os.path.abspath(__file__)))
print("dir changed")
class PropertyExample(QObject):
"""
Python property provider
"""
def __init__(self):
QObject.__init__(self)
self.rootObject = None
#NOTE: the root object is needed only by Python properties
# that call QML code directly
"""@QtCore.Slot(result=str)
def getDate(self):
return str(datetime.datetime.now())"""
"""@QtCore.Slot(str)
def notify(self, text):
#NOTE: QML uses <br> instead of \n for linebreaks
self.rootObject.notify(text)
"""
class ImagesFromPython(QDeclarativeImageProvider):
"""
Image provider example
"""
def __init__(self):
# this image provider supports QImage,
# as specified by the ImageType
QDeclarativeImageProvider.__init__(self, QDeclarativeImageProvider.ImageType.Image)
def main():
app = QApplication(sys.argv) # create the application
view = QDeclarativeView() # create the declarative view
# add Python properties to the
# QML root context
rc = view.rootContext()
# add the example property
property = PropertyExample()
rc.setContextProperty("example", property)
# register image providers
# NOTE: the image provider name in the Image.source URL is automatically lower-cased !!
# NOTE2: view.engine().addImageProvider("from_python", ImagesFromPython())
# doesn't work for some reason
view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
view.setSource("main.qml")
rootObject = view.rootObject()
property.rootObject = rootObject
#view.setWindowTitle(WINDOW_TITLE)
# view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
#view.setResizeMode(QDeclarativeView.SizeViewToRootObject)
view.window().showFullScreen()
# view.resize(480,854)
#view.resize(854,480)
view.show()
app.exec_()
if __name__ == '__main__':
print("__main__")
fSock.flush()
try:
main()
except Exception:
fp = open(os.path.join(LOG_FOLDER, 'pyside_example_exception_log.txt'), 'w', 0)
traceback.print_exc(file=fp)
fp.flush()
fp.close()
traceback.print_exc(file=fSock)
fSock.flush()
rfSock.flush()
rfSock.close()
fSock.flush()
fSock.close()
exit(0)
And QML codes:
//main.qml
import QtQuick 1.1
import com.nokia.meego 1.1
PageStackWindow {
id: rootWindow
property int pageMargin: 16
// ListPage is shown when the application starts, it links to
// the component specific pages
initialPage: MainPage { }
// These tools are shared by most sub-pages by assigning the
// id to a tools property of a page
ToolBarLayout {
id: commonTools
visible: false
ToolIcon {
iconId: "toolbar-back";
onClicked: { myMenu.close(); pageStack.pop(); }
}
ToolIcon {
iconId: "toolbar-view-menu";
onClicked: (myMenu.status == DialogStatus.Closed) ? myMenu.open() : myMenu.close()
}
}
}
//MainPage.qml
import QtQuick 1.1
import com.nokia.meego 1.1
Page {
id: listPage
anchors.margins: rootWindow.pageMargin
function openFile(file) {
var component = Qt.createComponent(file)
if (component.status == Component.Ready)
pageStack.push(component);
else
console.log("Error loading component:", component.errorString());
}
ListModel {
id: pagesModel
ListElement {
page: "SimpleExamplesPage.qml"
title: "Simple examples"
subtitle: "Buttons, TextField, ToolBar and ViewMenu"
}
ListElement {
page: "DialogsPage.qml"
title: "Dialogs"
subtitle: "How to use different dialogs"
}
}
ListView {
id: listView
anchors.fill: parent
model: pagesModel
delegate: Item {
id: listItem
height: 88
width: parent.width
BorderImage {
id: background
anchors.fill: parent
// Fill page borders
anchors.leftMargin: -listPage.anchors.leftMargin
anchors.rightMargin: -listPage.anchors.rightMargin
visible: mouseArea.pressed
source: "image://theme/meegotouch-list-background-pressed-center"
}
Row {
anchors.fill: parent
Column {
anchors.verticalCenter: parent.verticalCenter
Label {
id: mainText
text: model.title
font.weight: Font.Bold
font.pixelSize: 26
}
Label {
id: subText
text: model.subtitle
font.weight: Font.Light
font.pixelSize: 22
color: "#cc6633"
visible: text != ""
}
}
}
Image {
source: "image://theme/icon-m-common-drilldown-arrow" + (theme.inverted ? "-inverse" : "")
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
id: mouseArea
anchors.fill: background
onClicked: {
listPage.openFile(page)
}
}
}
}
ScrollDecorator {
flickableItem: listView
}
}
//DialogsPage.qml
import QtQuick 1.1
import com.nokia.meego 1.1
Page {
id: root
tools: tabTools
anchors.margins: rootWindow.pageMargin
QueryDialog {
id: query
icon: "image://theme/icon-l-contacts"
titleText: "Query Dialog Example"
message: "Press accept or reject button"
acceptButtonText: "Accept"
rejectButtonText: "Reject"
onAccepted: labelQueryResult.text = "Result: Accepted";
onRejected: labelQueryResult.text = "Result: Rejected";
}
SelectionDialog {
id: singleSelectionDialog
titleText: "Single Selection Dialog Header"
selectedIndex: 1
model: ListModel {
ListElement { name: "ListElement #1" }
ListElement { name: "ListElement #2" }
ListElement { name: "ListElement #3" }
ListElement { name: "ListElement #4" }
ListElement { name: "ListElement #5" }
ListElement { name: "ListElement #6" }
ListElement { name: "ListElement #7" }
ListElement { name: "ListElement #8" }
ListElement { name: "ListElement #9" }
ListElement { name: "ListElement #10" }
}
}
// Create page and buttons
ScrollDecorator {
flickableItem: container
}
Flickable {
id: container
x: 0 // we need to set the width and height
y: 0
width: root.width
height: root.height
contentWidth: dialogs.width
contentHeight: dialogs.height
flickableDirection: Flickable.VerticalFlick
pressDelay: 100
Column {
id: dialogs
spacing: 24
Row {
spacing: 32
Button {
text: "Query"
width: 200
onClicked: {
query.open();
}
}
Label {
id: labelQueryResult
text: "Result: N/A"
}
}
Row {
spacing: 32
Button {
text: "SingleSelection"
width: 200
onClicked: {
singleSelectionDialog.open();
}
}
Grid {
rows: screen.orientation == Screen.Landscape || screen.orientation == Screen.LandscapeInverted ? 1 : 2
Rectangle {
width: 200
height: 30
color: "white"
Text {
y: 10
anchors.centerIn: parent
text: "Selected:"
font.pixelSize: 15
font.bold: true
}
}
Rectangle {
width: 200
height: 30
color: "lightgray"
Text {
anchors.centerIn: parent
text: singleSelectionDialog.model.get(singleSelectionDialog.selectedIndex).name
font.pixelSize: 15
font.bold: true
}
}
}
}
Row {
spacing: 32
Button {
text: "Color menu"
width: 200
onClicked: {
colorMenu.open();
}
}
Rectangle {
id : colorRect
width: 50; height: 50;
color : "black"
MouseArea {
anchors.fill: parent
onClicked: { colorMenu.open(); }
}
}
}
}
}
ToolBarLayout {
id: tabTools
ToolIcon { iconId: "toolbar-back"; onClicked: { colorMenu.close(); pageStack.pop(); } }
ToolIcon { iconId: "toolbar-view-menu" ; onClicked: colorMenu.open(); }
}
Menu {
id: colorMenu
visualParent: pageStack
MenuLayout {
MenuItem {text: "Red"; onClicked: { colorRect.color = "darkred" } }
MenuItem {text: "Green"; onClicked: { colorRect.color = "darkgreen" }}
MenuItem {text: "Blue"; onClicked: { colorRect.color = "darkblue" }}
MenuItem {text: "Yellow"; onClicked: { colorRect.color = "yellow" }}
}
}
}
Upvotes: 0
Reputation: 525
You can try "showStatusBar : false". I tryed your example on Qt Simulator, and it works without statusbar. I had a Meego - QML - PySide application, QML app worked without statusbar on Qt Simulator. But When I tryed it on android with Necessitas, I got same problem. After I use "showStatusBar : false" problem solved. Thank you, It is first time I ran my QML-Meego application on android after I saw your question :)
PageStackWindow {
showStatusBar : false
Component.onCompleted: {
var pageComponent = Qt.createComponent("PageX.qml")
pageStack.push(pageComponent)
}
}
Upvotes: 1