I am creating a main window having a number of frames as child frames on it. I want to add these frames at runtime and i am using the following code.
in NFrame.h
In NFrame.h
QList<QFrame *> nFrame;
and initialize them in NFrame.cpp as
In Nframe.cpp
for(int i=1;i<=n;i++)
{
nFrame[i] = new QFrame(this);
nFrame[i]->show();
}
Is this a correct way to do this or i have to do something else.
I have found my mistake in the above code. I was trying to initialize a QList with a new Instance of of QFrame. As structure of QList is very much similar to an array so In the QList we can add items either byinsert() method or by append().
The following code correct my mistakes.
for(int i=0;i<n;i++)
{
nFrame.append(new QFrame(this));
nFrame[i]->show();
}
Related
I have a std::vector of Gtk::Boxes, that store widgets. Now, I want to access a certain widget in the Box at [i].
for(auto& it : layouts) {
for(int i = 0; i < it->size(); ++i) {
if(it->itemAt(i)->widget()) {
it->itemAt(i)->widget()->setVisible((std::string(it->get_name())== StringID));
}
}
}
layouts: std::vector holding Gtk::Boxes.
itemAt is a pseudo method, (QT method) to access Gtk::Box at (i).
Gtk::Box is not the right abstraction. Every operation on widgets is relative to other widgets present in the container. If you want control over children at a specific location in your container, I would suggest moving from Gtk::Box to Gtk::Grid, which has special methods to do what you need. For example, you could use:
Widget* Gtk::Grid::get_child_at(int left,
int top
)
See the reference for more information.
This should be easy but I may be misunderstanding something fundamental.
I have ellipses (called movers) on a screen in box2d. The ellipse is represented by a body. The body has a variable r which I use to make the ellipse size.
I want to destroy the ellipse when the r=0.
This is what i have written:
for (int i = 0; i < movers.length; i++) {
if(movers[i].r<0){
box2d.destroyBody(movers[i].body);
}
}
However this gives me an assertion error at the line box2d.destroyBody(movers[i].body);
How do I correct this? Is this because I am destroying the body but not the ellipse possibly or some other subtlety?
So the answer is not intuituitive but for future reference the problem is that box2d gets confused when trying to kill bodies if it is done inside of a world timestep.
What does this mean?
It means that you have to add all the bodies you are using to an arrayList rather than an array and your code should work from that. If you do that then at the end of void draw you can add the following (where movers is an arrayList of objects which have bodies and r is an attribute which defines whether a body should be destroyed or not):
for (int i = movers.size()-1; i >= 0; i--) {
Mover p = movers.get(i);
if (p.r<0) { //r is whatever attribute of your body
movers.remove(i);
}
}
This will destroy the bodies by removing them from the arrayList you are working from
It seems I am trying to fill a std::map with objects that are not copyable, and I have not achieved to do it yet.
General problem
I want to use std::map in order to store some objects of a type called Image (More precisely, it is Gdiplus::Image). I cannot write things like:
map<string, Gdiplus::Image> loadedImages ;
Gdiplus::Image newImage( CString("totoro.png") );
loadedImages.insert(std::pair<string, Gdiplus::Image>( "totoro", newImage ) );
Function "insert" seems to be the problem here. The compiler says:
'Gdiplus::Image::Image' : cannot access private member declared in class 'Gdiplus::Image'
I am not sure that it is the right explaination, but it seems that "Image" lacks of a public method used in function "insert". (Copy operator ? Copy constructor ?).
What I have tried
I tried to use references in the map, but it seems putting references in containers never works. I tried to use raw pointers, but I had got errors when I tried to delete all the images in the destructor. I happened across this other (and quite similar) question and I have begun to care about smart pointers. So now, I am trying, as recommended in the answer, with std::shared_ptr. However, my case is slightly different.
I want to write a function "find" that returns an image. "find" gives the image found in the map if the key (its path) exists, else it loads the image, add it to the map and returns it. So I cannot create a new image inside the parenthesis as I need the pointer.
The only version I came up with, that can compile is:
(Drawer.h)
#include <map>
#include <memory>
#include <Gdiplus.h>
using std::map ;
using std::shared_ptr ;
class CDrawer
{
public:
CDrawer(void);
~CDrawer(void);
void drawImage(string p_pathToPicture)
private:
map<string, shared_ptr<Gdiplus::Image>> m_loadedImages ; // Keep every image in memory instead of loading them each time. Each image has its path as a key.
Gdiplus::Image* findImage(string& p_path); // get the image from the map if the image is already loaded, else load it.
};
(Drawer.cpp) (Constructors and destructors are empty)
void CDrawer::drawImage(string p_pathToImage)
{
// get the bounding rectangle of the image
//...
Gdiplus::Image* l_image = findImage(p_pathToImage);
// Draw the image.
//...
}
Gdiplus::Image* CDrawer::findImage(string& p_pathToImage)
{
auto iterator = m_loadedImages.find(p_pathToImage);
if (iterator == m_loadedImages.end() ) // image not found, so we have not already loaded it
{
shared_ptr<Gdiplus::Image> l_newImage( new Gdiplus::Image( CString( p_pathToImage.c_str()) ) ); // Load the image (I know I have to add error code)
m_loadedImages.insert( std::pair<string, shared_ptr<Gdiplus::Image>>( p_pathToImage, l_newImage ) ); // Add the image to the list
return l_newImage.get() ;
}
else return iterator->second.get() ; // image found, so it is already loaded and we provide the existing one.
}
But it gives the following error during run time, when the destructor of Drawer is called:
Unhandled exception at 0x00C18CEE in MyProgramm.exe: 0xC0000005: Access violation reading location 0x02F36D78
Does someone knows where I am wrong, or if there is a simpler or better solution?
-(CCNode *)createFieldNode:(NSMutableArray *)fieldArray{
CGSize winSize = [CCDirector sharedDirector].viewSize;
CCNode* stackNode= [CCNode node];
for (int i; i <=fieldArray.count; i++){
//itemP is previous item in array and itemC is current item in area based on index i
BPItem*itemP;
BPItem*itemC;
if(i!=0){
itemP=[fieldArray objectAtIndex:i-1];
itemC=[fieldArray objectAtIndex:i];
float stackWidth=arc4random()%200+50;
float stackHeight=itemP.position.y+itemP.contentSize.height;
itemC.position=ccp(stackWidth,stackHeight);
}
else{
itemC=[fieldArray objectAtIndex:i];
float stackWidth=arc4random()%200+50;
itemC.position=ccp(stackWidth,0);
}
//having trouble adding multiple nodes to stackNode
[stackNode addChild:itemC];
}
return stackNode;
}
I want to add CCNodes from fieldArray on to a parent CCNode "stackNode". When I use breakpoints I am able to add the CCNode at index 0 and CCNode at index 1. However the program crash at i=2. The error I receive is:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'child already added to another node. It can't be added again'
Before the crash "stackNode" has two children. I'm not adding the CCNodes one by one because I have hundreds of different arrays with many a fieldArray.count around 20. Please help I can explain more if I have been unclear.
Change the for loop start as follows :
//itemP is previous item in array and itemC is current item in area based on index i
BPItem*itemP;
BPItem*itemC; // moved out of the for loop
for (int i; i <fieldArray.count; i++){ // <- changed the end condition to avoid crash
... rest of loop
Also, in the code that creates fieldArray, make certain you have logic to ensure that there are no duplicates, otherwise you will have the same issue (but for an altogether different reason).
I'm writing an application that runs an algorithm, but allows you to 'step through' the algorithm by pressing a button - displaying what's happening at each step.
How do I listen for events while within a method?
eg, look at the code I've got.
static int proceed;
button1Event(GtkWidget *widget)
{
proceed = 0;
int i = 0;
for (i=0; i<15; i++) //this is our example 'algorithm'
{
while (proceed ==0) continue;
printf("the nunmber is %d\n", i);
proceed = 0;
}
}
button2Event(GtkWidget *widget)
{
proceed = 1;
}
This doesn't work because it's required to exit out of the button1 method before it can listen for button2 (or any other events).
I'm thinking something like in that while loop.
while(proceed == 0)
{
listen_for_button_click();
}
What method is that?
The "real" answer here (the one any experienced GTK+ programmer will give you) isn't one you will like perhaps: don't do this, your code is structured the wrong way.
The options include:
recommended: restructure the app to be event-driven instead; probably you need to keep track of your state (either a state machine or just a boolean flag) and ignore whichever button is not currently applicable.
you can run a recursive main loop, as in the other answer with gtk_main_iteration(); however this is quite dangerous because any UI event can happen in that loop, such as windows closing or other totally unrelated stuff. Not workable in most real apps of any size.
move the blocking logic to another thread and communicate via a GAsyncQueue or something along those lines (caution, this is hard-ish to get right and likely to be overkill).
I think you are going wrong here:
while(proceed == 0)
{
listen_for_button_click();
}
You don't want while loops like this; you just want the GTK+ main loop doing your blocking. When you get the button click, in the callback for it, then write whatever the code after this while loop would have been.
You could check for pending events & handle the events in while loop in the clicked callback. Something on these lines:
button1Event(GtkWidget *widget)
{
proceed = 0;
int i = 0;
for (i=0; i<15; i++) //this is our example 'algorithm'
{
while (proceed ==0)
{
/* Check for all pending events */
while(gtk_events_pending())
{
gtk_main_iteration(); /* Handle the events */
}
continue;
}
printf("the nunmber is %d\n", i);
proceed = 0;
}
}
This way when the events related click on the second button is added to the event queue to be handled, the check will see the events as pending and handle them & then proceed. This way your global value changes can be reflected & stepping should be possible.
Hope this helps!
If you want to do it like this, the only way that comes to my mind is to create a separate thread for your algorithm and use some synchronization methods to notify that thread from within button click handlers.
GTK+ (glib, to be more specific) has its own API for threads and synchronization. As far as I know Condition variables are a standard way to implement wait-notify logic.