wxGrid and wxBitmap Topic is solved
Re: wxGrid and wxBitmap
Which compiler do you use? If it's Visual Studio, does it report memory leaks when you quit the application?
In the code you posted, there are two potential memory leaks, the pointers "pBlob" and "pFoto". Most likely these need to be freed, but it depends on the functions that return them.
E.g. it could be possible that the CloseResultSet() call also frees the memory "pBlob" points to.
In the code you posted, there are two potential memory leaks, the pointers "pBlob" and "pFoto". Most likely these need to be freed, but it depends on the functions that return them.
E.g. it could be possible that the CloseResultSet() call also frees the memory "pBlob" points to.
Use the source, Luke!
Re: wxGrid and wxBitmap
I'm using MinGW under codeBlocks .
pBlob and pFoto are pointers to one element (image). Also, they are not allocated dynamically.
I found a similar topic on the forum viewtopic.php?t=31071, the question also arose about a memory leak. The fact is that the string information in the cells is deleted by the following method
Grid1->ClearGrid();
But the documentation also says that in order to display information that differs from string data, it is necessary to redefine the renderer, which we did. But I noticed that by making several different queries to the database, the allocated memory for the application grows, while the display in the cells is cleared.
PS:
Perhaps you need to override the destructor of the wxBmpGridCellRenderer class and explicitly delete the member of the wxImage m_img; class in it?
however, this does not work if the class member is not a pointer to a wxImage object. And I don't know how to rewrite the wxBmpGridCellRenderer constructor using an initialization list with a pointer.
pBlob and pFoto are pointers to one element (image). Also, they are not allocated dynamically.
I found a similar topic on the forum viewtopic.php?t=31071, the question also arose about a memory leak. The fact is that the string information in the cells is deleted by the following method
Grid1->ClearGrid();
But the documentation also says that in order to display information that differs from string data, it is necessary to redefine the renderer, which we did. But I noticed that by making several different queries to the database, the allocated memory for the application grows, while the display in the cells is cleared.
PS:
Perhaps you need to override the destructor of the wxBmpGridCellRenderer class and explicitly delete the member of the wxImage m_img; class in it?
Code: Select all
class wxBmpGridCellRenderer : public wxGridCellRenderer
{
public:
wxBmpGridCellRenderer(const wxImage& image) : wxGridCellRenderer(), m_img(image) {}
/*
~wxBmpGridCellRenderer()
{
delete m_img;
}
*/
void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
const wxRect& rect, int row, int col, bool isSelected);
wxSize GetBestSize(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
int row, int col)
{
return wxSize(m_img.GetWidth(), m_img.GetHeight());
}
wxGridCellRenderer *Clone() const
{
return new wxBmpGridCellRenderer(m_img);
}
private:
wxImage m_img;
};
Re: wxGrid and wxBitmap
m_img in wxBmpGridCellRenderer is a member variable, it will be destroyed when the renderer gets destroyed.
Check the documentation for GetResultBlob(), it should say something about who's responsible for freeing the memory.
What does LoadImageFromBlob do? If it creates the wxImage with new, someone must delete it later.
pBlob and pFoto are pointers to one element (image). Also, they are not allocated dynamically.
Code: Select all
void *pBlob = pResults->GetResultBlob(_("FIMG"),BufferOut);
Code: Select all
m_foto = LoadImageFromBlob(pRetrievedBuffer,len);
Use the source, Luke!
Re: wxGrid and wxBitmap
Below is the implementation of the LoadImageFromBlob() method
pFoto is a pointer to wxImage and is declared in the main form class
I make several identical queries to the database in a row and in the Windows task manager it is clear that the memory consumed by the application is increasing. Therefore, I concluded that there is a memory leak, but I can not understand how it can be detected.
How can I check how much memory is allocated for the renderer? Since most likely
do not remove the renderer from memory
Code: Select all
wxImage* testWxSmithFrame::LoadImageFromBlob(const unsigned char *data, int size)
{
if( data != NULL )
{
wxMemoryInputStream mi(data, size);
wxImage *img = new wxImage(mi, wxBITMAP_TYPE_ANY);
if( img != NULL && img->IsOk() ) return img;
// wxLogDebug( wxT("DB::LoadImageFromBlob error: data=%p size=%d"), data, size);
// caller is responsible for deleting the pointer
delete img;
}
return NULL;
}
Code: Select all
class testWxSmithFrame: public wxFrame
{
public:
testWxSmithFrame(wxWindow* parent,wxWindowID id = -1);
virtual ~testWxSmithFrame();
wxImage*pPhoto;
private:
//(*Handlers(testWxSmithFrame)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnSendQueryButtonClick(wxCommandEvent& event);
void OnClearEntryFieldButtonClick(wxCommandEvent& event);
void OnCheckBoxEnableFotoClick(wxCommandEvent& event);
//*)
virtual int OnExit();
bool OpenDB();
wxImage* LoadImageFromBlob(const unsigned char*, int);
...
}
How can I check how much memory is allocated for the renderer? Since most likely
Code: Select all
Grid1->ClearGrid();
for(int i = 0; i < Grid1->GetNumberRows(); i++)
Grid1->SetCellRenderer(i,0,NULL);
Re: wxGrid and wxBitmap
pPhoto doesn't need to be a member variable.
And as the renderer makes a copy of the image, you can (and should) delete pPhoto after creating the renderer.
And as the renderer makes a copy of the image, you can (and should) delete pPhoto after creating the renderer.
Use the source, Luke!
Re: wxGrid and wxBitmap
And since I'm displaying the image through DrawBitmap, it is necessary to refine the implementation of the Draw method, with the ability to change the display. But, to be honest, I find it difficult to use the DrawBitmap method to hide it and then display it
Last edited by doublemax on Mon Jan 24, 2022 1:33 pm, edited 1 time in total.
Reason: Sorry, i accidently edited your post instead of replying to it. So some parts are missing now.
Reason: Sorry, i accidently edited your post instead of replying to it. So some parts are missing now.
Re: wxGrid and wxBitmap
Don't overthink it, this is very simple program logic. Depending on a condition you either call DrawBitmap() or you don't.
Use the source, Luke!
Re: wxGrid and wxBitmap
Hi,
Are you doing it the same way as in the sample?
Thank you.
Are you doing it the same way as in the sample?
Thank you.
Re: wxGrid and wxBitmap
Indeed, it is simple. True, I have a visibility condition
if(CheckBoxEnableFoto->GetValue())
not available in renderer method
if(CheckBoxEnableFoto->GetValue())
not available in renderer method
Re: wxGrid and wxBitmap
Or do I need to add a public class member (photo display flag) in the renderer class and set or uncheck the flag in the checkbox handler, and check its state in the Draw method?
Re: wxGrid and wxBitmap
That depends on whether this is a global switch (turn off/on images), or can be set for each item. In the latter case: yes, you'll need another flag for that.Melandr wrote: ↑Mon Jan 24, 2022 2:36 pmOr do I need to add a public class member (photo display flag) in the renderer class and set or uncheck the flag in the checkbox handler, and check its state in the Draw method?
Use the source, Luke!
Re: wxGrid and wxBitmap
If I declare a checkbox in the declaration of the class of the Main form in the private section, then I can access the checkbox properties from the methods of the main form class, but I cannot access from the method of the renderer class. And vice versa. How can I check if the checkbox is enabled from all classes?
As I understand it, I should get a pointer to the parent of the checkbox - the main form, and then check the state of the checkbox? But which class should the pointer to the main form be a member of?
How to get checkbox state from renderer class?
As I understand it, I should get a pointer to the parent of the checkbox - the main form, and then check the state of the checkbox? But which class should the pointer to the main form be a member of?
How to get checkbox state from renderer class?
Re: wxGrid and wxBitmap
There are several ways to do that.
1)
- renderer has bool flag to control image visibility, startvalue passed to constructor
- renderer has public method to change status of that flag
When the status of the checkbox changes, iterate over the grid, get the renderers, and call method to change visibility
2)
- subclass wxGrid
- custom wxGrid has bool flag to control image visibility
- custom wxGrid has public method to change status of that flag
renderer Draw() method gets reference to wxGrid. Use that to check status of flag
1)
- renderer has bool flag to control image visibility, startvalue passed to constructor
- renderer has public method to change status of that flag
When the status of the checkbox changes, iterate over the grid, get the renderers, and call method to change visibility
2)
- subclass wxGrid
- custom wxGrid has bool flag to control image visibility
- custom wxGrid has public method to change status of that flag
renderer Draw() method gets reference to wxGrid. Use that to check status of flag
Use the source, Luke!
Re: wxGrid and wxBitmap
The first two points are not difficult.
- renderer has bool flag to control image visibility, startvalue passed to constructor
- renderer has public method to change status of that flag
But on the third point, how can you control the displayed information in a cell without clearing the renderer? After filling the cells of the first column with images, I can remove the images before a new request with the following code
I can not understand how you can hide the display in the cell, and then display it again? Below is the renderer code in the cell
- renderer has bool flag to control image visibility, startvalue passed to constructor
- renderer has public method to change status of that flag
But on the third point, how can you control the displayed information in a cell without clearing the renderer? After filling the cells of the first column with images, I can remove the images before a new request with the following code
Code: Select all
Grid1->ClearGrid();
ClearCellGrid(*Grid1);
Code: Select all
void wxBmpGridCellRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rect, int row, int col, bool isSelected)
{
if(m_IsVisiblePhoto)
{
wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
dc.SetClippingRegion(rect);
m_img.Rescale(wxSize(109,145).GetWidth(),wxSize(109,145).GetHeight());
wxBitmap cellBitmap(m_img);
dc.DrawBitmap(cellBitmap,rect.x,rect.y);
dc.DestroyClippingRegion();
}
}