BlackBerry 10 - Adding ImageView to Container - c++

I'm trying to add an ImageView to container, by it doesn't appear on the screen.
Container is created in QML, but I want image to be added in .CPP file.
ApplicationUI.cpp:
ApplicationUI::ApplicationUI(bb::cascades::Application *app)
: QObject(app)
{
QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
AbstractPane *root = qml->createRootObject<AbstractPane>();
ImageView* imageView1 = new ImageView();
imageView1->setImage(Image("asset:///icon.png"));
Page *page = qml->createRootObject<Page>();
Container *_mRootContainer = page->findChild<Container*>("rootContainer");
_mRootContainer->add( imageView1 );
app->setScene(root);
}
main.xml:
import bb.cascades 1.0
Page {
Container {
objectName: "rootContainer"
Label {
text: "First page"
}
}
}
Thanks in advance ;)

You can create an image container in your .CPP file and then create/add all your images to your container. Eg: using the DockLayout here for images ontop of each other and centered them within parent container.
//Create the images container and center it within parent container
Container *imageContainer = new Container();
imageContainer->setLayout(new DockLayout());
imageContainer->setHorizontalAlignment(HorizontalAlignment::Center);
//Create the image (add the image file into asset folder)
ImageView* imageView1 = ImageView::create("asset:///icon.png");
//Align/center image horizontally and vertically within parent container
imageView1->setHorizontalAlignment(HorizontalAlignment::Center);
imageView1->setVerticalAlignment(VerticalAlignment::Center);
//Add images to image container
imageContainer->add(imageView1);

I recommed to show the image in a WebView
Best of luck

Related

How load QImage from path?

