Right now I am just trying to create a circle with a gradient fill:
//I want the center to be at 10, 10 in the circle and the radius to be 50 pixels
QRadialGradient radial(QPointF(10, 10), 50);
radial.setColorAt(0, Qt::black); //I want the center to be black
radial.setColorAt(1, Qt::white); //I want the sides to be white
painter.setBrush(QBrush(radial));
painter.drawEllipse(/*stuff*/);
However, all this accomplishes is to show me a totally white circle. How can I rectify this?
I'll try to help you, but I can't speak english very well.
Damn I also can't post images meanwhile... I'll post them on other site.
Sure it will be white. You are using wrong coordinates. Show me your "/* stuff */" variable list, please.
You see, if you set gradient for your widget (in your case its only a little area) you can paint your ellipse in wrong place and it will be surely white: [see pic]
Set Gradients coordinates correct. e.g:
QRadialGradient radial(QPointF(100, 100), 50);
// ...
painter.drawEllipse(50,50,100,100);
[see pic]
In the line
radial.setColorAt( 0, Qt::black );
change it to the line
radial.setColorAt( n, Qt::black );
n being a number between 0 and 1.
Related
I am drawing arcs in tkinter. They use the 'arc' method so only have an outer edge of a specified width and colour. Annoyingly some arcs seem to have randomly have a rounded edge. Does anyone know if this is a bug or if it can be fixed?
Example code:
w1.create_arc(xarc0,yarc0,xarc1,yarc1,start=arcstart,extent=arcextent,width=thick1,outline=mc,style="arc")
Pic of the problem attached.
After some experimenting, I believe this is a glitch
I ran a simulation to create 360 arcs, each with an extent from 1 - 360, I found that the only time when the arc has a curved end was when the extent of the arc was 90 or 271, I don't know why this happens but I don't think its supposed to.
The green arc is the simulation, the red and the blue arc are the arcs which have a curved end. I don't think there is a way to fix this problem, however you can change the extent from 90 to 91 as I've done for the orange arc, as you can see it has a straight end and there's not much difference.
Here's the code if you want to play around with it:
from tkinter import *
Window = Tk()
w1 = Canvas(Window)
w1.pack()
for x in range(360):
w1.after(5)
arc = w1.create_arc(20, 20, 150,100,start=0,extent=x,width=30,outline = "green", style="arc")
w1.update()
if x == 90 or x == 271:
print("Now!")
w1.create_arc(160,20, 300,100,start=0,extent=90,width=30,outline = "red", style="arc")
w1.create_arc(180,120, 320,200,start=0,extent=271,width=30,outline = "blue", style="arc")
w1.create_arc(0, 150, 140,230,start=0,extent=91,width=30,outline = "orange", style="arc")
Hi I'm creating a network diagrame of nodes using networkX's circular layout.
It's been great laying out nodes in a circle however I want to add text to each node(a description) but the text must not overlap, so it remains readable
something like this textwheel. Notice how all the text juts outward from each node.
How can i do the same. I'm using pyqt/qt and I know of the painter.rotate method but I can't have a fixed rotation, what's the best way to workout the correct rotation for each node's description.
I'm drawing the nodes on a Qgraphicsscene, so I can get the boundingRect of the scene, and also get the center of the scene. I can also get the position of each node as output by NetworkX's cirular layout. Having the 2 points is a start. I'm not sure what the best way forward after that is.
If there are several articles that demonstrate a good solution please let me.
One additional wrinkle is that the nodes themselves can be moved by the user. But I imagine that once I've worked out how to draw the text, i can apply the same formula/method in the event that the node itself is moved by the user.
Just need a general way of working out the angle of the center of the node in relation to the center of the graphicssene.
If there are code samples that can point me in the right direction please share.
Thanks
Usually, the rotation of the text is the same as the rotation of the radius used to position the reference point on the text's rectangle.
The code below demonstrates how to use painter transforms to easily achieve the desired result. The text alignment trick is inspired by this answer.
import sys
from PyQt5.QtCore import QRect, QRectF, QSizeF, QPointF, Qt
from PyQt5.QtGui import QPainter, QPicture, QFont, QColor
from PyQt5.QtWidgets import QApplication, QLabel
def drawNode(painter, angle, radius, text):
size = 32767.0;
painter.save();
painter.rotate(-angle);
painter.translate(radius, 0);
painter.drawText(QRectF(0, -size/2.0, size, size), Qt.AlignVCenter, text);
painter.restore();
if __name__ == "__main__":
app = QApplication(sys.argv)
pic = QPicture()
pic.setBoundingRect(QRect(-100, -100, 200, 200))
p = QPainter(pic)
p.drawEllipse(0, 0, 3, 3)
p.setFont(QFont("Helvetica", 25))
for angle in range(0, 359, 30):
drawNode(p, angle, 50, str(angle))
p.end()
l = QLabel()
l.setPicture(pic);
l.show();
sys.exit(app.exec_())
I want to draw a rectangle with rounded corners (border radius same for all 4 corners) with a specific color filling the entire rectangle, and a separate border color (say border is 1 px wide).
From my observation, Qt provides three methods - fillRect and drawRect and drawRoundedRect. I have tried them, they don't work like I want to. There is no method like fillRoundedRect. Which means that I can draw a rounded rectangle but it won't be filled with the color I want.
How do I do it? And also, I read that due to some aliasing problems, the corners are often rendered as unequal. How do I set it as equal for all four? Will painter.setRenderHint(QPainter::Antialiasing) suffice? Or do I have to do anything else?
You can create a QPainterPath, add the rounded rect to it, and then fill and stroke it:
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
QPainterPath path;
path.addRoundedRect(QRectF(10, 10, 100, 50), 10, 10);
QPen pen(Qt::black, 10);
p.setPen(pen);
p.fillPath(path, Qt::red);
p.drawPath(path);
Note that even with antialiasing, 1 px border will probably never really look good, especially on a low DPI desktop monitor, on a high DPI mobile device it will be almost invisible.
If you create the rectangle as QRectF(9.5, 9.5, 100, 50) it will look better with 1 px antialiased border, because it will "snap" on the right pixel:
The answer above (from #dtech) works great, but can sometimes end up with an uneven border around the roundedRect. Using QPainter.strokePath() instead of QPainter.drawPath() can fix this issue.
Here is a python implementation of QPushButton, with paintEvent reimplemented:
# I use PySide6, but whatever library should work.
from PySide6.QtWidgets import QPushButton
from PySide6.QtGui import QPainter, QPainterPath, QBrush, QPen
from PySide6.QtCore import Qt, QRectF
class RoundedButton(QPushButton):
def __init__(self, text, bordersize, outlineColor, fillColor):
super(RoundedButton, self).__init__()
self.bordersize = bordersize
self.outlineColor = outlineColor
self.fillColor = fillColor
self.setText(text)
def paintEvent(self, event):
# Create the painter
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
# Create the path
path = QPainterPath()
# Set painter colors to given values.
pen = QPen(self.outlineColor, self.bordersize)
painter.setPen(pen)
brush = QBrush(self.fillColor)
painter.setBrush(brush)
rect = QRectF(event.rect())
# Slighly shrink dimensions to account for bordersize.
rect.adjust(self.bordersize/2, self.bordersize/2, -self.bordersize/2, -self.bordersize/2)
# Add the rect to path.
path.addRoundedRect(rect, 10, 10)
painter.setClipPath(path)
# Fill shape, draw the border and center the text.
painter.fillPath(path, painter.brush())
painter.strokePath(path, painter.pen())
painter.drawText(rect, Qt.AlignCenter, self.text())
I am trying to fit part of in image into a raphael object.
Scaling the image works perfectly, but when I try to translate it, it ends up returning the wrong part of the image.
I am scalling the image using "S1.5,1.5,0,0", that is, I am not scalling it around the middle point, so scalling it works beautifully.
But, as I try to offset the image, the resulting image fragment is offset.
Maybe there's another way to do it in Raphael.
What I am trying to accomplish is use a fragment of an image as an image object in Raphael and I need to copy a rectangle from an external image into it.
Something like:
copy original image fragment (x0 = 100, y0 = 120, width = 300, height = 250) to the image object, which has dimensions (width = 150 and 125).
I have been looking for an answer for some time, but nothing that really helps.
Edit:
The fiddle is
/w9XSf/12/
In the example above, I am grabbing a 100 x 60px area from the original image (which is 612 x 325px), and trying to display it on the output image, which is 500 x 300px.
The scale works, but the area it is grabbing is not the one I need.
It does work, if I grab from 0, 0.
But, as I move from the top left corner of the originsl image, the actual area it gives me is farther away from what I actually need :(.
Any ideas? (I have already tried swapping the order of the T and the S in the transform string).
Thanks.
Using Raphael, the following code creates a container, to be used to display an image, duly translated and scaled. A live version of the solution is also available at http://jsfiddle.net/s6DHf/. This is a forked version of the actual problem.
var outputW = 525,
outputH = 300;
sourceX = 100,
sourceY = 100,
scaleX = 1.5,
scaleY = 1.5,
paper = new Raphael("image", outputW, outputH),
bgImg = paper.image("http://cdn3.whatculture.com/wp-content/uploads/2013/04/MAN-OF-STEEL-e1365755036183.jpg", 0, 0, 350, 200)
.transform("t" + sourceX + "," + sourceY + "s" + scaleX +","+ scaleY + ",0,0");
Check the use of "s" and "t" (in lowercase), which denotes relative scaling and relative translation, respectively. The problem was due to the use of "S" and "T" (in uppercase), which is all about absolute scaling and translation, respectively.
Raphael reference: http://raphaeljs.com/reference.html#Element.transform
Hope this helps.
I am using the setViewBox() function in Raphael 2. The width and height is multiplied by a value like (1.2, 1.3 ...). This changes the magnification/ zooming properly but the x and y which I have given as 0,0 makes the paper display its contents after some offset. If i modify the x and y to some positive value after the rendering( using firebug!!) then the top left of the paper moves back and above to its right position. I want to know how will the value be calculated. I have no idea about how the x,y affect the viewbox. If anybody can give me any pointers for this it will be a real help.
I have tried giving the difference between the width/ height divided by 2. Also I must mention that I am not rendering an image but various raphael shapes e.g. rects, paths text etc. in my paper.
Looking forward to some help!
Kavita
this is an example showing how to calculate the setViewBox values, I included jquery (to get my SVG cocntainer X and Y : $("#"+map_name).offset().left and $("#"+map_name).offset().top) and after that I calculated how much zoom I need :
var original_width = 777;
var original_height = 667;
var zoom_width = map_width*100/original_width/100;
var zoom_height = map_height*100/original_height/100;
if(zoom_width<=zoom_height)
zoom = zoom_width;
else
zoom = zoom_height;
rsr.setViewBox($("#"+map_name).offset().left, $("#"+map_name).offset().top, (map_width/zoom), (map_height/zoom));
did you put the center of your scaling to 0,0 like:
element.scale(1.2,1.2,0,0);
this can scale your element without moving the coordinates of the top left corner.