Displaying Text in the ApplicationWindow

Forum for discussion on different user applications
Locked
vladi
Posts: 18
Joined: 04 Jan 2012, 08:29

Displaying Text in the ApplicationWindow

Post by vladi » 13 Sep 2012, 05:18

Hallo,

I would like to create my one Stimulus Presentation Mudule in order to present some text or figures depending on a simple Trigger Signal which is generated by the SignalProcessing Module. I already created a Stuimulus Presentation Module and try to access the mrDisplay object which was automatically created. But I have difficulties to visualise some text with mrDisplay. Can somebody give me a example how to script it. Thanks in advance.

Regards,
Vladi

mellinger
Posts: 1210
Joined: 12 Feb 2003, 11:06

Re: Displaying Text in the ApplicationWindow

Post by mellinger » 17 Sep 2012, 09:51

Hi,

the GraphDisplay class is not a scripting class. In order to use it, you need to create objects derived from GraphObject, and specify the mrObject variable as their parent when they are created.

So what you probably want to do is

Code: Select all

// Class declaration in MyStimulusPresentationTask.h
class MyStimulusPresentationTask : public StimulusTask
{
 TextStimulus* mpTextStimulus;
 ...
};

// Class implementation in MyStimulusPresentationTask.cpp
// Constructor
MyStimulusPresentationTask::MyStimulusPresentationTask
: mpTextStimulus( new TextStimulus( mrDisplay ) )
{
  GUI::Rect r = { 0.5, 0.5, 0.5, 0.5 }; // empty rectangle at the center of the window
  mpTextStimulus->SetObjectRect( r );
  // set auto-adjustment of the rectangle's size according to text
  mpTextStimulus->SetAspectRatioMode( GUI::ApectRatioModes::AdjustBoth );
  ...
}

void
MyStimulusPresentationTask::OnWhateverEvent()
{
  mpTextStimulus->SetText( "Hello World" );
  mpTextStimulus->Present();
}
...

void
MyStimulusPresentationTask::OnWhateverOtherEvent()
{
  mpTextStimulus->Hide();
}
...
Instead of "OnWhateverEvent", you will need to write an event handler for an actual event you want to handle. For a documentation of StimulusTask events, see the StimulusTask documentation at
http://www.bci2000.org/wiki/index.php/P ... Task_Class
Note that nothing will happen when you present and hide a stimulus from inside the same event handler, as display changes will only occur after event handlers have been executed.
For more information about TextStimulus and other stimulus classes, see
http://www.bci2000.org/wiki/index.php/P ... ulus_Class
and the "See also" links and categories at the bottom of that page.

If you want to display stimuli as part of a stimulus sequence (i.e., not a text message independent of the sequence of actual stimuli), the approach is different. In that case, you use the OnInitialize() event to populate the set of stimulus associations with stimulus codes and associated stimuli. You also implement an OnNextStimulusCode() event handler which provides the desired sequence of stimulus codes:

Code: Select all

// Class declaration
class MyStimulusPresentationTask : public StimulusTask
{
  ...
  std::vector<int> mSequence;
  size_t mSequencePosition;
}

void
MyStimulusPresentationTask::OnInitialize()
{
  GUI::Rect r = { 0.5, 0.5, 0.5, 0.5 }; // empty rectangle at the center of the window
  TextStimulus* pTextStimulus = new TextStimulus( mrDisplay );
  pTextStimulus->SetObjectRect( r );
  pTextStimulus->SetAspectRatioMode( GUI::ApectRatioModes::AdjustBoth );
  pTextStimulus->SetText( "Text1" );
  // The following line makes that the stimulus will be presented
  // when stimulus code 1 appears in the sequence.
  Associations()[1].Add( pTextStimulus );
  // Here, we don't need a pointer to the first stimulus any more, as it will be
  // presented and deallocated automatically.

  // Let's add another stimulus:
  pTextStimulus = new TextStimulus( mrDisplay );
  pTextStimulus->SetObjectRect( r );
  // set auto-adjustment of the rectangle's size according to text
  pTextStimulus->SetAspectRatioMode( GUI::ApectRatioModes::AdjustBoth );
  pTextStimulus->SetText( "Text2" );
  Associations()[2].Add( pTextStimulus );
}

void
MyStimulusPresentationTask::OnStartRun()
{
  // Create a new sequence:
  mSequence.clear();
  for( int i = 0; i < 10; ++i )
    mSequence.push_back( RandomGenerator( 2 ) + 1 );
  mSequencePosition = 0;
}

