What to do to make "onEntered" working? - qml

I have a custom QDeclarativeItem subclass named Polygon.
I add a MouseArea in it but onEntered or onPressed does not working, or am i expect wrong thing to happen? I can see my polygons on the window but nothing is writing on console onPressed or onEntered.
Here is QML file:
import MyTypes 1.0
import QtQuick 1.0
import Qt 4.7
Item {
id: container
width: 350; height: 250
Polygon {
id: aPolygon
width: 20; height: 20
name: "A simple polygon"
color: "blue"
vertices:[
Point{x:20.0; y:40.0},
Point{x:40.0; y:40.0},
Point{x:40.0; y:20.0},
Point{x:20.0; y:20.0}
]
MouseArea{
anchors.fill: parent
drag.target: aPolygon
drag.axis: Drag.XandYAxis
drag.minimumX: 0
drag.maximumX: container.width - parent.width
drag.minimumY: 0
drag.maximumY: container.height - parent.width
onPressed:console.log("============== ==onPressed")
}
}
Polygon {
id: bPolygon
//anchors.centerIn: parent
width: 20; height: 20
name: "A simple polygon"
color: "blue"
vertices:[
Point{x:60.0; y:80.0},
Point{x:80.0; y:80.0},
Point{x:80.0; y:60.0},
Point{x:60.0; y:60.0}
]
MouseArea{
//hoverEnabled: false
enabled: visible
hoverEnabled: visible
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onEntered: {
console.log("============== ==onEntered")
}
}
}
}
Thanks for any idea.
Edit:
polygon.cpp
#include "polygon.h"
#include "point.h"
#include <QPainter>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <QGraphicsSceneDragDropEvent>
#include <QFocusEvent>
#include "DeclarativeDragDropEvent.h"
using namespace std;
using namespace Qt;
Polygon::Polygon(QDeclarativeItem *parent)
: QDeclarativeItem(parent)
{
// need to disable this flag to draw inside a QDeclarativeItem
//setFlag(QDeclarativeItem::ItemHasNoContents, false);
setFlags(ItemIsSelectable|ItemIsMovable|ItemIsFocusable);
setAcceptDrops(true);
setAcceptedMouseButtons( Qt::LeftButton );
}
/*void Polygon::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
forceActiveFocus();
}
void Polygon::focusOutEvent(QFocusEvent *event)
{
cout<<"focusout"<<endl;
this->setSelected( false );
}*/
/*QVariant Polygon::itemChange(GraphicsItemChange change, const QVariant &value)
{
return QGraphicsItem::itemChange(change, value);
}*/
/*void Polygon::focusInEvent ( QFocusEvent * event ){
cout<<"focusin"<<endl;
}*/
QRectF Polygon::boundingRect() const{
QVector<QPointF> vPnt=listToVector(m_vertices);
return QPolygonF(vPnt).boundingRect();
}
QPainterPath Polygon::shape () const
{
QPainterPath path;
QVector<QPointF> vPnt=listToVector(m_vertices);
path.addPolygon(QPolygonF(vPnt));
return path;
}
QString Polygon::name() const
{
return m_name;
}
void Polygon::setName(const QString &name)
{
m_name = name;
}
QColor Polygon::color() const
{
return m_color;
}
void Polygon::setColor(const QColor &color)
{
m_color = color;
}
void Polygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
QPen pen(m_color, 2);
painter->setPen(pen);
painter->setRenderHints(QPainter::Antialiasing, true);
QVector<QPointF> vPnt=listToVector(m_vertices);
painter->setBrush(QBrush(m_color,Qt::SolidPattern));
painter-> drawPolygon(QPolygonF(vPnt),Qt::OddEvenFill);
}
QVector<QPointF> Polygon:: listToVector(QList<Point *> lpnt) const{
QVector<QPointF> vPnt;
for(int i=0;i<lpnt.length();i++){
vPnt.append(QPointF(lpnt.at(i)->x(),lpnt.at(i)->y()));
}
return vPnt;
}
QDeclarativeListProperty<Point> Polygon::vertices()
{
return QDeclarativeListProperty<Point>(this, 0, &Polygon::append_vertex);
}
void Polygon::append_vertex(QDeclarativeListProperty<Point> *list, Point *vertex)
{
Polygon *polygon = qobject_cast<Polygon *>(list->object);
if (polygon) {
vertex->setParentItem(polygon);
polygon->m_vertices.append(vertex);
}
}

I believe you should set hoverEnabled to true, or is this intentionally set to visible? visible is a boolean property which might be false for a MouseArea.
MouseArea {
hoverEnabled: true
}
The same goes for enabled: visible

Related

Flutter fileimage not appearing in page flip animation widget

