How I can work with SVG files in Qt creator? - c++

I have some problem. I need to read SVG files and place content on the QGraphicsView scene. I read documentation about QSvgWidget and QSvgRenderer, but don't understand how get all shapes from file, point coordinates, where place they and have a posibillity to change color, size and other properties. Who can suggest methods, how I can do this? Thanks in advance!
I tried create QSvgWidget and I managed draw one figure with his color, but if figures more than one, they all dye in black color, and I don't know, how I can control this.
ui->setupUi(this);
scene = new QGraphicsScene;
scene->setSceneRect(-200, -100, 400, 200);
svg_widget = new QSvgWidget(":/resources/Test3.svg");
svg_widget->renderer();
svg_rend = new QSvgRenderer;
painter = new QPainter;
svg_rend->render(painter);
svg_widget->render(painter);
scene->addWidget(svg_widget);
ui->graphicsView->setScene(scene);
I understood that after creating QSvgWidget and call renderer(), QSvgRenderer does not affect on work with SVG. Can I combine svg_rend with svg_widget? Or does it make no sense?

Related

How to do overlapping custom items in qt?

Like in the title. I have few objects, and i wanted to set graphics to them and overlap each other. I'm setting 18 squares (terrains). I'm adding to this terrains graphics:
setPixmap(QPixmap(":Graphics/Terrain")); like so.
Then i want to add frame to it. I have 4 files of format .png, every one is 200x200px. First one is terrain.png - it's a green square, second and third are frames, about 20px wide with a transparent center (with alpha channel) and the last .png file is City.png, in left corner of City.png, there is a small graphics, rest is transparent (alpha channel). When i'm trying to set the frame by the same way as terrain.png:
setPixmap(QPixmap(":Graphics/Frame"));
it covers all of the terrain.png graphics, despite the fact that the center of frame1.png is transparent.
Furthermore i want to add some others object like for example City.png. How to do it? Mayby exists some diffrent way except using this setPixmap function ?
The setPixmap approach seems to work quite nicely, when used like this:
QGraphicsScene* scene = new QGraphicsScene();
QGraphicsPixmapItem* itemA = new QGraphicsPixmapItem();
itemA->setPixmap(QPixmap(":/NonTransparentImage.png"));
scene->addItem(itemA);
QGraphicsPixmapItem* itemB = new QGraphicsPixmapItem();
itemB->setPixmap(QPixmap(":/TransparentImage.png"));
scene->addItem(itemB);
QGraphicsView* view = new QGraphicsView(scene);
view->show();
As you expect, the transparent itemB overlaps itemA.

Drawing text with shadow on pixmap with QPainter

I am working on a project in C++ with Qt, and I am trying to find a way to apply a text shadow when drawing text on a QPixmap using QPainter.
I understand that QGraphicsDropShadowEffect is a thing, and I am using in other parts of my project, but I can't for the life of me find a way to apply a QGraphicsEffect when drawing with QPainter on a pixmap. Drawing the same text multiple times with different offsets and opacities doesn't quite cut it.
Are there any ways to do this?
If not, how could I go about making a function that does it, given a QGraphicsEffect to get the radius and color from?
Thanks in advance!
I don't think it is directly possible to "draw text with shadow", it is only possible to apply a shadow to something already drawn that would take in an element and use say its alpha channel to calculate the shadow.
You should use composition, either of the final products or during drawing. It should work if you use it on a text element. The other option would be to draw your text in black, apply Gaussian blur and then again draw the text on top of it with the desired offset.
Thanks for your answer ddriver, it made me search with some new keywords, which lead me to find a suiting solution for my project.
What I figured out is that you can simply create a QLabel with the text and effects you want (QGraphicsDropShadowEffect, in my case), and render it into a QPixmap using QWidget::grab(). You can then draw this new pixmap with QPainter as you would any other image, by converting your pixmap to a QImage and using QPainter's drawImage().

Qt GraphicsItem transformation affects all items in scene

I have this embedded Qt application that uses the QGraphics framework to display a web view.
The dimensions of the web view are 1280*720 pixels, and the QGraphicsView is set to render the scene at these coordinates (0,0, 1280x720).
I'm trying to add a loading indicator on the top right corner (at 1100,50), which is a simple PNG image that I rotate every now and then using a QTimeLine.
Code looks like this (I found the transformation trick on the internet):
// loading_indic initialization:
QGraphicsPixmapItem *loading_indic =
new QGraphicsPixmapItem( QPixmap("./resources/loading_64.png") );
loading_indic->setPos(QPoint(1100.0,50.0));
QTimeLine timeline = new QTimeLine(1000);
timeline->setFrameRange(0,steps);
connect(timeline, SIGNAL(valueChanged(qreal)), this, SLOT(updateStep(qreal)));
timeline->start();
// called at each step of a QTimeLine:
void updateStep(qreal step) {
QTransform transformation = QTransform()
// place coordinate system to the center of the image
.translate( width/2.0, height/2.0)
// rotate the image in this new coordinate system
.rotate(new_angle)
// replace the coordinate system to the original
.translate( -width/2.0, -height/2.0);
loading_indic->setTransform(transformation);
}
Now, my problem is that when doing this, it looks like the WebView is translated as well, resulting in everything being displayed in the center of the screen.
Result looks like this:
The webview is supposed to fill the screen, and the loading indicator should be on top right...
My scene contains only two items:
Scene
|
\____ QGraphicsWebView
\____ QGraphicsPixmapItem // loading indicator
What am I doing wrong here?
Solved my problem..
I don't know why, but it looks like adding this PNG item to the scene was screwing up with the scene's rectangle.
Doing this:
_scene.addItem(loading_indic);
loading_indic->setPos(1100.0, 50.0);
_scene.setSceneRect(0.0,0.0,1280.0,720.0); // resets the scene's rectangle ?!
loading_indic->startAnimation();
solved the problem. Now my items are correctly placed on screen.
If somebody has an explanation to this, I'll gladly accept his answer.

