When I am using QScatterSeries, I can very easily draw point at (x, y). However, instead of points I would like to draw short lines, like in the figure below. How can I get about doing so?
I tried using RectangleMarker, but it just draws a fat square. I would prefer a thin line about 2px wide and 20px in height.
Is there a way I can add custom marker shapes?
Here are the code and the settings I use to transform my points into lines :
//create scatter series to draw point
m_pSeries1 = new QtCharts::QScatterSeries();
m_pSeries1->setName("trig");
m_pSeries1->setMarkerSize(100.0);
//draw a thin rectangle (50 to 50)
QPainterPath linePath;
linePath.moveTo(50, 0);
linePath.lineTo(50, 100);
linePath.closeSubpath();
//adapt the size of the image with the size of your rectangle
QImage line1(100, 100, QImage::Format_ARGB32);
line1.fill(Qt::transparent);
QPainter painter1(&line1);
painter1.setRenderHint(QPainter::Antialiasing);
painter1.setPen(QColor(0, 0, 0));
painter1.setBrush(painter1.pen().color());
painter1.drawPath(linePath);
//attach your image of rectangle to your series
m_pSeries1->setBrush(line1);
m_pSeries1->setPen(QColor(Qt::transparent));
//then use the classic QtChart pipeline...
You can play the marker size, the dimension of the image and the drawing pattern in the painter to adapt the size and shape of the rectangle to obtain a line.
In the picture, it's the black line. As you can see you can repeat the process for other series.
Keep in mind that you cannot use the openGL acceleration:
m_pSeries0->setUseOpenGL(true);
My work is based on the QtCharts/QScatterSeries example : QScatterSeries example
Hope it will help you.
Florian
Related
I am using ArcGIS API v4.8 and the drawing tools to draw circle on my map.
1 issue I notice is when I draw a circle, the center of the circle moves when I move my mouse resizing the circle rather than fixed at the point of the 1st mouse click starts:
How do I fix the center regardless of how I move the radius of the circle? What is missing in my code?
const options = {view, layer: tempGraphicsLayer, pointSymbol, polylineSymbol, polygonSymbol}
let sketchViewModel = new SketchViewModel(options)
let drawCircleButton = document.getElementById('circleButton')
drawCircleButton.onclick = function () {
clear()
isDrawLine = false
sketchViewModel.create('polygon', {mode: 'click'})
sketchViewModel.create('circle')
}
EDIT:
I have found a similar sample, choose the Draw Circle tool, start drawing a circle on the map, you will notice that the center of the circle moves when you move your mouse, I want it to fix the center instead.
The problem when the center moves along with your mouse move is that the circle drawn is not accurate, as I want to start with the center of the circle I want, the circle can expand outward but the center should not move.
That is because the circle, in the given example, is being draw inside the square object. Basically your start and end point are representing corners, not the center point and outer layer of the circle. So every time you expand circle object, it expands from one corner, while the rest is dragging along your mouse.
Visual example:
There are workarounds for this of course. I've made a small sample code of one of the possible ways to draw a circle from a fixed center point.
https://jsfiddle.net/wLd46g8k/9/
Basically I used an ArcGis JS API 4.x constructor called Circle, where you pass a starting point and radius. In my example I've calculated the radius from these two points.
function drawCircle(){//draws the circle
graphicsLayer.graphics.removeAll();
var graphic = new Graphic({
geometry: new Circle({//circle constructor
center: startPoint,//pass the pointer-down event X Y as a starting point
radius: Math.floor(Math.sqrt(Math.pow(startPoint.x - endPoint.x, 2) + Math.pow(startPoint.y - endPoint.y, 2)))
}), //calculates endpoint distance from the startpoint and pass it as a radius
symbol: {//circle design
type: "simple-fill",
color: "orange",
style: "solid",
outline:{
color:"darkorange",
width:4
}
}
});
graphicsLayer.graphics.add(graphic);//adds the circle
};
I'm using Canvas for drawing in my Android application. But the result has bad quality (see the picture)
So, canvas drawing don't draw additional pixels with more dark color between "stairs pixels" for smoothing.
Like this
But I'm interesting how to do it.
Are there some preferences or methods for smoothing the picture? Thanx!
Edited: I've founded here
Use the ANTI-ALIAS flag for drawing smooth edges.
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
//or
Paint p = new Paint();
p.setAntiAlias(true);
I implemented a little drawing function into my app with CreateJS like so:
var currentPosition = this.posOnStage(event);
var drawing = container.getChildByName('drawing');
drawing.graphics.ss(this.brushSize, "round").s(this.brushColor);
drawing.graphics.mt(this._lastMousePosition.x, this._lastMousePosition.y);
drawing.graphics.lt(currentPosition.x, currentPosition.y);
drawing.alpha = this.brushAlpha;
container.updateCache(this.enableErasing ? "destination-out" : "source-over");
drawing.graphics.clear();
this._lastMousePosition = this.posOnStage(event);
As you can see, the alpha value of this drawing can change. Sadly you can draw over a point you once did draw, so when you draw over a point multiple times the alpha effect will go away. Any idea how to solve this ?
Thanks :)
EDIT:
I tried it like gskinner and Lanny 7 proposed, but it didn't work. I attached a image so you can see the problem.
As suggested by Lanny, apply the alpha to the actual stroke, not to the Shape. You can use Graphics methods to help with this.
For example:
// set the brush color to red with the current brush alpha:
this.brushColor = createjs.Graphics.getRGB(255, 0, 0, this.brushAlpha);
I am trying to use mask on my QWidget. I want to overlay existing widget with row of buttons - similar to Skype
Notice that these buttons don't have jagged edges - they are nicely antialiased and widget below them is still visible.
I tried to accomplish that using Qt Stylesheets but on pixels that should be "masked out" was just black colour - it was round button on black, rectangular background.
Then I tried to do this using QWidget::mask(). I used following code
QImage alpha_mask(QSize(50, 50), QImage::Format_ARGB32);
alpha_mask.fill(Qt::transparent);
QPainter painter(&alpha_mask);
painter.setBrush(Qt::black);
painter.setRenderHint(QPainter::Antialiasing);
painter.drawEllipse(QPoint(25,25), 24, 24);
QPixmap mask = QPixmap::fromImage(alpha_mask);
widget.setMask(mask.mask());
Sadly, it results in following effect
"Edges" are jagged, where they should be smooth. I saved generated mask so I could investigate if it was the problem
it wasn't.
I know that Linux version of Skype does use Qt so it should be possible to reproduce. But how?
One possible approach I see is the following.
Prepare a nice high resolution pixmap with the circular button icon over transparent background.
Paint the pixmap on a square widget.
Then mask the widget leaving just a little bit of margin beyond the border of the circular icon so that the widget mask jaggedness won't touch the smooth border of the icon.
I managed to get a nice circular button with not so much code.
Here is the constructor of my custom button:
Button::Button(Type t, QWidget *parent) : QPushButton(parent) {
setIcon(getIcon(t));
resize(30,30);
setMouseTracking(true);
// here I apply a centered mask and 2 pixels bigger than the button
setMask(QRegion(QRect(-1,-1,32,32),QRegion::Ellipse));
}
and in the style sheet I have the following:
Button {
border-radius: 15px;
background-color: rgb(136, 0, 170);
}
With border-radius I get the visual circle and the mask doesn't corrupt the edges because it is 1 pixel away.
You are using the wrong approach for generating masks. I would generate them from the button images themselves:
QImage image(widget.size(), QImage::Format_Alpha8);
widget.render(&image);
widget.setMask(QBitmap::fromImage(image.createMaskFromColor(qRgba(0, 0, 0, 0))));
I have a ortho set up at the moment for 2D, when I resize the window it stretches anything that is drawn in the window, is there a way to either just have black bars show when the window is resized or at least maintain the aspect ratio of the contents, so they dont stretch at all. I have tried a few implementations that I have seen on here, but nothing really works.
EDIT: Sorry guys had a bit of a blonde moment
Protected Overrides Sub OnResize(ByVal e As EventArgs)
MyBase.OnResize(e)
GL.Viewport(0, 0, Width, Height)
GL.MatrixMode(MatrixMode.Projection)
GL.LoadIdentity()
GL.Ortho(-1.0, testvalue, testvalue , 1.0, 0.0, 4.0)
End Sub
testvalue at the moment is 5000, window size is 800x800
I figured out what I had to do. Rather than utilizing the aspect ratio on the Ortho part, I used it on the view port as such:
Dim ar As Single = Width/Height
GL.Viewport( 0, 0, 800 * ar, 800 * ar)
This prevents all stretching and simply places a black bar on the right hand side when the width is greater than height.
When you resize, Windows creates its own message pump to handle events, bypassing your message pump. There are work-arounds (hacks) to get it to render whilst sizing, including running your update/rendering on a thread. Note that this is a problem for D3D as well as OpenGL.
There's a discussion here on an old Gamedev thread.
the ortho command comprises of: the following parameters: left, right, bottom, top, zNear, zFar further info: http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml
You will want to plug in your 'Width' into right and your 'Height' into bottom and ensure the Width and Height values reflect the new window size.
E.g.:
GL.Viewport(0, 0, Width, Height)
GL.MatrixMode(MatrixMode.Projection)
GL.LoadIdentity()
GL.Ortho(0.0, Width, Height, 0.0, 1.0, 2.0)
Since you're only after 2D your zNear and zFar can be quite small, just make sure to render between zNear and zFar and do not use 0.0 as your zNear, I would recommend using 0.1 or larger for your zNear.