I want to create a book app like google's play book application
my books are in pdf, Im getting them from Firebase storage, then im converting that pdf to image, page by page, its working fine
but when I try to put the file inside the PageFlip widget, it doesn't work as intended... it starts converting pdf to images, all good, then shows blank screen, when I press ctrl+s to refresh, then it does the conversion again, then it works
when I restart the app, again first time shows blank screen, after refresh it works fine
I can swipe through the images and animation works fine on them, but some pages are still blank, they're not rendered as image
for example, im on page 1 I swipe, page 2 (shows fine), again, page 3 (shows fine).... page 22(is blank/not rendered), page 23(shows fine)
the animation is a bit laggy too, not as smooth as playbooks application,
can someone help please?
My code
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:internet_file/internet_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pdfx/pdfx.dart';
import 'package:show_up_animation/show_up_animation.dart';
import '../helpers/ui_control.dart';
import '../models/book.dart';
import '../providers/book.dart';
import '../providers/loading.dart';
import '../providers/user.dart';
import '../widgets/featured_book.dart';
import '../widgets/page_flip.dart';
import '../widgets/slide_route.dart';
class BookView extends StatefulWidget {
const BookView({Key? key, required this.book, required this.currentPage})
: super(key: key);
final BookModel book;
final int currentPage;
#override
_BookViewState createState() => _BookViewState();
}
class _BookViewState extends State<BookView> {
late int page;
bool show = true;
Future<List<File>> pdfToImages(Future<PdfDocument> pdf) async {
final pdfDoc = await pdf;
List<File> images = [];
print('converting pdf to image');
for (int i = 1; i <= pdfDoc.pagesCount; i++) {
final tempDir = await getTemporaryDirectory();
File file =
File('${tempDir.path}/${widget.book.id}-${widget.book.title}-$i.png');
if (!file.existsSync()) {
final page = await pdfDoc.getPage(i);
final image = await page.render(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
backgroundColor: "#EFEADD",
);
Uint8List imageInUnit8List = image!.bytes;
file.writeAsBytesSync(imageInUnit8List);
page.close();
}
images.add(file);
}
return images;
}
#override
void initState() {
super.initState();
page = widget.currentPage;
}
void _onTap() {
setState(() {
show = !show;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: FutureBuilder<List<File>>(
future: pdfToImages(
PdfDocument.openData(InternetFile.get(widget.book.path))),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text(snapshot.error.toString()));
}
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: _onTap,
child: InteractiveViewer(
child: PageFlipWidget(
backgroundColor: const Color(0xFFEFEADD),
lastPage: Image.file(
snapshot.data!.elementAt(widget.book.pageCount - 1)),
onMiddleTap: _onTap,
children: List.generate(widget.book.pageCount, (index) {
return Image.file(
snapshot.data!.elementAt(index),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
);
}),
),
),
);
}),
);
}
}
Page flip animation widget
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'dart:ui' as ui;
import 'package:flutter/rendering.dart';
class PageFlipWidget extends StatefulWidget {
const PageFlipWidget({
Key? key,
this.duration = const Duration(milliseconds: 450),
this.cutoff = 0.6,
this.backgroundColor = const Color(0xFFFFFFFF),
required this.children,
this.initialIndex = 0,
this.lastPage,
this.showDragCutoff = false,
required this.onMiddleTap,
}) : super(key: key);
final Color backgroundColor;
final List\<Widget\> children;
final Duration duration;
final int initialIndex;
final Widget? lastPage;
final bool showDragCutoff;
final double cutoff;
final VoidCallback onMiddleTap;
#override
PageFlipWidgetState createState() =\> PageFlipWidgetState();
}
class PageFlipWidgetState extends State\<PageFlipWidget\>
with TickerProviderStateMixin {
int pageNumber = 0;
List\<Widget\>? pages = \[\];
final List\<AnimationController\> \_controllers = \[\];
bool? \_isForward;
#override
void didUpdateWidget(PageFlipWidget oldWidget) {
if (oldWidget.children != widget.children) {
\_setUp();
}
if (oldWidget.duration != widget.duration) {
\_setUp();
}
if (oldWidget.backgroundColor != widget.backgroundColor) {
\_setUp();
}
super.didUpdateWidget(oldWidget);
}
#override
void dispose() {
for (var c in \_controllers) {
c.dispose();
}
super.dispose();
}
#override
void initState() {
super.initState();
\_setUp();
}
void \_setUp() {
\_controllers.clear();
pages?.clear();
for (var i = 0; i < widget.children.length; i++) {
final controller = AnimationController(
value: 1,
duration: widget.duration,
vsync: this,
);
_controllers.add(controller);
final child = PageFlipBuilder(
backgroundColor: widget.backgroundColor,
amount: controller,
child: widget.children[i],
);
pages?.add(child);
}
pages = pages?.reversed.toList();
pageNumber = widget.initialIndex;
}
bool get \_isLastPage =\>
pages != null && (pages?.length ?? 0 - 1) == pageNumber;
bool get \_isFirstPage =\> pageNumber == 0;
void \_flipPage(DragUpdateDetails details, BoxConstraints dimens) {
final ratio = details.delta.dx / dimens.maxWidth;
if (\_isForward == null) {
if (details.delta.dx \> 0) {
\_isForward = false;
} else {
\_isForward = true;
}
}
if (\_isForward! || pageNumber == 0) {
\_isLastPage ? null : \_controllers\[pageNumber\].value += ratio;
} else {
\_controllers\[pageNumber - 1\].value += ratio;
}
}
Future \_onDragFinish() async {
if (\_isForward != null) {
if (\_isForward!) {
if (!\_isLastPage &&
\_controllers\[pageNumber\].value \<= (widget.cutoff + 0.15)) {
await nextPage();
} else {
\_isLastPage ? null : await \_controllers\[pageNumber\].forward();
}
} else {
if (!\_isFirstPage &&
\_controllers\[pageNumber - 1\].value \>= widget.cutoff) {
await previousPage();
} else {
if (\_isFirstPage) {
await \_controllers\[pageNumber\].forward();
} else {
\_isFirstPage ? null : await \_controllers\[pageNumber - 1\].reverse();
}
}
}
}
\_isForward = null;
}
Future nextPage() async {
await \_controllers\[pageNumber\].reverse();
if (mounted) {
setState(() {
pageNumber++;
});
}
}
Future previousPage() async {
await \_controllers\[pageNumber - 1\].forward();
if (mounted) {
setState(() {
pageNumber--;
});
}
}
Future goToPage(int index) async {
if (mounted) {
setState(() {
pageNumber = index;
});
}
for (var i = 0; i \< \_controllers.length; i++) {
if (i == index) {
\_controllers\[i\].forward();
} else if (i \< index) {
// \_controllers\[i\].value = 0;
\_controllers\[i\].reverse();
} else {
if (\_controllers\[i\].status == AnimationStatus.reverse) {
\_controllers\[i\].value = 1;
}
}
}
}
#override
Widget build(BuildContext context) {
return Material(
child: LayoutBuilder(
builder: (context, dimens) =\> GestureDetector(
behavior: HitTestBehavior.opaque,
onHorizontalDragCancel: () =\> \_isForward = null,
onHorizontalDragUpdate: (details) =\> \_flipPage(details, dimens),
onHorizontalDragEnd: (details) =\> \_onDragFinish(),
child: Stack(
fit: StackFit.expand,
children: \<Widget\>\[
if (widget.lastPage != null) ...\[
widget.lastPage!,
\],
...pages!,
Positioned.fill(
child: Flex(
direction: Axis.horizontal,
children: \<Widget\>\[
Flexible(
flex: (widget.cutoff \* 0.75 \* 10).round(),
child: Container(
color: widget.showDragCutoff
? Colors.blue.withAlpha(100)
: null,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: \_isFirstPage ? null : previousPage,
),
),
),
Flexible(
flex: 10,
child: Container(
color: widget.showDragCutoff
? Colors.orange.withAlpha(100)
: null,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: widget.onMiddleTap,
),
),
),
Flexible(
flex: (widget.cutoff \* 0.75 \* 10).round(),
child: Container(
color: widget.showDragCutoff
? Colors.red.withAlpha(100)
: null,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: \_isLastPage ? null : nextPage,
),
),
),
\],
),
),
\],
),
),
),
);
}
}
class PageFlipEffect extends CustomPainter {
PageFlipEffect({
required this.amount,
required this.image,
this.backgroundColor,
this.radius = 0.18,
}) : super(repaint: amount);
final Animation\<double\> amount;
final ui.Image image;
final Color? backgroundColor;
final double radius;
#override
void paint(ui.Canvas canvas, ui.Size size) {
final pos = amount.value;
final movX = (1.0 - pos) \* 0.85;
final calcR = (movX \< 0.20) ? radius \* movX \* 5 : radius;
final wHRatio = 1 - calcR;
final hWRatio = image.height / image.width;
final hWCorrection = (hWRatio - 1.0) / 2.0;
final w = size.width.toDouble();
final h = size.height.toDouble();
final c = canvas;
final shadowXf = (wHRatio - movX);
final shadowSigma =
Shadow.convertRadiusToSigma(8.0 + (32.0 * (1.0 - shadowXf)));
final pageRect = Rect.fromLTRB(0.0, 0.0, w * shadowXf, h);
if (backgroundColor != null) {
c.drawRect(pageRect, Paint()..color = backgroundColor!);
}
if (pos != 0) {
c.drawRect(
pageRect,
Paint()
..color = Colors.black54
..maskFilter = MaskFilter.blur(BlurStyle.outer, shadowSigma),
);
}
final ip = Paint();
for (double x = 0; x < size.width; x++) {
final xf = (x / w);
final v = (calcR * (math.sin(math.pi / 0.5 * (xf - (1.0 - pos)))) +
(calcR * 1.1));
final xv = (xf * wHRatio) - movX;
final sx = (xf * image.width);
final sr = Rect.fromLTRB(sx, 0.0, sx + 1.0, image.height.toDouble());
final yv = ((h * calcR * movX) * hWRatio) - hWCorrection;
final ds = (yv * v);
final dr = Rect.fromLTRB(xv * w, 0.0 - ds, xv * w + 1.0, h + ds);
c.drawImageRect(image, sr, dr, ip);
}
}
#override
bool shouldRepaint(PageFlipEffect oldDelegate) {
return oldDelegate.image != image ||
oldDelegate.amount.value != amount.value;
}
}
class PageFlipBuilder extends StatefulWidget {
const PageFlipBuilder({
Key? key,
required this.amount,
this.backgroundColor = const Color(0xFFFFFFCC),
this.child,
}) : super(key: key);
final Animation\<double\> amount;
final Color backgroundColor;
final Widget? child;
#override
State\<PageFlipBuilder\> createState() =\> \_PageFlipBuilderState();
}
class \_PageFlipBuilderState extends State\<PageFlipBuilder\> {
final \_boundaryKey = GlobalKey();
ui.Image? \_image;
#override
void didUpdateWidget(PageFlipBuilder oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.child != widget.child) {
\_image = null;
}
}
void \_captureImage(Duration timeStamp) async {
final pixelRatio = MediaQuery.of(context).devicePixelRatio;
final boundary = \_boundaryKey.currentContext?.findRenderObject()
as RenderRepaintBoundary;
if (boundary.debugNeedsPaint) {
await Future.delayed(const Duration(milliseconds: 20));
return \_captureImage(timeStamp);
}
final image = await boundary.toImage(pixelRatio: pixelRatio);
setState(() =\> \_image = image);
}
#override
Widget build(BuildContext context) {
if (\_image != null) {
return CustomPaint(
painter: PageFlipEffect(
amount: widget.amount,
image: \_image!,
backgroundColor: widget.backgroundColor,
),
size: Size.infinite,
);
} else {
WidgetsBinding.instance.addPostFrameCallback(\_captureImage);
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final size = constraints.biggest;
return Stack(
clipBehavior: Clip.hardEdge,
children: \<Widget\>\[
Positioned(
left: 1 + size.width,
top: 1 + size.height,
width: size.width,
height: size.height,
child: RepaintBoundary(
key: \_boundaryKey,
child: widget.child,
),
),
\],
);
},
);
}
}
}
class PageFlipImage extends StatefulWidget {
const PageFlipImage({
Key? key,
required this.amount,
this.image,
this.backgroundColor = const Color(0xFFFFFFCC),
}) : super(key: key);
final Animation\<double\> amount;
final ImageProvider? image;
final Color? backgroundColor;
#override
State\<PageFlipImage\> createState() =\> \_PageFlipImageState();
}
class \_PageFlipImageState extends State\<PageFlipImage\> {
ImageStream? \_imageStream;
ImageInfo? \_imageInfo;
bool \_isListeningToStream = false;
late ImageStreamListener \_imageListener;
#override
void initState() {
super.initState();
\_imageListener = ImageStreamListener(\_handleImageFrame);
}
#override
void dispose() {
\_stopListeningToStream();
super.dispose();
}
#override
void didChangeDependencies() {
\_resolveImage();
if (TickerMode.of(context)) {
\_listenToStream();
} else {
\_stopListeningToStream();
}
super.didChangeDependencies();
}
#override
void didUpdateWidget(PageFlipImage oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.image != oldWidget.image) {
\_resolveImage();
}
}
#override
void reassemble() {
\_resolveImage(); // in case the image cache was flushed
super.reassemble();
}
void \_resolveImage() {
final ImageStream newStream =
widget.image!.resolve(createLocalImageConfiguration(context));
\_updateSourceStream(newStream);
}
void \_handleImageFrame(ImageInfo imageInfo, bool synchronousCall) {
setState(() =\> \_imageInfo = imageInfo);
}
// Updates \_imageStream to newStream, and moves the stream listener
// registration from the old stream to the new stream (if a listener was
// registered).
void \_updateSourceStream(ImageStream newStream) {
if (\_imageStream?.key == newStream.key) return;
if (_isListeningToStream) _imageStream?.removeListener(_imageListener);
_imageStream = newStream;
if (_isListeningToStream) _imageStream?.addListener(_imageListener);
}
void \_listenToStream() {
if (\_isListeningToStream) return;
\_imageStream?.addListener(\_imageListener);
\_isListeningToStream = true;
}
void \_stopListeningToStream() {
if (!\_isListeningToStream) return;
\_imageStream?.removeListener(\_imageListener);
\_isListeningToStream = false;
}
#override
Widget build(BuildContext context) {
if (\_imageInfo != null) {
return CustomPaint(
painter: PageFlipEffect(
amount: widget.amount,
image: \_imageInfo!.image,
backgroundColor: widget.backgroundColor,
),
size: Size.infinite,
);
} else {
return const SizedBox();
}
}
}
in the beginning I was converting the pdf page to uint8list and using the image.memory widget, and it was not working swell, so I converted the uint8list bytes into file and then using image.file, it started getting this issue where it first it blank then after ctrl+s it starts rendering but some pages still not rendered
I think image.asset works well, but idk if that's helpful, I need my files on firebase storage.