I captured an Image with camera in my qt quick application.I want to send the path to my c++ code and load that Image in c++ QImage.But the Path is image://camera/preview_1 and I don't know How work with that path?
Camera {
id: camera
imageCapture {
onImageCaptured: {
console.log("Preview = "+preview);
photoPreview.source = preview
console.log("CapturedImagePath => "+camera.imageCapture.capturedImagePath);
up.loadImage(preview);
}
}
c++ class
void UserProfile::loadImage(QString path)
{
QUrl imageUrl(path);
qWarning()<<"imageUrl.host()=>"<<imageUrl.host();
qWarning()<<"imageUrl.path()=>"<<imageUrl.path();
qWarning()<<"imageUrl.toLocalFile()=>"<<imageUrl.toLocalFile();
bool isOpend= m_image.load(path); //m_image is an QImage object
qWarning()<<"Image loaded=> "<<isOpend;
}
Application output
D MyApp: qml: Preview = image://camera/preview_1
D MyApp: qml: CapturedImagePath =>
W MyApp: imageUrl.host()=> "camera"
W MyApp: imageUrl.path()=> "/preview_1"
W MyApp: imageUrl.toLocalFile()=> ""
W MyApp: Image loaded=> false
The URL image://camera/preview_1 means that the image data is living in a QQuickImageProvider instance. Probably, it's a QQuickImageProvider instance created by Camera.
As the UserProfile instance is living in the same QQmlEngine as the camera lives, you can
void UserProfile::loadImage(const QString &path)
{
auto myQmlEngine = qmlEngine(this);
if(myQmlEngine==nullptr)
return;
QUrl imageUrl(path);
auto provider = reinterpret_cast<QQuickImageProvider*>( myQmlEngine->imageProvider(imageUrl.host()));
if (provider->imageType()==QQuickImageProvider::Image){
QImage img = provider->requestImage(imageUrl.path().remove(0,1),nullptr,QSize());
// do whatever you want with the image
}
}
Be careful with the reinterpret_cast. You also have to make sure that the QQuickImageProvider::imageType() is returning QQmlImageProviderBase::Image.
and you could also use capturedImagePath instead of the preview URL to prevent this complexity if it could be an option for your usecase.

Save QML image inside c++

I am trying to display network image using qml and then save this image using c++ code,
Here is the qml code,
import QtQuick 2.3
import QtQuick.Window 2.2
import com.login 1.0
Window {
visible: true
width : 500
height: 500
Login{id: login}
MouseArea {
anchors.fill: parent
onClicked: {
// Qt.quit();
login.save(image);
}
}
Image {
id: image
source: "http://www.test.com/webp/gallery/4.jpg"
}
}
And inside my login class saving image like,
void Login::save( QQuickItem *item)
{
qDebug()<<"width: "<<item->width();
qDebug()<<"height: "<<item->height();
QQuickWindow *window = item->window();
QImage image = window->grabWindow();
QPixmap pix = QPixmap::fromImage(image);
pix.save("C:/Users/haris/Desktop/output.png");
}
I am getting the correct width and height of the image inside c++ class, but the problem is I cannot find a way to save the image item from QQuickItem.
Right now I am saving the image by grabing the window, which actually not giving the actual image size on output file, instead giving output file with current qml window size.
Basically I am following the code here saving QML image but it seems QDeclarativeItem is deprecated in Qt5, so I choose QQuickItem where as there is no paint option in QQuickItem.
Fortunately QQuickItem has a convenient grabToImage function which does that.
void Login::save( QQuickItem *item)
{
QSharedPointer<const QQuickItemGrabResult> grabResult = item->grabToImage();
connect(grabResult.data(), &QQuickItemGrabResult::ready, [=]() {
grabResult->saveToFile("C:/Users/haris/Desktop/output.png");
//grabResult->image() gives the QImage associated if you want to use it directly in the program
});
}
Alternate solution without using lambdas:
void Login::save( QQuickItem *item)
{
QSharedPointer<const QQuickItemGrabResult> grabResult = item->grabToImage();
/* Need to store grabResult somewhere persistent to avoid the SharedPointer mechanism from deleting it */
...
connect(grabResult.data(), SIGNAL(ready()), this, SLOT(onAsynchroneousImageLoaded()));
}
void Login::onAsynchroneousImageLoaded() {
auto grabResult = qobject_cast<const QQuickItemGrabResult*>(sender());
if (grabResult) {
grabResult->saveToFile("C:/Users/haris/Desktop/output.png");
} else {
//something went wrong
}
});
In a QObject-derived class (ImageSaver) register it as you would. It needs one member:
bool ImageSaver::saveImage(const QUrl &imageProviderUrl, const QString &filename){
qDebug() << Q_FUNC_INFO <<imageProviderUrl << filename;
QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
QQmlImageProviderBase *imageProviderBase = engine->imageProvider(imageProviderUrl.host());
QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase);
QSize imageActualSize;
QSize imageRequestedSize;
QString imageId = imageProviderUrl.path().remove(0,1);
QImage image = imageProvider->requestImage(imageId, &imageActualSize, imageRequestedSize);
qDebug() << Q_FUNC_INFO << imageId << imageActualSize;
return image.save(filename);
}
then in QML:
ImageSaver { id: imageSaver}
...
imageSaver.saveImage(image.source, "my.png");
...
Whereas grabToImage will grab the item using the items's size, this can preserve the actual size of the image.

CCNode tag - Shows all tags are same

I am new to cocos2d game development.I have subclassed a CCNode,and i am looping to add this subclass to the game layer setting the tag for this node.In the m file of this subclass i am using the touches delegate to detect the element.But the console shows that for any object of this node created tag's are the same.
You must initialise tag for each node. Use uniq integer number as tag. Better use enum.
typedef enum
{
kEnemy_Dog = 1000,
kEnemy_Cat,
kEnemy_Rat,
kEnemy_Bat
}EnemyType;
typedef enum
{
kHeroType_Lion = 2000,
kHeroType_Tiger,
kHeroType_Dino,
kEnemy_Eagle
}HeroType;
CCSprite *dog = [CCSprite spriteWithFile:TEX_DOG];
dog.tag = kEnemy_Dog;
[self addChild:dog z:2 tag: kEnemy_Dog];
CCSprite *lion = [CCSprite spriteWithFile:TEX_DOG];
lion.tag = kHeroType_Lion;
[self addChild:dog z:2 tag: kHeroType_Lion];
//to check
if(inSprite.tag == kHeroType_Lion)

