In my program I have a float
float integrity = 5.6;
and I want to draw it on the screen.
To do this, I use the DrawText function:
DrawText(TextFormat("%f",integrity), 300, 160, 30, WHITE);
But I get a bunch of zeros at the end that make everything look ugly.
What I expect: 5.6
The result: 5.600000
I can use "%.2f" in the DrawText() Function to round to the nearest 2 decimal points, that should pretty it up.
Related
I have a work-related C/C++ SDL 2.0 project - originally developed and compiled on Win7 computer for x86 platform (With MS Visual Studio) that was working fine for the whole time. Since the program was meant to run also at newer Win10 x64 devices, I moved the entire solution to a newer Win10 x64 computer, changed all SDL2 libraries, header files etc. for the x64 version and rebuilt the solution for x64 architecture.
The program is basically an advanced diagnostic screen with dials, icons and text information, so it uses variety of colors, fonts, geometry etc.
After the recompilation for x64 platform, I noticed that the colors of some elements are absolutely off. For example - a rectangle that should be grey (used SDL_SetRenderDrawColor one step before drawing the rect.) is suddenly green, despite its given grey RGB numbers as input arguments. Even the function SDL_GetRenderDrawColor called before and/or after drawing of the rectangle returns values 195, 195, 195, but the rectangle is shown green.
Rectangle drawing function:
void DrawRectangle(SDL_Color color, int pozX, int pozY, int width, int height)
{
SDL_Rect Proportions = { pozX, pozY, width, height };
SDL_SetRenderDrawColor(gRenderer, color.r, color.g, color.b, 0xFF);
SDL_RenderFillRect(gRenderer, &Proportions);
}
Rectangle drawing call:
DrawRectangle(grey, pocpozX, 182, width, height);
Later I have noticed that this rectangle inherits its color from a text rendered a few steps earlier. If I change the color of this text, it for some strange reason applies also for the rectangle.
Text drawing function:
void DrawText(std::wstring text, TTF_Font *font, int pozX, int pozY, SDL_Color color)
{
typedef std::basic_string<Uint16, std::char_traits<Uint16>, std::allocator<Uint16> > u16string;
std::wstring text_sf_str = text;
u16string utext_sf_str(text_sf_str.begin(), text_sf_str.end());
SDL_Surface* text_sf = TTF_RenderUNICODE_Blended(font, utext_sf_str.c_str(), color);
SDL_Texture* text_Tx = SDL_CreateTextureFromSurface(gRenderer, text_sf);
int text_TxW;
int text_TxH;
SDL_QueryTexture(text_Tx, NULL, NULL, &text_TxW, &text_TxH);
SDL_Rect textrect = { pozX, pozY, text_TxW, text_TxH };
SDL_RenderCopy(gRenderer, text_Tx, NULL, &textrect);
SDL_FreeSurface(text_sf);
SDL_DestroyTexture(text_Tx);
}
Notice all these conversions needed to display a wstring text with some uncommonly used UNICODE characters. I don't quite understand why SDL needs to be passed each character as Uint16 number, this could have been done better. I also don't understand the need of using SDL_QueryTexture just in order to display the text proportions right. I would expect the user to want to display the text not anyhow stretched by default. This all seems to me unnecessarily complicated.
Funny thing is, that if I remove SDL_DestroyTexture tag, there is of course a huge memory leak, but the problem disappears.
Text drawing call - in a for loop, this draws numeric labels onto speedometer axis:
if (i % 20 == 0)
{
if (i <= 160)
{
DrawText(str2, font, posX, posY, grey);
}
else
{
DrawText(str2, font, posX, posY, green);
}
}
... And this very "green" as the last argument of the call is what causes the rectangle to be green also - despite the fact that more elements are drawn between this text and rectangle so SDL_SetRenderDrawColor is called multiple times.
I have also noticed that some shown numbers are for a little while glitching some senseless values every n-th second, so I guess this is a memory-related problem. Of course there are more color problems, this was just for an example. Due to company policy, I cannot be more specific or post the full code here.
If I switch back to x86 configuration (with the right libraries of course), the problem now remains the same.
I'm using Cocos2D for iPhone to build up a game.I have a grid on the screen drawn by horizontal and vertical lines.(I did it with CCDrawNode) As you might guess there're lots of intersection points in there, I mean the points where horizontal and vertical lines intersect. With every touchBegan-Moved-Ended routine I draw a line, a bolder and different color line. In touchesMoved method I need to find the intersection point nearest to the current end point of the line and stick the line end to that point. How can I do that? I have one idea in my mind which is to add all the intersection points to an array when drawing the grid, iterate through that array and find the closest one. But I think this is not the best approach. You have any better ideas?
Assuming it is a normal grid with evenly spaced lines (e.g. every 10 pixels apart), you are much better off using a formula to tell you where an intersection should be.
E.g. given end point X/Y of 17,23, then x(17)/x-spacing(10) = 1.7, rounds to 2. 2*x-spacing = 20. y/y-spacing=2.3 -> 2*20 = 20. Thus your intersection is 20,20.
EDIT: more detailed example, in C# as that's what I use, if I get time I'll write an Objective-C sample
// defined somewhere and used to draw the grid
private int _spacingX = 10;
private int _spacingY = 10;
public Point GetNearestIntersection(int x, int y)
{
// round off to the nearest vertical/horizontal line number
double tempX = Math.Round((double)x / _spacingX);
double tempY = Math.Round((double)y / _spacingY);
// convert back to pixels
int nearestX = (int)tempX * _spacingX;
int nearestY = (int)tempY * _spacingY;
return new Point(nearestX, nearestY);
}
NOTE: the code above is left quite verbose to help you understand, you could easily re-write it to be cleaner
I've been trying to add some basic HUD-like Text to my OpenGL/C++ project.
Therefore i decided
glutBitmapCharacter( type, character)
to be my weapon of choice.
I realized that, for the easiest use, i should append a 2D Matrix to my previous Rendering area.
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, 10, 0, 10);
This should give me a sweet 10*10 2D cube to play around in.
Now a problem arised when glutBitmapCharacter remembers his last character position to append the next one. Pretty smart while it's writing a string, it obviously remembers this position and makes my Text fly all the way across screen once :) Naughty.
glRasterPos2f(x,y);
should be - as i heard - the normal thing to reset this thingy - (altough i don't perfectly understand why a gl function controls a glu Function, but thats just a sidenote).
Now the weird thing that happens, is once i run the code:
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, 10, 0, 10);
string message ="mmh... Pie...";
float poss[3];
glRasterPos3f(0.0, 0.0, 0.0);
glGetFloatv(GL_CURRENT_RASTER_POSITION, poss);
std::cout<< "X" <<(GLfloat) poss[0] << " Y"<<poss[1] << " Z"<<poss[2] << std::endl;
for( size_t i = 0; i < message.size(); ++i ) {
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, message[i]);
}
glPopMatrix();
My Text doesnt get shown. In fact the resulting X, Y and Z
(not even sure Z is necessary.. should be 0 anyway) are all inf (infinite).
If i don't set my own glRasterPos, things just work out fine, apart from leaving the screen. My returning positions are an upcounting X and 0 , 0 - as expected.
So whats the deal on this, what exactly am i doing wrong?
you produced a grand Segmentation Error: glGetFloatv(GL_CURRENT_RASTER_POSITION, poss) returns 4 values, so you must use:
float poss[4];
Apart from this, your code runs fine on my machine and returns:
X0 Y0 Z0.5
So the fault seems not to be in the code you posted here. You should try© it to a basic "HelloWorld"-GL program and see if it works there. Be careful that some OpenGL commands only work after a valid drawing surface is initialized - I guess you did that?
The following numbers are the path points of a very simple curve from Adobe InDesign:
pathPoint0 = app.selection[0].paths[0].pathPoints[0] // PointType: SMOOTH
pathPoint1 = app.selection[0].paths[0].pathPoints[1] // PointType: PLAIN
pathPoint0.leftDirection : {x=87.32570997045623, y=30.81406367905744}
pathPoint0.anchor : {x=67.69218412206757, y=134.53280706833522}
pathPoint0.rightDirection : {x=48.0586582736789, y=238.25155045761298}
pathPoint1.anchor : {117.05865827421783, 143.2515504576449}
The curve contains 2 path points, an smooth point and a plain point.
InDesign simple curve:
(source: no-ip.org)
I am trying to draw this curve by this code:
MoveToEx(hDC, 67, 134, NULL);
POINT points[] = {{87, 30}, {48, 238}, {117, 143}};
PolyBezierTo(hDC, points, 3);
But I can not draw same curve, my drawn curve is:
(source: no-ip.org)
Where is my mistake? Is any conversion need?
Thanks.
Hmm...
MoveToEx(hDC, 67, 134, NULL);
POINT points[] = {{87, 30}, {48, 238}, {117, 143}};
Your first point is 67,134 your second is 87,30 and your third 48,238.
With Y values of 134 then 30 then 238, I'd expect about what you seem to be getting -- a line that goes one direction, then sharply back in about the opposite direction.
The first point you're getting from InDesign is a "direction" point -- but for PolyBezier, the first and last points are the anchors. I'm not absolutely certain, but I think what you want is to rearrange the points so your anchors come first and last, and InDesign's "direction" points are used as the two control points in between:
POINT points[] = {{87, 30}, {67, 134}, {48,238}, {117, 143}};
// anchor, control, control, anchor
PolyBezier(hDC, points, 4);
Unless you're using MoveTo/LineTo (and such) otherwise, I'd just PolyBezier instead of PolyBezierTo -- keeps all the data in one place.
I try to draw a round rectangle with drawRoundedRect method directly in a QPixmap (no render engine involve here exept pure Qt one ...), I double check the size of the rectangle versus the size of my pixmap :
Pixmap : QSize(50, 73)
Rectangle: QRect(0,0 48x11)
See plenty of space ...
EDIT: some code
pixmap = QPixmap(50,73); //example size that match my case
QRectF rect(0,0,48,11);
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::TextAntialiasing);
painter.setWorldMatrixEnabled(false);
painter.setPen(QPen()); //no pen
painter.setBrush(QBrush(color));
painter.drawRoundedRect(rect, 2.0, 2.0);
I disabled world transformation ...
I set set transformation to unity ...
I tried several radius (1.0,2.0,3.0,4.0) ...
I change pen width, brush color ...
But it always ends with a rectamgle with 4 diferent corners ! Like that :
I directly ouptut the pixmap to a file to be sure I wasn't scraping it during the display ... same shape.
Anyone know about Qt round rectangle with small radius ? I saw somthing about it a long time ago but I don't remenber how to deal with it !
It looks like you're not using anti-aliasing (i.e. the QPainter::Antialiasing render hint). This is a Qt quirk that occurs without it. From what I've seen/heard, the Qt devs aren't terribly concerned with fixing this (most people want anti-aliasing anyway).
The work-around (besides just using anti-aliasing) is to draw the rect yourself with QPainter::drawLine() and QPainter::drawArc(). You might have to play with numbers until it looks right -- straight calculations tend to come out a pixel or two off. Also, you might find that even with this method the lower right corner is never exactly the same as the other corners.
If you're feeling mildly ambitious, you could try fixing this and submitting a patch to Qt.
Update: Arc drawing results changed in Qt 5. In my experience, it's a big improvement.
I know this is an old problem but for Qt5 users calling setRenderHint(QPainter::Qt4CompatiblePainting); on the QPainter seems to solve the problem.
Edit:
I found a solution for generating a perfect rounded rectangle together with border color and it looks the same as the rounded rectangles used by QPushButton's border for example. This is how I implemented the paintEvent to achieve this:
void MyButtonGroup::paintEvent(QPaintEvent * e)
{
int borderSize = 5;
QColor borderColor = Qt::red;
QColor backgroundColor = Qt::blue;
int borderRadius = 3;
QPen pen;
pen.setWidth(borderSize);
pen.setColor(borderColor);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(pen);
QRectF rect(rect().x() + borderSize / 2,
rect().y() + borderSize / 2,
rect().width() - borderSize,
rect().height() - borderSize);
if(borderSize % 2 == 0)
{
painter.drawRoundedRect(rect,
borderSize,
borderSize);
}
else
{
painter.drawRoundedRect(rect.translated(0.5, 0.5),
borderRadius,
borderRadius);
}
QBrush brush(backgroundColor);
pen.setBrush(brush);
painter.setBrush(brush);
if(borderSize % 2 == 0)
{
painter.drawRoundedRect(rect,
borderRadius,
borderRadius);
}
else
{
painter.drawRoundedRect(rect.translated(0.5, 0.5),
borderRadius,
borderRadius);
}
QWidget::paintEvent(e);
}
I'm posting this because I found it a bit hard to achieve this result:
Try adding half a pixel offset (e.g.: rect.translated(0.5,0.5) ):
QRectF rect(0,0,48,11);
painter.setRenderHint(QPainter::Antialiasing,false);
painter.drawRoundedRect( rect.translated(0.5,0.5), 2.0, 2.0 );
I suppose this has to do with the coordinate system placing an integer value between two pixels.
If you draw with antialiasing and use a pen of 1 pixel width then drawing at exact integer coordinates results in lines of 2 pixel width instead.
Only with this 0.5 pixel offset you'll get lines that are exactly 1 pixel wide.
QRectF rect(0,0,48,11);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setBrush(Qt::NoBrush);
painter.setPen( Qt::white );
painter.drawRoundedRect( rect.translated(0.5,0.5), 2.0,2.0 );
Best way do draw RoundRect is Path.
http://developer.nokia.com/community/wiki/Qt_rounded_rect_widget
void fillRoundRect(QPainter& painter, QRect r, int radius)
{
painter.setRenderHint(QPainter::Antialiasing,true);
QPainterPath rounded_rect;
rounded_rect.addRoundRect(r, radius, radius);
painter.setClipPath(rounded_rect);
painter.fillPath(rounded_rect,painter.brush());
painter.drawPath(rounded_rect);
}
try to play with render hints
1) disable antiAliasing;
2) enable SmoothPixmapTransform
but still no guarantee that it will help.
I have tried all tips from answers here but nothing works for me. But based on these code snippets I have found following solution:
As default set m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, true) and only for rounded rectangles with width%2==0 disable it.
QRect rect = ConvertRectangle(rectangle);
int nPenWidth = m_pPainter->pen().width();
if ( nPenWidth % 2 == 0 )
m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, false);
m_pPainter->drawRoundedRect(rect, dbRadiusX, dbRadiusY);
if ( nPenWidth % 2 == 0 )
m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, true);