QML: Move a frameless window by dragging

I have a frameless QQuickWindow, and I want to move it with the mouse by dragging. Before trying in my big application, I have created a simple test application to try what I found here, using cursor position from C++ class to avoid problems from QML:
http://www.tickanswer.com/solved/5390888353/dragging-frameless-window-jiggles-in-qml
But I failed with the code below. When I press over the red RECT and move the mouse, my yellow rect (root RECT) moves, but only inside the original size it had (in this case, 500x500)... What am I doing wrong?
Thanks in advance
In my main.cpp:
int main(int argc, char *argv[])
{
QtQuickControlsApplication a(argc, argv);
QQuickView* pView = new QQuickView();
CursorPosProvider mousePosProvider;
pView->rootContext()->setContextProperty("mousePosition", &mousePosProvider);
pView->setSource(QUrl("qrc:/Test.qml"));
pView->setFlags(Qt::FramelessWindowHint);
pView->show();
return a.exec();
}
Test.qml:
import QtQuick 2.0
Rectangle {
id: myWindow
width: 500; height: 500
color: "yellow"
Rectangle {
anchors.centerIn: parent
width: 200; height: 200
color: "red"
MouseArea {
id: titleBarMouseRegion
property var clickPos
anchors.fill: parent
onPressed: clickPos = { x: mousePosition.cursorPos().x, y: mousePosition.cursorPos().y }
onPositionChanged: {
myWindow.x = mousePosition.cursorPos().x - clickPos.x
myWindow.y = mousePosition.cursorPos().y - clickPos.y
}
}
}
}
cursorprovider.h:
#ifndef CURSORPOSPROVIDER_H
#define CURSORPOSPROVIDER_H
#include <QObject>
#include <QPointF>
#include <QCursor>
class CursorPosProvider : public QObject
{
Q_OBJECT
public:
explicit CursorPosProvider(QObject *parent = nullptr) : QObject(parent)
{
}
virtual ~CursorPosProvider() = default;
Q_INVOKABLE QPointF cursorPos()
{
return QCursor::pos();
}
};
#endif // CURSORPOSPROVIDER_H
I wrote this example and I see no jiggle (running on Linux)
ApplicationWindow {
id: iWindow
visible: true
title: "My title"
color: "gray"
width: 500
height: 500
MouseArea{
id: iMouseArea
property int prevX: 0
property int prevY: 0
anchors.fill: parent
onPressed: {prevX=mouse.x; prevY=mouse.y}
onPositionChanged:{
var deltaX = mouse.x - prevX;
iWindow.x += deltaX;
prevX = mouse.x - deltaX;
var deltaY = mouse.y - prevY
iWindow.y += deltaY;
prevY = mouse.y - deltaY;
}
}
}
I have changed the structure, I have used a QQuickWidget with a QML inside, and now I have what I wanted. Here is my code in case anyone needs something similar
main.cpp
...
MovableWidget *view = new MovableWidget;
view->setSource(QUrl("qrc:/Test.qml"));
view->setWindowFlags(Qt::FramelessWindowHint);
view->show();
...
Test.qml
import QtQuick 2.0
Rectangle {
id: myWindow
width: 500; height: 500
color: "yellow"
Rectangle {
anchors.centerIn: parent
width: 200; height: 200
color: "red"
}
}
MovableWidget.cpp
#include "movableWidget.h"
#include <QMouseEvent>
// ****************************************************************************
MovableWidget::MovableWidget(QWidget *parent)
: QQuickWidget(parent),
m_previousPos(0,0)
{
installEventFilter(this);
}
// ****************************************************************************
bool MovableWidget::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
m_previousPos = QCursor:os();
}
else if (event->type() == QEvent::MouseMove)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if(mouseEvent->buttons() == Qt::LeftButton)
{
QPoint offset = m_previousPos - QCursor:os();
m_previousPos = QCursor:os();
move(pos() - offset);
}
}
return false;
}