Viewport size adjustment of ScrollView in BlackBerry10

Hi I need to adjust the viewport of the ScrollView so that it shows up in the middle of the screen. I tried all the properties that I can think of.
Page *page = new Page();
Container *container = new Container();
AbsoluteLayout *absoluteLayout = new AbsoluteLayout();
container->setLayout(absoluteLayout);
for(int y=0;y<1536;y+=256)
{
for(int x=0;x<1536;x+=256)
{
AbsoluteLayoutProperties *imageProperties = AbsoluteLayoutProperties::create().x(x).y(y);
ImageView *imageView = ImageView::create().layoutProperties(imageProperties);
imageView->setImage(Image("assets/tile256.jpg"));
container->add(imageView);
}
}
ScrollView *scrollView = ScrollView::create(container).preferredSize(300,300);
scrollView->setHorizontalAlignment(HorizontalAlignment::Center);
scrollView->setVerticalAlignment(VerticalAlignment::Center);
scrollView->setMaxHeight(300);
scrollView->setMaxWidth(300);
ScrollViewProperties *scrollViewProperties = scrollView->scrollViewProperties();
scrollViewProperties->setScrollMode(ScrollMode::Both);
scrollView->zoomToPoint(300,500,1);
QRectF qRectf = scrollView->viewableArea();
qRectf.setX(300);
qRectf.setY(300);
page->setContent(scrollView);
app->setScene(page);
Here is what I tried.
To dock a control at a specific area, set layout of the container DockLayout and add controls in it. So, even if the control is expanded/contracted it will dock at specified area. Here, add ScrollView in a Container and set that container as content of the page.
Page *page = new Page();
Container *mainContainer = new Container(); //This is the main container of the page
mainContainer->setLayout(new DockLayout()); //To dock scroll view at center of the screen
Container *container = new Container();
...
...
...
mainContainer->add(scrollView);//Add scroll view to the main container
page->setContent(mainContainer);//Set main container as the content
app->setScene(page);

QScrollArea with multiple QWidgets only shows empty box

I am trying to create a widget that would display some information. Each information would be a QWidget that contains multiple QLabel with text (the information). My idea is to put multiple (array of these) into a QScrollArea so that the user can view them scrolling up and down. The following code:
InfoWidget::InfoWidget(QWidget* parent) : QWidget(parent){
widgets = new QVector<MarkerInfoWidget*>();
csv_data = 0;
csv_velocity = 0;
labels = 0;
infoWidgetLayout = new QVBoxLayout(this);
setLayout(infoWidgetLayout);
scrollArea = new QScrollArea(this);
scrollWidgetLayout = new QVBoxLayout(scrollArea);
scrollArea->setLayout(scrollWidgetLayout);
infoWidgetLayout->addWidget(scrollArea);
//Test
QString name = "TEST";
for(int i=0; i<10; i++){
MarkerInfoWidget* markerWidget = new MarkerInfoWidget(name, scrollArea);
scrollWidgetLayout->addWidget(markerWidget);
widgets->append(markerWidget);
}
}
Both MarkerInfoWidget and InfoWidget extends QWidget. What I am getting is simply a box that has very small text:
If I drag it out and re-size it, it display correctly:
What I have noticed is that if I re-size it too small, it does not generate scrolls. What do I need to fix this?
I guess changing:
scrollArea->setLayout(scrollWidgetLayout);
to sth like:
QFrame* frame = new QFrame(scrollArea);
frame->setLayout(scrollWidgetLayout);
scrollArea->setWidget(frame);
As far as i know you have to put widget into QScrollableArea to make it really scrollable. Setting its layout is probably not the thing you want to do.