How do I create an image button in BlackBerry 10 Cascades? - qml

I need to create custom UI elements like buttons and lists with image backgrounds in Cascades Qml, However there doesn't seem to be a way to set the background of controls such as Button.
I can't find any examples of this anywhere.
It seems like this could be possible by using a container and creating a custom control, but I don't see a way of getting that container to have an onClick event.

Custom control is actually very easy in BB10. Here's an example of what you are trying to do:
Container {
property alias text: label.text
property alias image: imagev.imageSource
ImageView {
id: imagev
imageSource: "asset:///images/Button1.png"
}
Label {
id: label
text: "demo"
}
gestureHandlers: [
TapHandler {
onTapped: {
//do tapped code
}
},
LongPressHandler {
onLongPressed: {
//do long press code
}
}
]
}
Save it as "CustomButton.qml" and then in your main QML file you can access it like so:
Page {
CustomButton {
text: "my text"
image: "images/myimage.png"
}
}

You can do this by using MouseArea element:
Item {
Image {
anchors.fill: parent
source: "yourimg.png"
}
MouseArea {
anchors.fill: parent
onClicked: {
console.log("do your action here!")
}
}
}
If you put this code in a separate QML file e.g. CustomButton.qml. You can use it in the other QML file like a custom button element:
CustomButton {
}
You can read more about this here.

Related

Retrieving the used modifiers on button click with QtQuick 2.9

I've got that pure QML application working on QtQuick 2.9.
I'm trying to retrieve the keyboard modifier used during the mouseclick.
From QtQuick 2.15, I could write this:
Button {
text: "button"
onClicked: {
if ((mouse.button == Qt.LeftButton) && (mouse.modifiers & Qt.ShiftModifier)) {
doSomething();
} else {
doSomethingElse();
}
}
}
But the MouseEvent isn't available in QtQuick 2.9.
What's the alternative ?
A Button's clicked signal does not provide a MouseEvent (no matter what version of Qt you're using). The clicked signal could be generated via the keyboard too, so it wouldn't make sense to provide a MouseEvent. You will need to create a MouseArea and handle the events yourself to do what you want.
Button {
id: button
MouseArea {
id: mouse
anchors.fill: parent
onPressed: {
if ((mouse.button == Qt.LeftButton) && (mouse.modifiers & Qt.ShiftModifier)) {
doSomething();
} else {
doSomethingElse();
}
}
}
}

Launching a new activity with onClick

I am trying to develop for BlackBerry and I am just playing around with it to try and learn the basics.
So this is really simple but how do I launch a new activity using a button?
I have the onClick property in the QML file and I don't know which code to put in the {}'s.
It's unclear what exactly do you expect but I'll give you the example of making a new Sheet. Sheets are full screen views that appear on top of your current content and are usually used for creating or editing content or other activities that are not a main focus of your application.
Lets say that you already have a Page with a button on it:
Page {
Container {
Button {
text: "Open sheet"
onClicked: {
}
}
}
}
Now to open a new Sheet when you click a button you can attach it to existing Page and define its content. After that you just need to call newSheet.open() from the onClicked() method.
Page {
Container {
Button {
text: "Open sheet"
onClicked: {
newSheet.open()
}
}
}
attachedObjects: [
Sheet {
id: newSheet
Page {
Container {
Label {
text: "Sheet"
}
Button {
text: "Close sheet"
onClicked: newSheet.close()
}
}
}
}
]
}
That is the example with opening a new Sheet when clicking the button. You should also check Tabs and NavigationPane

Pop to specific item in QtQuick StackView

I am using Qt 5.2.1 on Android, and I have a main application window with code as below (the example is a bit contrived, but it illustrates accurately what I am doing):
property Component mainMenuView: MainMenuView {
onMoviesSelected: {
stackView.push(moviesListView)
}
onSettingsSeleted: { }
onAboutSeleted: { }
}
property Component moviesListView: MovieListView {
onMovieSelected: {
stackView.push(movieDetailView)
}
onBack: stackView.pop()
}
property Component movieDetailView: MovieDetailView {
onCreditsSelected: {
stackView.push(personListView)
}
onBack: stackView.pop()
}
property Component personListView: PersonListView {
onPersonSelected: {
// Pending...
}
onBack: stackView.pop()
}
The idea is you choose from the menu, you see the movies. You choose from the movies, you see movie detail. You choose to view credits, you see the list of cast and crew. All of this uses a StackView and works just fine. The back button also works fine, popping off the views one at a time as you go back.
So now when I choose a particular person from the personListView, I want to skip right back to the moviesListView and miss out the intermediate movieDetailView. The idea is that the movie list now shows only the movies that include the selected person.
I know that I could, any maybe should, just push another moviesListView in this case - but this example is contrived to describe the general issue.
To do this, you can invoke the StackView pop() method and supply the 'item' you want to go back to - so I tried this:
property Component personListView: PersonListView {
onPersonSelected: {
stackView.pop(moviesListView)
}
onBack: stackView.pop()
}
When this runs, there are no error messages (so I assume it knows that movieListView is something that exists) but it pops back to the immediately previous view, i.e. the movieDetailView. It should miss out that view and show the movieListView.
If I try to pop back to the mainMenuView, it still just pops back to the immediately previous movieDetailView.
Is this somehow related to how I am using Component for my views and if so what should I do, or is something else wrong?
Looks like a bug. I can reproduce it with this example:
import QtQuick 2.2
import QtQuick.Controls 1.1
Rectangle {
property Component mainMenuView: Button {
text: "mainMenuView"
onClicked: {
Stack.view.push(moviesListView)
}
}
property Component moviesListView: Button {
text: "moviesListView"
onClicked: {
Stack.view.push(movieDetailView)
}
}
property Component movieDetailView: Button {
text: "movieDetailView"
onClicked: {
Stack.view.push(personListView)
}
}
property Component personListView: Button {
text: "personListView"
onClicked: {
// Wrong: goes to movieDetailView.
Stack.view.pop(moviesListView)
// Wrong: goes to mainMenuView.
// Stack.view.pop({item: moviesListView})
}
}
StackView {
initialItem: mainMenuView
}
}
I've created QTBUG-39423 for this.