Qml define custom property group [duplicate]

This question already has answers here:
How to create grouped/nested properties?
(3 answers)
Closed 7 years ago.
How can I define custom property groups in qml, equal to the anchors property?
Example usage:
Item {
anchors {
leftMargin: 5
rightMargin: 5
}
}
I'm afraid this is not as simple as you are thinking it might be.
As far as I know, you have two options:
1.- Follow the recommendation you will see in the link provided by #BaCaRoZzo and implement your own object type.
2.- Write a more complex QML type in C++ and use it in your QML file. More or less the idea pointed out by #folibis. Example:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "customitem.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<CustomItem>("CustomItem", 1,0, "CustomItem");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
customitem.h
#ifndef CUSTOMITEM_H
#define CUSTOMITEM_H
#include <QObject>
class CustomItem: public QObject
{
Q_OBJECT
/*
* Any property that is writable should have an associated NOTIFY signal.
* Ref: http://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html#exposing-properties
*/
Q_PROPERTY(int x READ x WRITE setX NOTIFY xChanged)
Q_PROPERTY(int y READ y WRITE setY NOTIFY yChanged)
public:
CustomItem(QObject *parent = 0);
int x() const;
void setX(int);
int y() const;
void setY(int);
private:
int m_x;
int m_y;
signals:
void xChanged();
void yChanged();
public slots:
};
#endif // CUSTOMITEM_H
customitem.cpp
#include "customitem.h"
CustomItem::CustomItem(QObject *parent)
: QObject(parent), m_x(0), m_y(0)
{
}
int CustomItem::x() const
{
return m_x;
}
void CustomItem::setX(int x)
{
m_x = x;
}
int CustomItem::y() const
{
return m_y;
}
void CustomItem::setY(int y)
{
m_y = y;
}
main.qml
import QtQuick 2.5
import QtQuick.Window 2.2
import CustomItem 1.0
Window {
visible: true
CustomItem {
id: customItem
x: 50
y: 50
}
Rectangle {
id: rect
x: customItem.x
y: customItem.y
width: 100; height: 100
color: "red"
}
}

D3D D2D Interop on Windows 7

