How to properly position a QGraphicsTextItem on a QGraphicsScene - c++11

The probelm I have is that I am trying to position a QGraphicsTextItem on a specific location of my QGraphicsScene , to be precise in the center of the speedometer below. But nothing I tried seems to work properly. Despite I clearly provided the coordinates I want the QGraphicsTextItem, it still anchored on top-left as shown below:
Below the snippet of code:
speedwidget.cpp
SpeedWidget::SpeedWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::SpeedWidget)
{
ui->setupUi(this);
mScene = new Scene(this);
ui->graphicsView->setScene(mScene);
io = new QGraphicsTextItem;
io->setPos(210,240);
QFont *f = new QFont;
f->setPointSize(18);
io->setFont(*f);
mScene->addText("Odometer :")->setDefaultTextColor(Qt::red);
mScene->addItem(io);
}
speedwidget.h
class SpeedWidget : public QWidget
{
Q_OBJECT
public:
SpeedWidget(QWidget *parent = nullptr);
~SpeedWidget();
private:
Ui::SpeedWidget *ui;
Scene *mScene;
QGraphicsTextItem *io;
};
#endif // SPEEDWIDGET_H
What I tried so far to solve the problem was:
I consulted this post which explained the idea but I don't need to change the background color in this example.
This one had a good snippet, but I am not trying to highlight the color. I am only trying to position the text on a specific location.
If I change io->setPos(210,240); and give different numbers, I still see it anchored on top-left.
Thanks for pointing to the right direction for solving this issue.

The Qt Graphics View framework implements a parent-child mechanism. Simply make your QGraphicsTextItem become a child of your odometer's dial item. From then on, your text label's position will be relative to the one of the dial:
io = new QGraphicsTextItem(this);
// Position text item so that it's centered on the dial
...
Furthermore, note that this line:
mScene->addText("Odometer :")->setDefaultTextColor(Qt::red);
Means that you create yet another text item. A pointer to the newly created item is being returned. Either use & retain that one or use the one that you explicitly created with the new expression.
Furthermore you might want to reconsider your choice of using a QGraphicsScene for one simple "widget". While the Qt graphics framework is not necessarily heavy, it certainly brings quite a lot of overhead for just rendering an odometer.
You can simply overwrite the QWidget::paint() function in your SpeedWidget subclass and render everything using QPainter. That will be a lot lighter and also a lot less hassle.

Related

can graphics overlay be used to constantly update location marker in arcgis?

