Двойная строка состояния с PySide и QML на Nokia N9 Harmattan
Я пытаюсь использовать PySide с QML на Nokia N9, и по некоторым причинам мое тестовое приложение выглядит непохожим на нативные приложения N9. Например, здесь я получаю двойную строку состояния (они оба реагируют на нажатие).
Вот код для этого:
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_()
И файлы QML:
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"
}
}
Файл main.qml
создает PageStackWindow
и я подозреваю, что это ...Window
часть, которая заставляет телефон снова отображать строку состояния, как будто он пытается добавить строку состояния к каждому созданному окну (а здесь, может быть, у нас есть окно внутри окна?). Кроме того, между окном и панелью инструментов есть пространство. Может кто-то указать правильный способ сделать это? Я просто хочу использовать обычные страницы внутри PageStack.
2 ответа
Вы можете попробовать "showStatusBar: false". Я попробовал ваш пример на Qt Simulator, и он работает без статусбара. У меня было приложение Meego - QML - PySide, приложение QML работало без строки состояния в Qt Simulator. Но когда я попробовал его на Android с Necessitas, у меня возникла та же проблема. После того, как я использую "showStatusBar: false", проблема решена. Спасибо, я впервые запустил свое приложение QML-Meego на Android после того, как увидел ваш вопрос:)
PageStackWindow {
showStatusBar : false
Component.onCompleted: {
var pageComponent = Qt.createComponent("PageX.qml")
pageStack.push(pageComponent)
}
}
Извините, я новичок в QML. Вы можете попробовать другой пример QML Harmattan и попробовать еще раз с python, используя это view.window().showFullScreen()
Мое приложение включает ListView и основано на примере приложения на сайте документации для разработчиков Nokia Harmattan. Сначала это main.py для 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)
И QML коды:
//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" }}
}
}
}