I'm trying to use DWrite to draw text in my dx11 app but I'm having lot of problems, I shared resources beetween D3D10 Device and D3D11 Device because dx10 is capable to connect D3D with D2D, that's the code of my GraphicsDevice:
// File: GraphicsDevice.h
#pragma once
#ifndef _GRAPHICSDEVICE_H_
#define _GRAPHICSDEVICE_H_
#ifndef _DEFINES_H_
#include "Defines.h"
#endif
#ifndef _COLOR_H_
#include "Color.h"
#endif
#ifndef _UTILITIES_H_
#include "Utilities.h"
#endif
#ifndef _DWRITE_H_
#include "DWrite.h"
#endif
// Forward declaration
namespace BSGameFramework { ref class Game; }
using namespace BSGameFramework;
using namespace System;
namespace BSGameFramework
{
namespace Graphics
{
public ref class GraphicsDevice
{
public:
/// <summary>GraphicsDevice constructor.</summary>
/// <param name="game">The game wich the device has to work.</param>
GraphicsDevice(Game^ game);
virtual ~GraphicsDevice();
/// <summary>Clear the screen.</summary>
/// <param name="color">The color that the screen background will assume after clearing.</param>
void Clear(Color color);
/// <summary>Render on the screen.</summary>
void Render();
/// <summary>Set the full screen state.</summary>
void FullScreen(bool isFullScreen);
property Color BlendFactor
{
Color get()
{
return blendFactor_;
}
void set(Color blendFactor_)
{
blendFactor_ = BlendFactor;
}
}
property D3D_DRIVER_TYPE DriverType
{
D3D_DRIVER_TYPE get()
{
return driverType_;
}
}
property D3D_FEATURE_LEVEL FeatureLevel
{
D3D_FEATURE_LEVEL get()
{
return featureLevel_;
}
}
property ID3D11Device* D3DDevice
{
ID3D11Device* get()
{
return d3dDevice_;
}
}
property ID3D11DeviceContext* D3DContext
{
ID3D11DeviceContext* get()
{
return d3dContext_;
}
}
property ID3D10Device1* D3DDevice10_1
{
ID3D10Device1* get()
{
return d3dDevice10_1_;
}
}
property ID2D1Factory* D2DFactory
{
ID2D1Factory* get()
{
return d2dFactory_;
}
}
property ID2D1RenderTarget* D2DRenderTarget
{
ID2D1RenderTarget* get()
{
return d2dRenderTarget_;
}
}
property ID2D1SolidColorBrush* D2DSolidColorBrush
{
ID2D1SolidColorBrush* get()
{
return d2dSolidColorBrush_;
}
}
property IDWriteFactory* DWriteFactory
{
IDWriteFactory* get()
{
return dWriteFactory_;
}
}
property int WindowWidth
{
int get()
{
return GetWindowWidth();
}
}
property int WindowHeight
{
int get()
{
return GetWindowHeight();
}
}
property HWND Window
{
HWND get()
{
return GetWindow();
}
}
property int SafeTitleArea
{
int get()
{
return safeTitleArea_;
}
void set(int safeTitleArea)
{
safeTitleArea_ = safeTitleArea;
}
}
private:
void CreateD3D11Resources();
void CreateD3D10Resources(ID3D11Texture2D* d3d11Texture);
void CreateD2D1Resources(ID3D10Texture2D* d3d10Texture);
Game^ game_;
Color blendFactor_;
D3D_DRIVER_TYPE driverType_;
D3D_FEATURE_LEVEL featureLevel_;
int safeTitleArea_;
int GetWindowWidth();
int GetWindowHeight();
HWND GetWindow();
// Direct3D 11
ID3D11Device* d3dDevice_;
ID3D11DeviceContext* d3dContext_;
// Direct3D 10
ID3D10Device1* d3dDevice10_1_;
// Direct2D
ID2D1Factory* d2dFactory_;
ID2D1RenderTarget* d2dRenderTarget_;
ID2D1SolidColorBrush* d2dSolidColorBrush_;
// DirectWrite
IDWriteFactory* dWriteFactory_;
IDXGISwapChain* swapChain_;
ID3D11RenderTargetView* backBufferTarget_;
};
}
}
#endif
// FILE: GraphicsDevice.cpp
#include "GraphicsDevice.h"
#include "Game.h"
#include "GraphicsDeviceNativeWrapper.h"
using namespace BSGameFramework::Graphics;
using namespace BSGameFramework;
inline GraphicsDevice::GraphicsDevice(Game^ game) : driverType_( D3D_DRIVER_TYPE_NULL ), featureLevel_( D3D_FEATURE_LEVEL_11_0 ),
d3dDevice_( 0 ), d3dContext_( 0 ), swapChain_( 0 ), backBufferTarget_( 0 )
{
game_ = game;
BlendFactor = Color::White;
CreateD3D11Resources();
}
inline GraphicsDevice::~GraphicsDevice()
{
if (backBufferTarget_)
{
backBufferTarget_->Release();
}
if (swapChain_)
{
swapChain_->Release();
}
if (d3dContext_)
{
d3dContext_->Release();
}
if (d3dDevice_)
{
d3dDevice_->Release();
}
backBufferTarget_ = 0;
swapChain_ = 0;
d3dContext_ = 0;
d3dDevice_ = 0;
}
inline void GraphicsDevice::Clear(Color color)
{
if (d3dContext_ == 0)
{
return;
}
float clearColor[4];
Vec4 convertedColor = Utilities::ColorToVec4(color);
clearColor[0] = convertedColor.values[0];
clearColor[1] = convertedColor.values[1];
clearColor[2] = convertedColor.values[2];
clearColor[3] = convertedColor.values[3];
d3dContext_->ClearRenderTargetView(backBufferTarget_, clearColor);
}
inline void GraphicsDevice::Render()
{
swapChain_->Present(0, 0);
}
inline void GraphicsDevice::FullScreen(bool isFullScreen)
{
swapChain_->SetFullscreenState(isFullScreen, NULL);
}
inline int GraphicsDevice::GetWindowWidth()
{
return game_->WindowWidth;
}
inline int GraphicsDevice::GetWindowHeight()
{
return game_->WindowHeight;
}
inline HWND GraphicsDevice::GetWindow()
{
return game_->Window;
}
#pragma region CreateD3D11Resources
inline void GraphicsDevice::CreateD3D11Resources()
{
HRESULT result;
RECT dimensions;
GetClientRect(Window, &dimensions);
unsigned int width = dimensions.right - dimensions.left;
unsigned int height = dimensions.bottom - dimensions.top;
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
D3D_DRIVER_TYPE_SOFTWARE
};
unsigned int totalDriverTypes = ARRAYSIZE(driverTypes);
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
};
unsigned int totalFeatureLevels = ARRAYSIZE(featureLevels);
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 2;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = game_->Window;
swapChainDesc.Windowed = true;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
unsigned int creationFlags = 0;
#ifdef _DEBUG
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
unsigned int driver = 0;
pin_ptr<IDXGISwapChain*> swapChainPointer;
swapChainPointer = &swapChain_;
pin_ptr<ID3D11Device*> d3dDevicePointer;
d3dDevicePointer = &d3dDevice_;
pin_ptr<D3D_FEATURE_LEVEL> featureLevelPointer;
featureLevelPointer = &featureLevel_;
pin_ptr<ID3D11DeviceContext*> d3dContextPointer;
d3dContextPointer = &d3dContext_;
for (driver = 0; driver < totalDriverTypes; ++driver)
{
result = D3D11CreateDeviceAndSwapChain(0, driverTypes[driver], 0, creationFlags, featureLevels, totalFeatureLevels,
D3D11_SDK_VERSION, &swapChainDesc, swapChainPointer,
d3dDevicePointer, featureLevelPointer, d3dContextPointer);
if (SUCCEEDED(result))
{
driverType_ = driverTypes[driver];
break;
}
}
if (FAILED(result))
{
DXTRACE_MSG("Failed to create the Direct3D device!");
return;
}
ID3D11Texture2D* backBufferTexture;
result = swapChain_->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferTexture);
if (FAILED(result))
{
DXTRACE_MSG("Failed to get the swap chain back buffer!");
return;
}
pin_ptr<ID3D11RenderTargetView*> backBufferTargetPointer;
backBufferTargetPointer = &backBufferTarget_;
result = d3dDevice_->CreateRenderTargetView(backBufferTexture, 0, backBufferTargetPointer);
if (FAILED(result))
{
DXTRACE_MSG("Failed to create the render target view!");
return;
}
d3dContext_->OMSetRenderTargets(1, backBufferTargetPointer, 0);
D3D11_VIEWPORT viewport;
viewport.Width = static_cast<float>(width);
viewport.Height = static_cast<float>(height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
d3dContext_->RSSetViewports(1, &viewport);
CreateD3D10Resources(backBufferTexture);
}
#pragma endregion
#pragma region CreateD3D10Resources
inline void GraphicsDevice::CreateD3D10Resources(ID3D11Texture2D* d3d11Texture)
{
//Load D3D10.DLL
HMODULE d3d10_1 = LoadLibrary("D3D10_1.dll");
// Get adapter of the current D3D11 device. Our D3D10 will run on the same adapter.
IDXGIDevice* dxgiDevice;
IDXGIAdapter* dxgiAdapter;
d3dDevice_->QueryInterface<IDXGIDevice>(&dxgiDevice);
dxgiDevice->GetAdapter(&dxgiAdapter);
SafeRelease<IDXGIDevice>(&dxgiDevice);
//Get address of the function D3D10CreateDevice1 dynamically.
typedef HRESULT (WINAPI* FN_D3D10CreateDevice1)(
IDXGIAdapter *pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software,
UINT Flags, D3D10_FEATURE_LEVEL1 HardwareLevel, UINT SDKVersion, ID3D10Device1 **ppDevice );
FN_D3D10CreateDevice1 fnCreate = (FN_D3D10CreateDevice1)GetProcAddress(d3d10_1, "D3D10CreateDevice1");
//Call D3D10CreateDevice1 dynamically.
pin_ptr<ID3D10Device1*> d3dDevice10_1Ptr = &d3dDevice10_1_;
fnCreate(dxgiAdapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT | D3D10_CREATE_DEVICE_DEBUG, D3D10_FEATURE_LEVEL_10_1, D3D10_1_SDK_VERSION, d3dDevice10_1Ptr);
//Create a D3D10.1 render target texture and share it with our D3D11.
D3D10_TEXTURE2D_DESC tDesc;
tDesc.Width = game_->WindowWidth;
tDesc.Height = game_->WindowHeight;
tDesc.MipLevels = 1;
tDesc.ArraySize = 1;
tDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
tDesc.SampleDesc.Count = 1;
tDesc.SampleDesc.Quality = 0;
tDesc.Usage = D3D10_USAGE_DEFAULT;
//EVEN IF YOU WON'T USE AS SHADER RESOURCE, SET THIS BIND FLAGS:
tDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
tDesc.CPUAccessFlags = 0;
tDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED;
//Create the RT texture on D3D10
ID3D10Texture2D* texture;
d3dDevice10_1_->CreateTexture2D(&tDesc, NULL, &texture);
//Get DXGI Resource and retrieve the sharing handle.
IDXGISurface* dxgiSurface;
IDXGIResource* dxgiResource;
HANDLE shareHandle;
texture->QueryInterface<IDXGISurface>(&dxgiSurface);
dxgiSurface->QueryInterface<IDXGIResource>(&dxgiResource);
dxgiResource->GetSharedHandle(&shareHandle);
SafeRelease(&dxgiResource);
SafeRelease(&dxgiSurface);
//Call D3D 11 to open shared resource.
ID3D11Resource* d3d11Resource;
d3dDevice_->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource), (void**)&d3d11Resource);
d3d11Resource->QueryInterface<ID3D11Texture2D>(&d3d11Texture);
SafeRelease(&d3d11Resource);
if (d3d11Texture)
{
d3d11Texture->Release();
}
CreateD2D1Resources(texture);
}
#pragma endregion
#pragma region CreateD2D1Resources
inline void GraphicsDevice::CreateD2D1Resources(ID3D10Texture2D* d3d10Texture)
{
pin_ptr<ID2D1Factory*> d2dFactoryPtr = &d2dFactory_;
pin_ptr<IDWriteFactory*> dWriteFactoryPtr = &dWriteFactory_;
//pin_ptr<ID2D1HwndRenderTarget*> d2dRenderTargetPtr = &d2dRenderTarget_;
//pin_ptr<ID2D1SolidColorBrush*> D2DSolidColorBrushPtr = &d2dSolidColorBrush_;
GraphicsDeviceNativeWrapper::CreateFactories(Window, d2dFactoryPtr, dWriteFactoryPtr);
//Get DXGI Surface from the created render target.
IDXGISurface1* pRT10;
d3d10Texture->QueryInterface<IDXGISurface1>(&pRT10);
FLOAT dpiX;
FLOAT dpiY;
d2dFactory_->GetDesktopDpi(&dpiX, &dpiY);
// Create a DC render target.
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE),
static_cast<float>(dpiX),
static_cast<float>(dpiY)
);
// Create a Direct2D render target.
// Assuming m_pD2DFactory was previously created with:
//D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), NULL,
// (void**)(&m_pD2DFactory));
pin_ptr<ID2D1RenderTarget*> renderTargetPtr = &d2dRenderTarget_;
d2dFactory_->CreateDxgiSurfaceRenderTarget(pRT10, (const D2D1_RENDER_TARGET_PROPERTIES *)&props, renderTargetPtr);
pin_ptr<ID2D1SolidColorBrush*> solidColorBrushPtr = &d2dSolidColorBrush_;
d2dRenderTarget_->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), solidColorBrushPtr);
}
#pragma endregion
// File GraphicsDeviceNativeWrapper.h
#pragma once
#ifndef _GRAPHICSDEVICENATIVEWRAPPER_H_
#define _GRAPHICSDEVICENATIVEWRAPPER_H_
#ifndef _DWRITE_H_
#include "DWrite.h"
#endif
#pragma managed(push, false)
namespace BSGameFramework
{
namespace Graphics
{
class GraphicsDeviceNativeWrapper abstract sealed
{
public:
static void CreateFactories(HWND window, ID2D1Factory** d2dFactory, IDWriteFactory** dWriteFactory/*,ID2D1RenderTarget** d2dRenderTarget, ID2D1SolidColorBrush** d2dSolidColorBrush*/)
{
HRESULT result;
result = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,__uuidof(ID2D1Factory), NULL, (void**)d2dFactory);
if (SUCCEEDED(result))
{
result = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(dWriteFactory));
}
RECT rc;
GetClientRect(window, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
}
static void CreateTextFormat(const wchar_t* font, IDWriteFactory* factory, IDWriteTextFormat** format)
{
factory->CreateTextFormat(font, NULL, DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 72.0f, L"en-us", format);
(*format)->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
(*format)->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
}
};
}
}
#pragma managed(pop)
#endif
And this is my SpriteBatch:
// File: SpriteBatch.h
#pragma once
#ifndef _SPRITEBATCH_H_
#define _SPRITEBATCH_H_
#ifndef _DEFINES_H_
#include "Defines.h"
#endif
#ifndef _GRAPHICRESOURCE_H_
#include "GraphicResource.h"
#endif
#ifndef _TEXTURE2D_H_
#include "Texture2D.h"
#endif
#ifndef _GRAPHICSDEVICE_H_
#include "GraphicsDevice.h"
#endif
#ifndef _SPRITESORTMODE_H_
#include "SpriteSortMode.h"
#endif
#ifndef _BLENDSTATE_H_
#include "BlendState.h"
#endif
#ifndef _NATIVESPRITEBATCH_H_
#include "NativeSpritebatch.h"
#endif
#ifndef _SPRITEEFFECT_H_
#include "SpriteEffect.h"
#endif
#ifndef _IDRAWABLECOMPONENT_H_
#include "IDrawableComponent.h"
#endif
#ifndef _SPRITEFONT_H_
#include "SpriteFont.h"
#endif
using namespace BSGameFramework::GameBase;
namespace BSGameFramework
{
namespace Graphics
{
public ref class SpriteBatch : GraphicResource
{
public:
SpriteBatch(GraphicsDevice^ graphicsDevice);
~SpriteBatch();
void Begin();
void Begin(SpriteSortMode sortMode, BlendState^ blendState);
void Draw(IDrawableComponent^ component);
void DrawString(SpriteFont^ font, System::String^ text, Vector2 position);
void End();
private:
bool CompileD3DShader(char* filePath, char* entry, char* shaderModel, ID3DBlob** buffer);
void SortByDepth();
SpriteSortMode sortMode_;
BlendState ^blendState_;
System::Collections::Generic::List<IDrawableComponent^>^ componentList_;
bool beginInvoked_;
ID3D11VertexShader* solidColorVS_;
ID3D11PixelShader* solidColorPS_;
ID3D11InputLayout* inputLayout_;
ID3D11Buffer* vertexBuffer_;
ID3D11BlendState* alphaBlendState_;
NativeSpritebatch* spriteBatch;
};
}
}
#endif
// File: SpriteBatch.cpp
#include "SpriteBatch.h"
#ifndef _SPRITEBATCHBEGINENDEXCEPTION_H_
#include "SpriteBatchBeginEndException.h"
#endif
using namespace BSGameFramework::Graphics;
using namespace BSGameFramework::Exception;
inline SpriteBatch::SpriteBatch(GraphicsDevice^ graphicsDevice) : alphaBlendState_( 0 )
{
graphicDevice_ = graphicsDevice;
sortMode_ = SpriteSortMode::Deferred;
blendState_ = BlendState::AlphaBlend;
// ID3DBlob contiene un puntatore ad un dato di lunghezza qualsiasi, GetBufferPointer restituisce il puntatore e GetBufferSize la grandezza
ID3DBlob* vsBuffer = 0;
// Compila lo shader e salva il risultato nel buffer
bool compileResult = CompileD3DShader("TextureMap.fx", "VS_Main", "vs_4_0", &vsBuffer);
if (compileResult == false)
{
DXTRACE_MSG("Error compiling the vertex shader!");
return;
}
HRESULT d3dResult;
pin_ptr<ID3D11VertexShader*> solidColorVSPointer;
solidColorVSPointer = &solidColorVS_;
// Crea il vertex shader e lo salva in solidColorVS_ di tipo ID3D11VertexShader*
d3dResult = Device->D3DDevice->CreateVertexShader(vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), 0, solidColorVSPointer);
if (FAILED(d3dResult))
{
DXTRACE_MSG("Error creating the vertex shader!");
if (vsBuffer)
{
vsBuffer->Release();
}
return;
}
D3D11_INPUT_ELEMENT_DESC solidColorLayout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
unsigned int totalLayoutElements = ARRAYSIZE(solidColorLayout);
pin_ptr<ID3D11InputLayout*> inputLayoutPointer;
inputLayoutPointer = &inputLayout_;
// Crea l'input layout e lo salva in inputLayout di tipo ID3D11InputLayout*
d3dResult = Device->D3DDevice->CreateInputLayout(solidColorLayout, totalLayoutElements, vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), inputLayoutPointer);
vsBuffer->Release();
if (FAILED(d3dResult))
{
DXTRACE_MSG("Error creating the input layout!");
return;
}
ID3DBlob* psBuffer = 0;
// Compila il pixel shader e salva il risultato in psBuffer
compileResult = CompileD3DShader("TextureMap.fx", "PS_Main", "ps_4_0", &psBuffer);
if (compileResult == false)
{
DXTRACE_MSG("Error compiling pixel shader!");
return;
}
pin_ptr<ID3D11PixelShader*> solidColorPSPointer;
solidColorPSPointer = &solidColorPS_;
// Crea il pixel shader e lo salva in solidColorPS_ di tipo ID3D11PixelShader*
d3dResult = Device->D3DDevice->CreatePixelShader(psBuffer->GetBufferPointer(), psBuffer->GetBufferSize(), 0, solidColorPSPointer);;
psBuffer->Release();
if (FAILED(d3dResult))
{
DXTRACE_MSG("Error creating pixel shader!");
return;
}
spriteBatch = new NativeSpritebatch(Device->D3DDevice);
// Spostare nel Begin successivamente
D3D11_BLEND_DESC blendDesc;
ZeroMemory(&blendDesc, sizeof(D3D11_BLEND_DESC));
blendDesc.AlphaToCoverageEnable = FALSE;
blendDesc.IndependentBlendEnable = FALSE;
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
pin_ptr<ID3D11BlendState*> alphaBlendStatePointer;
alphaBlendStatePointer = &alphaBlendState_;
Device->D3DDevice->CreateBlendState(&blendDesc, alphaBlendStatePointer);
Device->D3DContext->OMSetBlendState(alphaBlendState_, blendFactor, 0xFFFFFFFF);
}
inline SpriteBatch::~SpriteBatch()
{
}
inline void SpriteBatch::Begin()
{
if (beginInvoked_)
{
throw gcnew SpriteBatchBeginEndException("Beetween two SpriteBatch begin methods you must call SpriteBacth End method!");
}
beginInvoked_ = true;
Device->D2DRenderTarget->BeginDraw();
Device->D2DRenderTarget->SetTransform(D2D1::IdentityMatrix());
if (componentList_ == nullptr)
{
componentList_ = gcnew System::Collections::Generic::List<IDrawableComponent^>();
}
}
inline void SpriteBatch::Begin(SpriteSortMode sortMode, BlendState^ blendState)
{
Begin();
sortMode_ = sortMode;
}
inline void SpriteBatch::Draw(IDrawableComponent^ component)
{
if (component == nullptr)
{
throw gcnew ArgumentNullException("Component argument is null, please ensure to initialize all components correctly!");
}
else
{
componentList_->Add(component);
}
}
inline void SpriteBatch::DrawString(SpriteFont^ font, System::String^ text, Vector2 position)
{
RECT rc;
GetClientRect(Device->Window, &rc);
// Create a D2D rect that is the same size as the window.
D2D1_RECT_F layoutRect = D2D1::RectF(
static_cast<FLOAT>(rc.left) / font->DpiScaleX,
static_cast<FLOAT>(rc.top) / font->DpiScaleY,
static_cast<FLOAT>(rc.right - rc.left) / font->DpiScaleX,
static_cast<FLOAT>(rc.bottom - rc.top) / font->DpiScaleY
);
// Use the DrawText method of the D2D render target interface to draw.
WCHAR textUnicode = Utilities::StringToWCHAR(text);
UINT32 cTextLength_ = (UINT32) wcslen(&textUnicode);
Device->D2DSolidColorBrush->SetColor(D2D1::ColorF(0,0,0,1));
Device->D2DSolidColorBrush->SetColor(D2D1::ColorF(255, 255, 255, 255));
Device->D2DRenderTarget->DrawText(&textUnicode, cTextLength_, font->DWriteTextFormat, layoutRect, Device->D2DSolidColorBrush);
}
inline void SpriteBatch::End()
{
if (componentList_->Count)
{
if (sortMode_ == SpriteSortMode::BackToFront)
{
SortByDepth();
}
for (int i = 0; i < componentList_->Count; i++)
{
Texture* text = componentList_[i]->Texture->TextureInfo;
unsigned int stride = sizeof(VertexPos);
unsigned int offset = 0;
Device->D3DContext->IASetInputLayout(inputLayout_);
if (componentList_[i]->Effect != SpriteEffect::None)
{
ID3D11Buffer* vertexBuffer;
float width = (float)text->textureDesc_.Width;
float height = (float)text->textureDesc_.Height;
D3D11_BUFFER_DESC vertexDesc;
ZeroMemory(&vertexDesc, sizeof(vertexDesc));
vertexDesc.Usage = D3D11_USAGE_DYNAMIC;
vertexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexDesc.ByteWidth = sizeof(VertexPos) * 6;
D3D11_SUBRESOURCE_DATA resourceData;
ZeroMemory(&resourceData, sizeof(resourceData));
pin_ptr<ID3D11Buffer*> vertexBufferPointer;
vertexBufferPointer = &vertexBuffer;
switch (componentList_[i]->Effect)
{
case BSGameFramework::Graphics::SpriteEffect::FlipHorizontally:
{
VertexPos verticesOne[] =
{
{ XMFLOAT3(width, height, 1.0f), XMFLOAT2(0.0f, 0.0f) },
{ XMFLOAT3(width, 0.0f, 1.0f), XMFLOAT2(0.0f, 1.0f) },
{ XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 1.0f) },
{ XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 1.0f) },
{ XMFLOAT3(0.0f, height, 1.0f), XMFLOAT2(1.0f, 0.0f) },
{ XMFLOAT3(width, height, 1.0f), XMFLOAT2(0.0f, 0.0f) },
};
resourceData.pSysMem = verticesOne;
Device->D3DDevice->CreateBuffer(&vertexDesc, &resourceData, vertexBufferPointer);
Device->D3DContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
break;
}
case BSGameFramework::Graphics::SpriteEffect::FlipVertically:
{
VertexPos verticesTwo[] =
{
{ XMFLOAT3(width, height, 1.0f), XMFLOAT2(1.0f, 1.0f) },
{ XMFLOAT3(width, 0.0f, 1.0f), XMFLOAT2(1.0f, 0.0f) },
{ XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(0.0f, 0.0f) },
{ XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(0.0f, 0.0f) },
{ XMFLOAT3(0.0f, height, 1.0f), XMFLOAT2(0.0f, 1.0f) },
{ XMFLOAT3(width, height, 1.0f), XMFLOAT2(1.0f, 1.0f) },
};
resourceData.pSysMem = verticesTwo;
Device->D3DDevice->CreateBuffer(&vertexDesc, &resourceData, vertexBufferPointer);
Device->D3DContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
break;
}
}
}
else
{
Device->D3DContext->IASetVertexBuffers(0, 1, &text->vertexBuffer_, &stride, &offset);
}
Device->D3DContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
Device->D3DContext->VSSetShader(solidColorVS_, 0, 0);
Device->D3DContext->PSSetShader(solidColorPS_, 0, 0);
Device->D3DContext->PSSetShaderResources(0, 1, &text->colorMap_);
Device->D3DContext->PSSetSamplers(0, 1, &text->colorMapSampler_);
spriteBatch->SetTranspose(Device->D3DContext, text, Device->WindowWidth, Device->WindowHeight, componentList_[i]->Position.X, componentList_[i]->Position.Y,
componentList_[i]->Scale.X, componentList_[i]->Scale.Y, componentList_[i]->Rotation);
Device->D3DContext->Draw(6, 0);
}
}
Device->D2DRenderTarget->EndDraw();
componentList_->Clear();
beginInvoked_ = false;
sortMode_ = SpriteSortMode::Deferred;
}
inline bool SpriteBatch::CompileD3DShader(char* filePath, char* entry, char* shaderModel, ID3DBlob** buffer)
{
DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined(DEBUG) || defined(_DEBUG)
shaderFlags |= D3DCOMPILE_DEBUG;
#endif
ID3DBlob* errorBuffer = 0;
HRESULT result;
result = D3DX11CompileFromFile(filePath, 0, 0, entry, shaderModel, shaderFlags, 0, 0, buffer, &errorBuffer, 0);
if (FAILED(result))
{
if (errorBuffer != 0)
{
OutputDebugStringA((char*)errorBuffer->GetBufferPointer());
errorBuffer->Release();
}
return false;
}
if (errorBuffer != 0)
{
errorBuffer->Release();
}
return true;
}
inline void SpriteBatch::SortByDepth()
{
for (int i = 0; i < componentList_->Count - 1; i++)
{
for (int j = 1; j < componentList_->Count; j++)
{
if (componentList_[i]->ZIndex < componentList_[j]->ZIndex)
{
IDrawableComponent^ component = componentList_[i];
componentList_[i] = componentList_[j];
componentList_[j] = component;
}
}
}
}
When I call SpriteBatch.DrawString(...) from my C# app I'm not obtaining nothing written on my screen, can please somebody explaining me what's I'm missing? I'm new on DirectX programming so please be quiet with me xD Thanks!
There's a lot of code you posted and I didn't read it all, but I was trying to do the same thing (successfully) a few days ago and I might have some suggestions.
Overall, it looks like you do this more or less the same way I do. What I did different it that I created the shared texture using D3D11 device, but this should make no difference. The second thing, which I think could be the problem, is that you're not synchronizing the texture resource between D3D10 and D3D11.
When I tried to use such resources without synchronization, D2D was only rendering stuff once in like 50 calls, the rest just had no effect. I think I was continously blocking the resource when rendering it with D3D11.
You should create the texture using
tDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
instead. Here are the details about this flag: MSDN. Basically, you query two IDXGIKeyedMutex interfaces from the shared texture objects on both D3D10 and D3D11 devices. You lock the D3D10 mutex when you draw your D2D stuff to the texture. You lock the D3D11 mutex when you want to use this texture in D3D11. You do this using IDXGIKeyedMutex::AcquireSync and IDXGIKeyedMutex::ReleaseSync. Just be sure to pass the same Key value to each consecutive D3D10 Release -> D3D11 Acquire and D3D11 Release -> D3D10 Acquire calls.
Oh, one more little, not important thing, I noticed this in your code:
texture->QueryInterface<IDXGISurface>(&dxgiSurface);
dxgiSurface->QueryInterface<IDXGIResource>(&dxgiResource);
I'm not 100% sure, but I think you can get the IDXGIResource interface directly from your texture.