So i was trying to create a location display buffer which isn't available in scene map, so for this
i created a triangle symbol and updated it so that every time location changed the graphic has to be erased and placed at new position like this
prevLocX=camera.location.X// initialized at start
prevLocY=camera.location.Y
newLocX=camera.location.X
newLocY=camera.location.Y
callCurrentLocation();
CallCurrentLocation()
{
if prevlocX!=newlocX && ...
{
go.Graphics.Clear();
Mappoint mp1=new Mappoint(newLocX,newLocY,SpatialReferences.wgs84);
--
--
go.graphics.add(msm1);
PrevlocX=newLocX;
PrevLocY=newLocY;
}
i know this seems redundant and inefficient but this was the best way i could think of please see if it can be made better
Most efficient would be to keep the overlay and graphic instances and just update the geometry on the graphic with a new point each time.

Winapi How do I draw a rectangle to a specific Window handle?

I'm Using a Wrapper Library in GMS2 That was made back in GM6 Days (gamemaker) Someone was able to wrap majority of the win32API to use in GM6-8. There is only 1 odd instance in where the WinAPI system seems to mess up when drawing the controls to the Main Application Window.
The desired goal is to draw an image to an Child window and draw a grid defining it's splitting according to the user input EX: 16x16 and having the user select squares VIA Mouse Click + Dragging over the boxes.
Unfortunately I have little to no experience in win32API so i'm a bit lost as to where to start.
Looking over the documentation it looks like he left majority of the script names of the DLL to mimic the format of that when calling in C++ or C (just my assumptions).
From His Documentation he has things like "Drawing System" Which Contains things like "Move Item","Add Line","Add Graphic Buffer" etc... and then other Graphic Buffer functions. But then theres the "Draw" functions which has things like "Draw Fill Rect , DrawSelectObj" etc... he doesn't really provide examples so i'm unsure as to how to use these things together to get my desired results. What is the difference between a drawing system and a draw function? Do I have to use them in conjunction, along with the Graphics Buffer?
Can Someone point in the right direction of the necessary steps to get it done? An Example without code and just the function equivalent will suffice, I just need to know out of which functions to use and then later bind it to the Child Window.
An Example Code from his demo is something like this
GbGradient2 = API_GB_Create (105,105); //Graphics Buffer
DcGradient2 = API_GB_GetDC (GbGradient2);
API_Draw_Gradient (DcGradient2,0,0,105,105,0,c_yellow,c_lime);
BrGradient2 = API_Draw_CreatePatternBrush (API_GB_GetBitmap (GbGradient2));
API_Draw_Gradient (DcGradient2,0,0,105,105,0,c_red,65535);
BrGradient3 = API_Draw_CreatePatternBrush (API_GB_GetBitmap (GbGradient2));
hRectangle = API_DS_AddRectangle (2,5,5,105,105); // Adds a rectangle(Drawing System)
hEllipse = API_DS_AddEllipse (2,5,5,105,105);
hNoPen = API_Draw_CreatePen (PS_NULL,0,0);
API_DS_SetItemBrush (hRectangle,BrGradient2); // Sets the brush
API_DS_SetItemBrush (hEllipse,BrGradient3);
API_DS_SetItemPen (hRectangle,hNoPen); // Sets the pen
API_DS_SetItemPen (hEllipse,hNoPen);
API_Draw_Gradient (GbGradient2,0,0,16,16,0,c_yellow,c_lime);
Lookin at it a little more it looks like the draw functions are linked to GDI somehow.
since GMS2 is a cross platform tool , its windows-only functionality gas been removed.
you can make a nice GUI for that porpose by using GMS2 objects , as you have a little Xp
about Win32 API,this will be easier than that big stuffy coding
here are some tips ,
creating a window object with a rectangle sprite
creating ui objects at the create event of above object
adding some code to the global mouse event

Rotating text using center in itext

I'm converting a document which is created with a online editor. I need to be able to rotate the text using it's central point and not (0,0).
Since Image rotates using the centre I assumed this would work but it doesn't. Anyone has a clue how to rotate text using the central point in itext?
float fw = bf.getWidthPoint(text, textSize);
float fh = bf.getAscentPoint(text, textSize) - bf.getDescentPoint(text, textSize);
PdfTemplate template = content.createTemplate(fw, fh);
Rectangle r = new Rectangle(0,0,fw, fw);
r.setBackgroundColor(BaseColor.YELLOW);
template.rectangle(r);
template.setFontAndSize(bf, 12);
template.beginText();
template.moveText(0, 0);
template.showText(text);
template.endText();
Image tmpImage = Image.getInstance(template);
tmpImage.setAbsolutePosition(Utilities.millimetersToPoints(x), Utilities.millimetersToPoints(pageHeight-(y+Utilities.pointsToMillimeters(fh))));
tmpImage.setRotationDegrees(0);
document.add(tmpImage);
Why are you using beginText(), moveText(), showText(), endText()? Those methods are to be used by developers who speak PDF syntax fluently. Other developers should avoid using those low-level methods, because they are bound to make errors.
For instance: you're using the setFontAndSize() method outside a text object. That method is forbidden in graphics state, you can only use it in text state. Although Adobe Reader will probably tolerate it, Acrobat will complain when doing a syntax check.
Developers who don't speak PDF syntax fluently are advised to use convenience methods as demonstrated in the TextMethods example. Take a look at text_methods.pdf. The text "Away again Center" is probably what you need.
However, there's even an easier way to achieve what you want. Just use the static showTextAligned() method that is provided in the ColumnTextclass. That way you don't even need to use beginText(), setFontAndSize(), endText():
ColumnText.showTextAligned(template,
Element.ALIGN_CENTER, new Phrase(text), x, y, rotation);
Using the showTextAligned() method in ColumnText also has the advantage that you can use a phrase that contains chunks with different fonts.
For those who use Paragraph in itext 7 :
paragraph.setFixedPosition(....)
paragraph.setRotationAngle(Math.toRadians(....));
paragraph.setProperty(Property.ROTATION_POINT_X, textCenterX);
paragraph.setProperty(Property.ROTATION_POINT_Y, textCenterY);

How to overlay TWO images and save them into AN image? (Flash CS5)

I am a total noob with Flash. And i am no programmer. Just good with photoshop (image designing).
Here is my problem. I found a simple drawing application and modified it, only the interface, not the codings.
It provides a 'save button' that enables to save the drawing (drawn on MovieClip) into diskdrive. And then i modified it, put another layer on top of the MovieClip a Graphic. But then when i try to save it, it only saves the MovieClip as a .png image. What i want is that it saves the MovieClip along with the Graphic layered on top of it into one .png image. How can i do that?
Maybe it'll be more helpful if I provide the code to the 'save button'?
** /* Save */
private function export():void
{
var bmd:BitmapData = new BitmapData(600, 290);
bmd.draw(board);
var ba:ByteArray = PNGEncoder.encode(bmd);
private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
trace("completeHandler: " + loader.data);
}
private function saveSuccessful(e:Event):void
{
saveDialog = new SaveDialog();
addChild(saveDialog);
saveDialog.closeBtn.addEventListener(MouseEvent.MOUSE_UP, closeSaveDialog);
}
private function closeSaveDialog(e:MouseEvent):void
{
removeChild(saveDialog);
}
private function save(e:MouseEvent):void
{
export();
}**
EDIT: i have put 'bmd.draw(topLayer);' under the first draw() call but then when i published a preview it says "Access of undefined property topLayer". i checked its property first it mentions this 'Instance of: topLayer' and it is a Graphic.
Check the codes. There should be a construction fileReference.save(someOtherName) somewhere, probably with different name for fileReference, but it will be declared nearby as FileReference=new FileReference(). Then, track that someOtherName above, it should be an output of PNGEncoder.encode() of yet another variable, which should be of type BitmapData. Find out what is drawn on that bitmap data, there will be a line bitmapData.draw(someMovieClip). Find out if that someMovieClip is only the layer that's drawn upon in your program. You can add a similar line right after that one to draw your shape (you should have its name so you could reference it in code), this will draw your Graphic over the thing that you draw.
In case the entire graphics drawn by you can be fit within a single screen, just take a screenshot of your application in progress, load it up into Photoshop and have fun with your graphics be correctly on top of whatever it saves. Or, use an existing saved image as a background layer, place a screenshot as foreground, clear the areas that are not your graphics and have some more fun.
EDIT: Okay, there it is: You have export() function (which is incomplete in your copypasting, BTW), with all the relevant part I've mentioned. There is a draw() call, a PNGEncoder.encode() call, and a BitmapData object. You should add another line of code after the first draw() call with something like this:
bmd.draw(yourGraphic);
YourGraphic is the name of the graphic you have manually added above the MovieClip, the one you can edit in its properties on stage. Should do.
REPLY: i have put bmd.draw(topLayer); under the first draw() call but then when i published a preview it says "Access of undefined property topLayer". i checked its property first it mentions this 'Instance of: topLayer' and it is a Graphic.

OpenGL texture loading issue

This is a very vague problem, so please feel free to clarify anything about this project.
I'm working on a very large application, and recently a very perplexing bug has cropped up regarding the texturing. Some of the textures that we are loading are being loaded - I've stepped through the code, and it runs - but all OpenGL renders for those textures is a weird Pink/White striped texture.
What would you suggest to even begin debugging this situation?
The project is multithreaded, but a mutex makes sure all OpenGL calls are not interrupted by anything else.
Some textures are being loaded, some are not. They're all loaded in the exact same way.
I've made sure that all textures exist
The "pink/white" textures are definitely loaded in memory - they become visible shortly after I load any other texture into OpenGL.
I'm perplexed, and have no idea what else can be wrong. Is there an OpenGL command that can be called after glTexImage that would force the texture to become useable?
Edit:
It's not about the commands failing, it's mainly a timing issue. The pink/white textures show up for a while, until more textures are loaded. It's almost as if the textures are queued up, and the queue just pauses at some time.
Next Edit: I got the glIntercept log working correctly, and this is what it outputted (before the entire program crashed)
http://freetexthost.com/1kdkksabdg
Next Edit: I know for a fact the textures are loaded in OpenGL memory, but for some reason they're not rendering in the program themselves.
If your texture is colored incorrectly most likely you're loading the wrong order of RGB. Make sure in your glTexImage2D you're using the right enums for your image format. Make sure the number of components is correct and that you're getting the order of your RGB pixels in the format argument right.
Although probably not related to your textures showing up wrong, OpenGL doesn't support multithreaded draws so make sure you're not doing any drawing work on a different thread than the one that owns the context.
Edit: Do you have a reference renderer so you can verify the image pixels are being loaded as expected? I would strongly recommend writing a small routine to load then immediately save the pixels to a file so you can be sure that you're getting the right texture results.
Check your texture coordinates. If they are set wrong, you can see just one or two texels mapped to entire primitives. Remember, OpenGL is a state machine. Check if you're changing the texture coordinate state at the wrong time. You may be setting the texture coordinates at a later point in your code, then when you get back to redrawing these elements the state is acceptable for mapping your texture to the code.
If it is merely a timing issue where the texture loading OpenGL calls aren't executed in time, and your threading code is correct, try adding a call to glFlush() after loading the textures. glFlush() causes all pending OpenGL commands to execute.
When you say:
The project is multithreaded, but a mutex makes sure all OpenGL calls are not interrupted by anything else.
This doesn't sound like strong enough protection to me: remember that OpenGL is a state machine with a large amount of internal state. You need to make sure the OpenGL state is what you expect it to be when you are making your calls, and that certain sequences of calls don't get interrupted with by calls from other threads.
I'm no expert on OpenGL thread-safety, but this seems to me where your problem might lie.
Check the size and compression of those images you use as textures. i think opengl texture size has to be a power of 2 ...
You can't load a texture in a thread and use it in other different thread because you will see a beautiful white texture. To do this possible you must load the OpenGL context in between differents threads before use any OpenGL function.
If you are using GLIntercept to check your code, ensure to enable:
ThreadChecking = True;
in the gliConfig.ini file.
Viewing the log it seems that quite a few OpenGL calls are being main outside the main context.
It is possible to load textures in another thread without getting a white texture. The problem is that - once you initialized the OpenGL window - the OpenGL context is "bound" to this thread. You have to deactivate the context in the main thread while you're loading textures and before you start loading them, you have to activate the context in this thread.
You can use this class:
Context.h:
#ifndef CONTEXT_H
#define CONTEXT_H
#include <GL/glut.h>
class Context
{
public:
static Context* getInstance();
void bind();
void unbind();
private:
Context();
Context(const Context&);
~Context();
static Context *instance;
HGLRC hglrc;
HDC hdc;
class Guard
{
public:
~Guard()
{
if (Context::instance != 0) {
delete Context::instance;
}
}
};
friend class Guard;
};
#endif
Context.cpp:
#include "Context.h"
Context* Context::getInstance()
{
static Guard guard;
if(Context::instance == 0) {
Context::instance = new Context();
}
return Context::instance;
}
void Context::bind()
{
wglMakeCurrent(this->hdc, this->hglrc);
}
void Context::unbind()
{
wglMakeCurrent(NULL, NULL);
}
Context::Context()
{
this->hglrc = wglGetCurrentContext();
this->hdc = wglGetCurrentDC();
}
Context::~Context()
{
}
Context *Context::instance = 0;
And that's what you have to do:
int state = 0;
void main()
{
// Create the window.
glutCreateWindow(TITLE);
// Set your loop function.
glutDisplayFunc(&loop);
// Initialize the singleton for the 1st time.
Context::getInstance()->bind();
glutMainLoop();
}
void loop()
{
if (state == 0) {
Context::getInstance()->unbind();
startThread(&run);
} else if (state == 1) {
// Rebind the context to the main thread (just once).
Context::getInstance()->bind();
state = 2;
} else if (state == 2) {
// Draw your textures, lines, etc.
} else {
// Draw something (but no textures).
}
}
void run()
{
Context::getInstance()->bind();
// Load textures...
Context::getInstance()->unbind();
state = 1;
}

Resources