[KWWidgets] how to prevent vtkKWRenderWidget warning on destroy?

Patrick D. Emond patrickdemond at gmail.com
Fri Dec 7 11:14:15 EST 2007


Hi Dean,

I was looking at this error again last night and I think I may have come 
up with a solution.  Before deleting any vtkKWRenderWidget always clear 
out it's parent:


this->RenderWidget->SetParent( NULL );
this->RenderWidget->Delete();
this->RenderWidget = NULL;


When you set any KW object's parent using SetParent(parent), the parent 
registers the child.  Here's what I mean:


this->RenderWidget = vtkKWRenderWidget::New(); // ReferenceCount = 1
this->RenderWidget->SetParent( ParentWidget ); // ReferenceCount = 2


So, now if you try deleting either ParentWidget OR RenderWidget first 
you get that "is being destroyed" message:


this->RenderWidget->Delete(); // ReferenceCount from 2 to 1
                               // since it is not 0 we get the error
this->ParentWidget->Delete();

OR

this->ParentWidget->Delete(); // this tries to delete RenderWidget,
                               // lowering ReferenceCount from 2 to
                               // but since it is not 0 we get the error
this->RenderWidget->Delete();


By setting the parent of our RenderWidget to NULL before deleting it the 
ParentWidget lets go of the RenderWidget, lowering it's ReferenceCount 
by 1 and thus not causing the error on delete.

I haven't tried this using your code, but I do have it working in my 
own.  Try it out and see if it works for you.

Patrick