How to be notified on focus?

This question has been edited:
I am working with QML.
I have a custom type called polygon, which is a subcalss of QDeclarativeItem.
I want to be notified when a mouse clicked on a polygon(has focus).
I know QDeclarativeItem has a function: focusInEvent.
I override it in Polygon.cpp, here is polygon.cpp
#include "polygon.h"
#include "point.h"
#include <QPainter>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <QGraphicsSceneDragDropEvent>
#include <QFocusEvent>
#include "DeclarativeDragDropEvent.h"
using namespace std;
using namespace Qt;
Polygon::Polygon(QDeclarativeItem *parent)
: QDeclarativeItem(parent)
{
// need to disable this flag to draw inside a QDeclarativeItem
setFlag(QDeclarativeItem::ItemHasNoContents, false);
setFlags(ItemIsSelectable|ItemIsMovable|ItemIsFocusable);
setAcceptDrops(true);
}
QVariant Polygon::itemChange(GraphicsItemChange change, const QVariant &value)
{
return QGraphicsItem::itemChange(change, value);
}
void Polygon::focusInEvent ( QFocusEvent * event ){
cout<<"focusin"<<endl;
}
QRectF Polygon::boundingRect() const{
QVector<QPointF> vPnt=listToVector(m_vertices);
return QPolygonF(vPnt).boundingRect();
}
QPainterPath Polygon::shape () const
{
QPainterPath path;
QVector<QPointF> vPnt=listToVector(m_vertices);
path.addPolygon(QPolygonF(vPnt));
return path;
}
QString Polygon::name() const
{
return m_name;
}
void Polygon::setName(const QString &name)
{
m_name = name;
}
QColor Polygon::color() const
{
return m_color;
}
void Polygon::setColor(const QColor &color)
{
m_color = color;
}
void Polygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
QPen pen(m_color, 2);
painter->setPen(pen);
painter->setRenderHints(QPainter::Antialiasing, true);
QVector<QPointF> vPnt=listToVector(m_vertices);
painter->setBrush(QBrush(m_color,Qt::SolidPattern));
painter-> drawPolygon(QPolygonF(vPnt),Qt::OddEvenFill);
}
QVector<QPointF> Polygon:: listToVector(QList<Point *> lpnt) const{
QVector<QPointF> vPnt;
for(int i=0;i<lpnt.length();i++){
vPnt.append(QPointF(lpnt.at(i)->x(),lpnt.at(i)->y()));
}
return vPnt;
}
QDeclarativeListProperty<Point> Polygon::vertices()
{
return QDeclarativeListProperty<Point>(this, 0, &Polygon::append_vertex);
}
void Polygon::append_vertex(QDeclarativeListProperty<Point> *list, Point *vertex)
{
Polygon *polygon = qobject_cast<Polygon *>(list->object);
if (polygon) {
vertex->setParentItem(polygon);
polygon->m_vertices.append(vertex);
}
}
And here is my qml file:
import MyTypes 1.0
import QtQuick 1.0
import Qt 4.7
Item {
id:container
width: 300; height: 200
Polygon {
id: aPolygon
anchors.centerIn: parent
width: 100; height: 100
name: "A simple polygon"
color: "blue"
vertices:[
Point{x:20.0; y:40.0},
Point{x:40.0; y:40.0},
Point{x:40.0; y:20.0},
Point{x:20.0; y:20.0}
]
}
}
i override shape, boundingRect as you can see to define Polygon object and to succeed to be notified when a click, a focus appeared in ti
But i can not see cout output in focusInEvent function on screen.
Should i add something on main.cpp of project?
What to do to C++ code know that the object has focus?
Some connection?
Thanks for any idea.
I tried and it seems the problem is with the output "cout", try the "qDebug" and see that you have good code.
All you did is correct.