int
MyStimulusPresentationTask::OnNextStimulusCode()
{
  if( mSequencePosition >= mSequence.size() )
    return 0;
  return mSequence[mSequencePosition++];
}
Calling RandomGenerator( N ) will return a random number between 0 and N-1. Note that stimulus codes must be greater 0, as a stimulus code of 0 indicates that no stimulus is presented, and is also treated as an end-of-sequence indicator.

Regards,
Juergen

vladi
Posts: 18
Joined: 04 Jan 2012, 08:29

Re: Displaying Text in the ApplicationWindow

Post by vladi » 01 Oct 2012, 13:51

Hallo Juergen,

Thank you very much for your answer. I tried to follow your instruction but unforntunatly it didn't worked out. When I create a new Application Module I get those functions automatically created:

virtual void Halt();
virtual void Preflight( const SignalProperties& Input, SignalProperties& Output const;
virtual void Initialize( const SignalProperties& Input, const SignalProperties& Output );
virtual void StartRun();
virtual void Process( const GenericSignal& Input, GenericSignal& Output );
virtual void StopRun();

Now I would like to present in the Process function some text in the application window but I am not able to figure out how.
I tried it with the following code but I think that I don't get some basic points.

mrDisplay.SetColor(RGBColor::White);
TextStimulus* mpTextStimulus = new TextStimulus( mrDisplay );

mpTextStimulus->SetText("dasda").SetColor(RGBColor::Black);
mpTextStimulus->Show();

Regards,
Vladi

mellinger
Posts: 1210
Joined: 12 Feb 2003, 11:06

Re: Displaying Text in the ApplicationWindow

Post by mellinger » 02 Oct 2012, 08:42

Hallo Vladi,

sorry, in my example code I forgot to set a rectangle for the stimulus, that's why it didn't appear.
I corrected the example code accordingly.

Regards,
Juergen

vladi
Posts: 18
Joined: 04 Jan 2012, 08:29

Re: Displaying Text in the ApplicationWindow

Post by vladi » 04 Oct 2012, 04:54

Hallo Juergen,

Thank you again. Now it works but I have one problem left. Namely the size of the rectangle seems not to adjust to the text. Here is my code:

SimpleStimulusPresentationTask.cpp

Code: Select all

#include "StimulusTask.h"
#include "PCHIncludes.h"
#pragma hdrstop
#include "TextWindow.h"
#include "SimpleStimulusPresentationTask.h"
#include "BCIError.h"
#include <windows.h>


using namespace std;



RegisterFilter( SimpleStimulusPresentationTask, 3 );
     // Change the location if appropriate, to determine where your filter gets
     // sorted into the chain. By convention:
     //  - filter locations within SignalSource modules begin with "1."
     //  - filter locations within SignalProcessing modules begin with "2."  
     //       (NB: SignalProcessing modules must specify this with a Filter() command in their PipeDefinition.cpp file too)
     //  - filter locations within Application modules begin with "3."


SimpleStimulusPresentationTask::SimpleStimulusPresentationTask() :
 mrDisplay( Window() )
{

  // Declare any parameters that the filter needs....
	
 BEGIN_PARAMETER_DEFINITIONS

   "Application:SimpleStimulusPresentationTask int EnableSimpleStimulusPresentationTask= 0 0 0 1 // enable SimpleStimulusPresentationTask? (boolean)",                       // These are just examples:
   "Application:SimpleStimulusPresentationTask float SomeParameter=  0.0 0.0 -1.0 1.0 // a useless SimpleStimulusPresentationTask parameter",   //  change them, or remove them.

 END_PARAMETER_DEFINITIONS
 
 
  // ...and likewise any state variables:

 BEGIN_STATE_DEFINITIONS
 
   "SomeState       8 0 0 0",    // These are just examples. Change them, or remove them.
   "SomeOtherState 16 0 0 0",
   
 END_STATE_DEFINITIONS

 
}


SimpleStimulusPresentationTask::~SimpleStimulusPresentationTask()
{
  Halt();
}

void
SimpleStimulusPresentationTask::Halt()
{
  // De-allocate any memory reserved in Initialize, stop any threads, etc.
  // Good practice is to write the Halt() method such that it is safe to call it even *before*
  // Initialize, and safe to call it twice (e.g. make sure you do not delete [] pointers that
  // have already been deleted:  set them to NULL after deletion).
}

void
SimpleStimulusPresentationTask::Preflight( const SignalProperties& Input, SignalProperties& Output ) const
{
	
  Output = Input; // this simply passes information through about SampleBlock dimensions, etc....
}


void
SimpleStimulusPresentationTask::Initialize( const SignalProperties& Input, const SignalProperties& Output )
{

  r.left = 1;
  r.right = 0;
  r.bottom = 0;
  r.top= 1;

 
  mpTextStimulus =  new TextStimulus( mrDisplay);
  mpTextStimulus->SetTextHeight(0.6)
	  .SetColor(RGBColor::White)
	  .SetTextColor(RGBColor::Blue)
	  .SetColor(RGBColor::White)
	  .SetObjectRect(r)
	  .SetAspectRatioMode(GUI::AspectRatioModes::AdjustBoth);


}

void
SimpleStimulusPresentationTask::StartRun()
{
  // The user has just pressed "Start" (or "Resume")
  bciout << "Hello World!" << endl;
}


void
SimpleStimulusPresentationTask::Process( const GenericSignal& Input, GenericSignal& Output )
{
	mpTextStimulus->SetText( "Hal" );
    mpTextStimulus->Present();

    Output = Input; // This passes the signal through unmodified.                  
}

void
SimpleStimulusPresentationTask::StopRun()
{
  // The Running state has been set to 0, either because the user has pressed "Suspend",
  // or because the run has reached its natural end.
  bciout << "Goodbye World." << endl;
  // You know, you can delete methods if you're not using them.
  // Remove the corresponding declaration from SimpleStimulusPresentationTask.h too, if so.
}
SimpleStimulusPresentationTask.h

Code: Select all

////////////////////////////////////////////////////////////////////////////////
// $Id: $
// Authors: 
// Description: SimpleStimulusPresentationTask header
//   
//   
// $BEGIN_BCI2000_LICENSE$
// 
// This file is part of BCI2000, a platform for real-time bio-signal research.
// [ Copyright (C) 2000-2012: BCI2000 team and many external contributors ]
// 
// BCI2000 is free software: you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
// 
// BCI2000 is distributed in the hope that it will be useful, but
//                         WITHOUT ANY WARRANTY
// - without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License along with
// this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// $END_BCI2000_LICENSE$
////////////////////////////////////////////////////////////////////////////////

#ifndef INCLUDED_SimpleStimulusPresentationTask_H  // makes sure this header is not included more than once
#define INCLUDED_SimpleStimulusPresentationTask_H

#include "ApplicationBase.h"
#include "TextStimulus.h"
#include "ImageStimulus.h"
#include "StimulusTask.h"

class SimpleStimulusPresentationTask : public ApplicationBase
{
 public:
           SimpleStimulusPresentationTask();
  virtual ~SimpleStimulusPresentationTask();
  virtual void Halt();
  virtual void Preflight(  const SignalProperties& Input,       SignalProperties& Output ) const;
  virtual void Initialize( const SignalProperties& Input, const SignalProperties& Output );
  virtual void StartRun();
  virtual void Process(    const GenericSignal&    Input,       GenericSignal&    Output );
  virtual void StopRun();

  
 private:
   ApplicationWindow& mrDisplay;
   //GUI::DisplayWindow mrDisplay;
   TextStimulus* mpTextStimulus;
   ImageStimulus* pStimulus;
   GUI::Rect r;
  // TextStimulus* mpTextStimulus;
   // Use this space to declare any APPWINDOW-specific methods and member variables you'll need
};

#endif // INCLUDED_SimpleStimulusPresentationTask_H
Regards,
Vladi

mellinger
Posts: 1210
Joined: 12 Feb 2003, 11:06

Re: Displaying Text in the ApplicationWindow

Post by mellinger » 04 Oct 2012, 08:59

Your rectangle is invalid because its left/right and top/bottom coordinates are reverted.

As a side note: you should not create the rectangle as a member variable unless you want it to actually keep information in between function calls. Otherwise, the unneeded member variable introduces additional state into your class, which increases the difficulty of debugging, because bugs will have more circumstances to choose from when "deciding" to appear or not. Because of that, use a local variable:

Code: Select all

GUI::rect r = { 0, 0, 1, 1 };
Regards,
Juergen

Locked

Who is online

Users browsing this forum: No registered users and 20 guests