Qt GUI Development - Displaying a 2D grid using QGraphicsView

I'm new to Qt development so I've being trying to research a solution to a user interface I need to design. My project is to simulate players in an online game moving around a global map. To represent the map I need to display a 2D grid, with each space in the grid representing a region of a map. I then need to display the location of each player in the game. The back-end is all fully working, with the map implemented as a 2D array. I'm just stuck on how to display the grid.
The research I have done has led me to believe a QGraphicsView is the best way to do this, but I can't seem to find a tutorial relevant to what I need. If anyone has any tips on how to implement this it would be much appreciated.
Thanks, Dan
A 2D Grid is nothing more than a set of horizontal and vertical lines. Suppose you have a 500x500 map and you want to draw a grid where the distance between the lines in both directions is 50. The sample code that follows shows you how you can achieve it.
// create a scene and add it your view
QGraphicsScene* scene = new QGraphicsScene;
ui->view->setScene(scene);
// Add the vertical lines first, paint them red
for (int x=0; x<=500; x+=50)
scene->addLine(x,0,x,500, QPen(Qt::red));
// Now add the horizontal lines, paint them green
for (int y=0; y<=500; y+=50)
scene->addLine(0,y,500,y, QPen(Qt::green));
// Fit the view in the scene's bounding rect
ui->view->fitInView(scene->itemsVBoundingRect());
You should check the QGraphicsView and the QGraphicsScene documentation as well as the corresponding examples. Also you can watch the graphics view training videos or some graphics view related videos from the Qt developer days.
Well if you have a constant grid size or even a limited number of grid sizes what i like to do is to draw a grid block in gimp or any other program and then set that as the background brush (draw only bottom and right side of the block) qt will repeat the image and will give you a full grid. I think this is good for performance too.
This is the grid image i used in one of my programs it's 10x10 pixels.
Then call QGraphicsScene setBackgroundBrush as the follwing:
scene->setBackgroundBrush(QBrush(QPixmap(":/grid/grid10.png")));
The more native way is this:
scene = self.getScene() # Your scene.
brush = QBrush()
brush.setColor(QColor('#999'))
brush.setStyle(Qt.CrossPattern) # Grid pattern.
scene.setBackgroundBrush(brush)
borderColor = Qt.black
fillColor = QColor('#DDD')
rect = QRectF(0.0, 0.0, 1280, 720) # Screen res or whatever.
scene.addRect(rect,borderColor,fillColor) # Rectangle for color.
scene.addRect(rect,borderColor,brush) # Rectangle for grid.
Sorry by PyQt...
Suppose a scene is set to the graphicsview then simply below one line will show the grid.
ui->graphicsView->scene()->setBackgroundBrush(Qt::CrossPattern);
There several other values can be passed for ex: Qt::Dense7Pattern
These are members of enum BrushStyle, just click on any used value in Qt creator and it will take you to the enum declaration where you can see all other possible values.
PS:
A scene can be set like this:
ui->graphicsView->setScene(new QGraphicsScene());

Qt Screen Resolution Splash Screen

I have a splash screen image that I display with splash.showFullScreen() but it doesn't re size it to the screen resolution so it either comes out tiled or to large depending on the display. I have tried everything I can think of but nothing works. This might sound like a stupid question which it probably is but I can't find the answer so if any can just help me with this? If it makes a difference I use a QPixmap named pixmap for the splash image. By the way I want the image to be stretched to the screen resolution.
You should scale the pixmap to the size of the screen with QPixmap::scaled(). You can get the screen resolution by calling QDesktopWidget::screenGeometry(). The desktop widget can be obtained by QApplication::desktop().
You can try something like this:
QDesktopWidget* desktopWidget = qApp->desktop();
QRect screenGeometry = desktopWidget->screenGeometry();
int screenWidth = screenGeometry.width();
int screenHeight = screenGeometry.height();
QPixmap pixmapForSplash = yourPixmap.scaled(screenWidth, screenHeight);
QSplashScreen splashScreen(pixmapForSplash);
(I'm sorry, I can not check this, because I do not have a development environment on this computer... I hope it is correct.)
I think you should call resize() method for your splash screen by the size of the available desktop geometry that you can get using QDesktopWidget::availableGeometry method. The QApplication::desktop() function is used to get an instance of QDesktopWidget.
slpashScreen.resize(QApplication::desktop()->avaiableGeometry().size());
If you use a QLabel to display the image, make sure the label is in a layout that will cause it to fill the entire parent widget and set the label to scale its contents using setScaledContents(true).