Dictaphone BB10 in QML

I need make small app on BB10 using QML, which record and play some voice. I have all needed permision (microphone and store file) and this code:
import bb.cascades 1.0
import bb.multimedia 1.0
Page {
property string dataUrl;
Container {
background: Color.create("#001100")
layout: StackLayout {
}
attachedObjects: [
MediaPlayer {
id: audioPlayer
sourceUrl: dataUrl + "/recording.mp4"
},
AudioRecorder {
id: recorder
outputUrl: dataUrl + "/recording.mp4"
}
]
Button {
id: btnRecord
text: "Record"
onClicked: {
recorder.record();
}
}
Button {
id: btnStop
text: "Stop Record"
onClicked: {
recorder.reset();
}
}
Button {
text: "Play Audio"
onClicked: {
audioPlayer.play()
}
}
Button {
text: "Stop Audio"
onClicked: {audioPlayer.stop()
}
}
}
}
After running I can see all buttons, but recording and/or playing is not work. I dont know what is wrong. I cant see any errors.
You're almost there. The problem is your sourceUrl is wrong. The best place to store your recording is in your app's data directory but your QML has no idea where that is.
To solve this you need to expose your app's data path to your QML using C++. You can do this using a property (more info here).
Add the following C++ code under where you create your AbstractPane object (in my case called root). This is normally done in applicationui.cpp.
root->setProperty("dataUrl", "file://" + QDir::currentPath() + "/data");
Now add the dataUrl property to your QML and use it for your sourceUrl:
Page {
property string dataUrl;
Container {
background: Color.create("#001100")
layout: StackLayout {
}
attachedObjects: [
MediaPlayer {
id: audioPlayer
sourceUrl: dataUrl + "/recording.m4a"
},
AudioRecorder {
id: recorder
outputUrl: dataUrl + "/recording.m4a"
}
]
....
}
Edit: Make sure you call audioPlayer.reset() after you've finished recording, this forces the player to reload the recorded audio. If you don't do this your audio playback may be truncated.

blackberry 10 global tab bar application(global TabbedPane)

I am creating a application which has a global tab bar ."Actionbar" should have 5 buttons and should be seen on every screen.
Is there any way to place 5 tabs on "ActionBar" at one moment without help of "tabbed menu" ?
And how I can make this tabbed-pane global? because latter in the app I use navigationPane and it replaces tabbedpane. I want the tabbedPane bar to be visible on all screens
UPDATE ::::
I tried sheets but tabs are dissappearing
import bb.cascades 1.0
TabbedPane {
showTabsOnActionBar: true
Tab {
Page {
titleBar: TitleBar {
title: "1"
}
attachedObjects: [
ComponentDefinition {
id: mySheet
source: "sheets.qml"
}
]
Button {
onClicked: {
var sheet = mySheet.createObject();
sheet.open();
}
text: "sheet"
}
}
}
Tab {
}
}
and my sheets.qml file
import bb.cascades 1.0
Sheet {
id: mySheet
content: Page {
Container {
Label {
text: "Hi then"
}
Button {
text: "close"
onClicked: {
onClicked: mySheet.close()
}
}
}
}
}
"And how I can make this tabbedpane global? because latter in the app I use navigationPane and it replaces tabbedpane."
If I understand your question correctly, you want there to always be a tabbedpane instead of it being replaced by the navigationpane later.
What you need to to is have your tabbedpane as the main object in your qml. The navigationpane should be inside each tab, so basically 5 tabs means you would have 5 x navigation panes.
When you need to push a page, push it to the relevant tab's navigationpane.
UPDATE:
Sheets allow you to push a page ontop of the tabbedpane. Here is an example:
Create a qml file with the root item being a sheet, e.g.
Sheet {
content: Page {
Container {
... insert content
}
}
}
Then in your tabbedpane you would do the following:
inside attachedObjects
ComponentDefinition {
id: sheetDefinition
source: "mypage.qml"
}
in your function/onclick/etc:
var sheet = sheetDefinition.createObject;
sheet.open();
UPDATE 2:
To push pages within a tabbedpane do something similar to the following:
TabbedPane {
Tab {
NavigationPane {
id: tab1Nav
Page {
}
}
}
}
Then to push a page use
tab1Nav.push(page);
Or replace the content of the navigationpane to keep the tabs in place.