dean.inglis at camris.ca wrote:
> I've been trying to figure this out and
> am stumped.  I created a vtkKWRenderWidget
> in the custom KWWidget class as part of the 
> example in KWWidgets/Examples/Cxx/Tutorial1
> and then in the main application, KWTutorial1
> parented the custom widget to a vtkKWFrameWithLabel.  I get the same error!
> Can someone please try adding a subdir called
> Step5 to KWWidgets/Examples/Cxx/Tutorial1
> and populate it with the following modified
> custom widget, and then replace KWTutorial1.cxx
> with the one below???  Does anyone else get
> the same error with this test?
> 
> thanks,
> Dean
> 
>> Subject: Re: [KWWidgets] how to prevent vtkKWRenderWidget warning on
>>   destroy?
>>
>> At 11/5/2007 10:26 AM, dean.inglis at camris.ca wrote:
>>> Hi,
>>>
>>> I posted on this topic in June and didn't get a response.
>>> Still having the same error/warning.  I have a custom composite
>>> widget that has a vtkKWRenderWidget ivar for displaying an
>> Hi
>> This is probably one of the oldest error message in VTK, sadly :)
>> It has to do with order your widgets are destroyed.
>> Please make sure your RenderWidget/RenderWindow is destroyed 
>> released/destroyed before its parents.
>>  > A TkRenderWidget is being destroyed before it associated 
>> vtkRenderWindow is destroyed.
>>
>> It's pretty explicit: your render window has to be released before 
>> the widget itself... Something might be holding on to your render window.
>>
> 
> // -------------------vtkKWMyWidget.h--------------
> #ifndef __vtkKWMyWidget_h
> #define __vtkKWMyWidget_h
> 
> #include "vtkKWCompositeWidget.h"
> 
> class vtkKWLabel;
> class vtkKWCheckButton;
> class vtkKWRenderWidget;
> 
> class vtkKWMyWidget : public vtkKWCompositeWidget
> {
> public:
>   static vtkKWMyWidget* New();
>   vtkTypeRevisionMacro(vtkKWMyWidget,vtkKWCompositeWidget);
>   void PrintSelf(ostream& os, vtkIndent indent);
> 
>   // Description:
>   // Get the internal widgets.
>   vtkGetObjectMacro(Label, vtkKWLabel);
>   vtkGetObjectMacro(CheckButton, vtkKWCheckButton);
> 
>   // Description:
>   // Set/Get the background color of the label when the checkbutton is selected
>   vtkGetVector3Macro(SelectedBackgroundColor, double);
>   virtual void SetSelectedBackgroundColor(double r, double g, double b);
>   virtual void SetSelectedBackgroundColor(double rgb[3])
>     { this->SetSelectedBackgroundColor(rgb[0], rgb[1], rgb[2]); }; 
> 
>   // Description:
>   // Update the "enable" state of the object and its internal parts.
>   // Depending on different Ivars (this->Enabled, the application's 
>   // Limited Edition Mode, etc.), the "enable" state of the object is updated
>   // and propagated to its internal parts/subwidgets.
>   virtual void UpdateEnableState();
> 
> protected:
>   vtkKWMyWidget();
>   ~vtkKWMyWidget();
> 
>   vtkKWLabel *Label;
>   vtkKWCheckButton *CheckButton;
>   vtkKWRenderWidget *RenderWidget;
> 
>   double SelectedBackgroundColor[3];
> 
>   // Description:
>   // Create the widget.
>   virtual void CreateWidget();
> 
>   // Description:
>   // Update the label's aspect according to the checkbutton's state.
>   virtual void UpdateLabel();
> 
>   // Description:
>   // Processes the events that are passed through CallbackCommand (or others).
>   virtual void ProcessCallbackCommandEvents(
>     vtkObject *caller, unsigned long event, void *calldata);
> 
> private:
>   vtkKWMyWidget(const vtkKWMyWidget&);   // Not implemented.
>   void operator=(const vtkKWMyWidget&);  // Not implemented.
> };
> 
> #endif
> 
> // -------------------vtkKWMyWidget.cxx--------------
> #include "vtkKWMyWidget.h"
> 
> #include "vtkObjectFactory.h"
> #include "vtkKWLabel.h"
> #include "vtkKWCheckButton.h"
> #include "vtkKWRenderWidget.h"
> #include "vtkKWTkUtilities.h"
> 
> //----------------------------------------------------------------------------
> vtkStandardNewMacro( vtkKWMyWidget );
> vtkCxxRevisionMacro(vtkKWMyWidget, "$Revision: 1.1 $");
> 
> //----------------------------------------------------------------------------
> vtkKWMyWidget::vtkKWMyWidget()
> {
>   this->Label = NULL;
>   this->CheckButton = NULL;
>   this->RenderWidget = NULL;
> 
>   this->SelectedBackgroundColor[0] = 0.8;
>   this->SelectedBackgroundColor[1] = 0.2;
>   this->SelectedBackgroundColor[2] = 0.2;
> }
> 
> //----------------------------------------------------------------------------
> vtkKWMyWidget::~vtkKWMyWidget()
> {
>   if (this->Label)
>     {
>     this->Label->Delete();
>     this->Label = NULL;
>     }
> 
>   if (this->CheckButton)
> 	{
> 	this->CheckButton->Delete();
> 	this->CheckButton = NULL;
> 	}
> 
>   if (this->RenderWidget)
> 	{
> 	this->RenderWidget->Delete();
> 	this->RenderWidget = NULL;
> 	}
> }
> 
> //----------------------------------------------------------------------------
> void vtkKWMyWidget::CreateWidget()
> {
>   // Check if already created
> 
>   if (this->IsCreated())
>     {
>     vtkErrorMacro(<< this->GetClassName() << " already created");
>     return;
>     }
> 
>   // Call the superclass to create the composite widget container
> 
>   this->Superclass::CreateWidget();
> 
>   // Create our internal label widget
> 
>   this->Label = vtkKWLabel::New();
>   this->Label->SetParent(this);
>   this->Label->Create();
> 
>   // Create our internal checkbutton widget
> 
>   this->CheckButton = vtkKWCheckButton::New();
>   this->CheckButton->SetParent(this);
>   this->CheckButton->Create();
> 
>   // Pack both our internal widgets next to each other
> 
>   this->Script("pack %s %s -side left -padx 1", 
>                this->CheckButton->GetWidgetName(),
>                this->Label->GetWidgetName());
> 
>   // Listen to the checkbutton's SelectedStateChangedEvent so that we can
>   // update the label's aspect each time the checkbutton's state changes.
> 
>   if ( !this->RenderWidget )
> 	{
> 	this->RenderWidget = vtkKWRenderWidget::New();
> 	}
>   this->RenderWidget->SetParent(this);
>   this->RenderWidget->Create();
>   this->RenderWidget->SetBorderWidth(2);
>   this->RenderWidget->SetReliefToGroove();
>   this->RenderWidget->CornerAnnotationVisibilityOff();
>   this->RenderWidget->HeaderAnnotationVisibilityOff();
>   this->RenderWidget->SetWidth(200);
>   this->RenderWidget->SetHeight(200);
> 
>   this->Script("pack %s -side top -anchor nw -expand n -fill x -padx 2 -pady 2",
> 	 this->RenderWidget->GetWidgetName());
> 
>   this->AddCallbackCommandObserver(
>     this->CheckButton, vtkKWCheckButton::SelectedStateChangedEvent);
> 
>   // Update the label's aspect according to the checkbutton's state
> 
>   this->UpdateLabel();
> }
> 
> // ---------------------------------------------------------------------------
> void vtkKWMyWidget::UpdateEnableState()
> {
>   this->Superclass::UpdateEnableState();
> 
>   this->PropagateEnableState(this->Label);
>   this->PropagateEnableState(this->CheckButton);
> }
> 
> //----------------------------------------------------------------------------
> void vtkKWMyWidget::UpdateLabel()
> {
>   // If the checkbutton is selected, change the background color of the
>   // label (reset the parent's background color otherwise)
> 
>   if (this->CheckButton && this->Label)
>     {
>     if (this->CheckButton->GetSelectedState())
>       {
>       this->Label->SetBackgroundColor(this->SelectedBackgroundColor);
>       }
>     else
>       {
>       this->Label->SetBackgroundColor(this->GetBackgroundColor());
>       }
>     }
> }
> 
> //----------------------------------------------------------------------------
> void vtkKWMyWidget::ProcessCallbackCommandEvents(
>   vtkObject *caller, unsigned long event, void *calldata)
> {
>   // We received a notification from the checkbutton that its state changed.
>   // Let's update the label's font accordingly.
> 
>   if (caller == this->CheckButton && 
>       event == vtkKWCheckButton::SelectedStateChangedEvent)
>     {
>     this->UpdateLabel();
>     }
> 
>   this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata);
> }
> 
> //----------------------------------------------------------------------------
> void vtkKWMyWidget::SetSelectedBackgroundColor(double r, double g, double b)
> {
>   if ((r == this->SelectedBackgroundColor[0] &&
>        g == this->SelectedBackgroundColor[1] &&
>        b == this->SelectedBackgroundColor[2]) ||
>       r < 0.0 || r > 1.0 ||
>       g < 0.0 || g > 1.0 ||
>       b < 0.0 || b > 1.0)
>     {
>     return;
>     }
> 
>   this->SelectedBackgroundColor[0] = r;
>   this->SelectedBackgroundColor[1] = g;
>   this->SelectedBackgroundColor[2] = b;
>   
>   this->Modified();
> 
>   this->UpdateLabel();
> }
> 
> //----------------------------------------------------------------------------
> void vtkKWMyWidget::PrintSelf(ostream& os, vtkIndent indent)
> {
>   this->Superclass::PrintSelf(os,indent);
> 
>   os << indent << "SelectedBackgroundColor: ("
>      << this->SelectedBackgroundColor[0] << ", " 
>      << this->SelectedBackgroundColor[1] << ", " 
>      << this->SelectedBackgroundColor[2] << ")" << endl;
> }
> 
> // -------------------KWTutorial1.cxx--------------
> #include "vtkKWApplication.h"
> #include "vtkKWWindowBase.h"
> #include "vtkKWMyWidget.h"
> #include "vtkKWLabel.h"
> #include "vtkKWFrameWithLabel.h"
> #include "vtkFileOutputWindow.h"
> #include "vtkOutputWindow.h"
> 
> #include <vtksys/SystemTools.hxx>
> 
> int my_main(int argc, char *argv[])
> {
>   // Initialize Tcl
> 	vtkOutputWindow* ow = vtkOutputWindow::GetInstance();
>   vtkFileOutputWindow* fow = vtkFileOutputWindow::New();
>   fow->SetFileName( "debug.txt" );
>   if ( ow )
> 	{
> 	ow->SetInstance( fow );
> 	}
>   fow->Delete();
> 
>   Tcl_Interp *interp = vtkKWApplication::InitializeTcl(argc, argv, &cerr);
>   if (!interp)
>     {
>     cerr << "Error: InitializeTcl failed" << endl ;
>     return 1;
>     }
> 
>   // Create the application
> 
>   vtkKWApplication *app = vtkKWApplication::New();
>   app->SetName("KWTutorial1");
> 
>   // Add a window
> 
>   vtkKWWindowBase *win = vtkKWWindowBase::New();
>   app->AddWindow(win);
>   win->Create();
> 
>   vtkKWFrameWithLabel *frame = vtkKWFrameWithLabel::New();
>   frame->SetParent(win->GetViewFrame());
>   frame->Create();
>   frame->SetLabelText("Test");
> 
>   app->Script("pack %s -side top -anchor nw -expand n -fill x -pady 2",
> 			  frame->GetWidgetName());
> 
>   // Add our widget
>   
>   vtkKWMyWidget *my_widget = vtkKWMyWidget::New();
>   my_widget->SetParent(frame->GetFrame());
>   my_widget->Create();
>   my_widget->GetLabel()->SetText("Agree?");
> 
>   app->Script("pack %s -side left -anchor c -expand y", 
>               my_widget->GetWidgetName());
> 
>   // Start the application
> 
>   int ret = 0;
>   win->Display();
>   app->Start(argc, argv);
>   ret = app->GetExitStatus();
>   win->Close();
> 
>   // Deallocate and exit
> 
>   my_widget->Delete();
>   win->Delete();
>   app->Delete();
>   
>   return ret;
> }
> 
> #if defined(_WIN32) && !defined(__CYGWIN__)
> #include <windows.h>
> int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int)
> {
>   int argc;
>   char **argv;
>   vtksys::SystemTools::ConvertWindowsCommandLineToUnixArguments(
>     lpCmdLine, &argc, &argv);
>   int ret = my_main(argc, argv);
>   for (int i = 0; i < argc; i++) { delete [] argv[i]; }
>   delete [] argv;
>   return ret;
> }
> #else
> int main(int argc, char *argv[])
> {
>   return my_main(argc, argv);
> }
> #endif
> 
> 
> 
> _______________________________________________
> KWWidgets mailing list
> KWWidgets at kwwidgets.org
> http://public.kitware.com/cgi-bin/mailman/listinfo/kwwidgets
> 


More information about the KWWidgets mailing list