i have been using cleardevice() to clear the graphics ... but it creates several problems
for eg .. i create a background but i have to clear some specific elements , then i have to use another user defined function drawb() which draws the background and simultaneously cleardevice();
creating a lot of problems
line(x,y,x1,y1); //suppose this line is to be erased
//but using cleardevice even clears the background
cleardevice();
drawb(); //to draw board or background
so i want to know an alternative approach(an approach to clear only the line not the background) (if it exists )
Once a line is drawn, there is no real way to remove it (except if you are drawing using XOR mode!). However, there are some thing you could do. You could render everything but the line in a page and store it there. Then, in another page you render everything, including the line. So if you want to undo the line, you just switch the page back.
An example:
setactivepage(0);
// draw stuff, including background
setactivepage(1);
// draw stuff, including background and line
setvisualpage(0); // no line visible
setvisualpage(1); // line visible
Also, if you want to reset the screen with a background, there is no need to do a cleardevice(), since the drawb() overwrites every pixel ayway.
You can first take the image before drawing the line by getimage()
and put that image on the line whenever you want to hide your image
This will not change your background and not flick it. putimage() can put the image.
Related
I am new to C++,Qt and Visual Studio and this is my first post on Stack Overflow.
I apologize in advance if this is a repeated question, I tried searching for a similar question but couldn't find one. Let me know if this is a repeated question and I will delete it.
I am trying to create a line plot using QWidget::paintEvent(). The line plot I am drawing is actually a QPainterPath. I want to detect when the mouse hovers over my line plot and so I create a small rectangle where my mouse cursor is and detect when this rectangle intersects with my line plot using bool QPainterPath::intersects() function. The problem is that this function returns true even when my mouse is not exactly over my line plot. In the Image 1 (I am not allowed to embed images yet) my line plot is the thick black curve and the bool QPainterPath::intersects() returns true even when my cursor is over the yellow region. As per the Qt document this is because:
There is an intersection if any of the lines making up the rectangle crosses a part of the path or if any part of the rectangle overlaps with any area enclosed by the path.
There is no way to have a QPainterPath without any enclosed area as Qt only provides two types of fill for QPainterPath: Qt::OddEvenFill or Qt::WindingFill. (To be honest, I find this kind of annoying, since an open path is a series of line segments connected end-to-end, if someone wants to enclose an area they can easily connect the first and last point using either QPainterPath::lineTo() or QPainterPath::moveTo() functions)
Anyway, I decided to get smarter than Qt and drew two extra QPainterPath with pathUp being a few pixels above my line plot and pathDn being a few pixels below my line plot. Image 2 shows these 3 line plots, red one is pathUp, black one is real line plot and green one is pathDn. I thought I coould detect the intersection in the QWidget::mouseMoveEvent() by using the following code:
// cRect: Rectangle at mouse cursor position
if((pathUp.intersects(cRect) && (!pathDn.intersects(cRect))) || ((!pathUp.intersects(cRect)) && pathDn.intersects(cRect)))
{
qDebug() << "Intersects";
}
But this still produces wrong results because now the enclosed area is different, as you can see in Image 3 the green area is an enclosed area of pathDn and red area is the enclosed area of pathUp. The thick black curve is again the line plot that I want to detect my mouse hover on. This enclosed area is not affected by Qt::setFillRule of QPainterPath.
What's even more frustrating is that I tried this technique using QPolygonF instead of QPainterPath on QWidget and the results were exactly the same. I also tried QGraphicsView, there I used QGraphicsPathItem to create my line plot and then used QGraphicsScene::focusItemChanged() signal to detect when I click on my line plot. It again produced the same result of detecting the click when my cursor is over the enclosed area. I do not want to create a custom QGraphicsItem (unless I absolutely have to) just to reimplement it's hoverEnterEvent() and hoverLeaveEvent() method because of the limitations imposed on the boundingRect() of the QGraphicsItem as explained in Qt Docs:
QGraphicsScene expects all items boundingRect() and shape() to remain unchanged unless it is notified. If you want to change an item's geometry in any way, you must first call prepareGeometryChange() to allow QGraphicsScene to update its bookkeeping.
Since I making a plot in real-time the boundingRect() will change quite frequently (> 20 Hz), which will result in an extra computational burden on the software. Is there any way I can solve my problem without creating a custom QGraphicsItem?
P.S. I have been using Stack Overflow for many years whenever I got stuck. I just never made an account here because I never needed to post anything. You guys are the best and I am very happy to be a part of this community!
For university, we need to make a game in Unity that is controlled with an Arduino. My idea was a hacking game where the Arduino acts as the 'hacking device' when hacking something in the game. The arduino would have a screen and on that screen would be a basic command-line interface that lets me input simple commands to 'hack' but I've been having trouble regarding text and clearing it.
I've been able to use unity to send typed characters to the display as-well as a backspace function (pressing backspace would remove last character in the string)
I first had issue with clearing all the text when writing (calling tft.print doesn't clear any previous text). I was using fillScreen which was slow. I found out setTextColor had a second argument that let me just set all certain colored text to a different color. Setting it to black would essentially clear it.
This made it update pretty much instantly when writing to the screen but I now had a new issue, backspace would no longer would.
My understand is that when removing the character, it's color won't be updated when calling setTextColor leaving it on the screen until a restart/fillScreen is called.
I'm not really sure how to solve this and all google searches turn up little to no help.
Here's my code for updating the text:
void updateString(char c){
tft.setTextColor(WHITE,BLACK);
if(c!='<'){
//Add new character to end of string
str.concat(String(c));
}
else if(c=='<' && str.length()>2){
//Remove last character in string
str.remove(str.length()-1);
}
//Set cursor back to 0,0
tft.setCursor(0,0);
//Display text
tft.print(str);
}
I'd appreciate any help.
Maybe, use a similar function to tft.clear() each time you refresh the screen or you can draw a filled square of the background on the text so it looks like it has been erased then you rewrite the text.
Sounds like you are using proportionally-spaced fonts instead of the original classic fonts that ships with Adafruit_GFX. Historically, when using the default classic fonts one could set the background color option of the text to the same color as the background of the screen (usually black). This would overwrite the old screen contents with new data and work because the characters using the classic fonts are a uniform size. When using proportionally-spaced fonts, the background color option for the font is disabled by design.
This was presumably because of memory requirements and speed on slower AVR's. Regardless, when using proportionally-spaced fonts the background color feature won't work due to non-uniform sized characters overlapping the same regions as adjacent characters.
There are two work-arounds to this. Adafruit says in order to replace previously drawn text when using custom fonts you can either:
Use getTextBounds() to determine the smallest rectangle that encloses a
string and then erase that area using fillRect() prior to drawing
the new text. OR
Create an offscreen bitmap using GFXcanvas1 for a fixed size area,
draw the text in the GFXcanvas1 object and then copy to the screen
using drawBitmap().
Note that options 1 & 2 above are mutually exclusive. The second method requires more memory. The first method isn't perfect and produces some small amount of flicker, but is in general acceptable if coded carefully.
I hope that I have understood what the nature of your problem is and answered it in a satisfactory manner. If nothing else, at least now you know why custom font's will not work with the so called background color feature that works with the original 'classic' Adafruit fonts.
Nikki Cooper
I need suggestion on how to plot points real-time. Using OpenGL
Right now what am doing is loading the desired data from a csv to an array and plotting the points from there. This is working fine.
What I intend to do is, load such multiple csv's one by one at regular intervals of time, so that i can create a animation kind of output. I can do this but once the program plots the point by entering glutMainLoop();, it never gets out without closing opengl window. I want to load the 1st csv, show it in OpenGL window, then load the next csv and show the new set of points and so on.
If its difficult to comprehend, just see the image below
Just consider the red and blue points.Consider them as not actually moving but being plotted from an external data with each new postions loaded from the csv file. Hope its clear
[...] once the program plots the point by entering glutMainLoop();, it never gets out without closing opengl window.
freeglut extends glut by glutLeaveMainLoop and glutMainLoopEvent.
e.g.:
bool condtion = true;
while (condtion)
{
glutMainLoopEvent(); // handle the main loop once
glutPostRedisplay(); // cause `display` to be called in `glutMainLoopEvent`
condtion = ...;
}
Another option would be to use glutIdleFunc to do additional stuff. So it is not necessary to leave the glut main loop at all..
I have a class derived from CStatic and on that i m painting lines to show measurement in MFC C++ project. The problem is that I m displaying the line's distance at round about the mid of the line. I m using ExtTextOut function to draw the text. As i m using device context for that, I googled alot to erase that text and redraw on some other location, but i m unable to do. Basically CStatic has an image display over which i m drawing for measurement. Please can anyone tell me how to erase the text drawn through ExtTextOut without harming the background image?
Thanks In advance
I don't think you can just erase the text, leaving what's behind it untouched. You have to redraw the background again.
If you don't want to redraw everything, you can invalidate the part where the text lies (with InvalidateRect or InvalidateRgn) and only that will be redrawn.
Another option, that works with lines but I don't know if it works with text, would be to set the drawing mode with CDC::SetROP2 to R2_XORPEN (I think), draw the text, then draw it again to erase it. By doing it this way, the text will look "mixed" with the background, though.
I was wondering if there is a way to draw a gl::texture file with out having to use the gl::draw command every loop. Is there a way I can draw it once, and then not worry about it.
Drawing the image on every loop of draw() is slowing down my application, so I'd like to only draw things once on the screen and then update them if need be.
Quoting from Cinder's tutorials:
"When you create a new Cinder project, you will notice there are a few functions declared for you. Every Cinder project is made up of three main functions. You initialize your variables in the setup() method which is called once when your program begins. You make changes to those variables in the update() method. And finally, you draw() content in your program window. Update and draw are the heartbeat of any Cinder project. UpdateSetup, then update and draw, update and draw, update and draw, on and on until you quit the application."
There's a way though to draw objects permanently in OpenGL and concequently in Cinder but I wouldn't recommend it. Is to disable gl::clear() in your draw function. You can't though selectively delete any unneeded object. You will have to render your scene from scratch. Think of OpenGL's frame-buffer more of a canvas. Everytime you call gl::clear() you take the brush and you paint your canvas black or what ever color you specify with gl::clear(). After that the frame-buffer is "tabula rasa" you have to draw everything you want to display from scratch. If you don't state any gl::clear() command when you draw a new object is like your canvas stays intact and you draw your object on top of the already drawn.