Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

WxPerl Next button

by saran73 (Initiate)
on Jan 04, 2013 at 16:30 UTC ( [id://1011675]=perlquestion: print w/replies, xml ) Need Help??

saran73 has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks. I'm writing an app to read data from XML that contains multiple choice question. I used 2 dialogs (one for the use user selecting the topic and another to show the question with answer choice using RadioBox). I'm not sure how to use the same button to show a question, wait for the user to select the answer and show the next question after he clicks next. Also, how can I update the choice string in the RadioBox for the next question? Thanks in advance for the help.

Replies are listed 'Best First'.
Re: WxPerl Next button
by jmlynesjr (Deacon) on Jan 04, 2013 at 20:00 UTC

    Refer to More wxPerl Examples now on Github. Specifically the CppTrial-pg086.pl and CppTrial-pg225.pl examples.

    You may need to create a custom dialog similar to pg225 that uses radio buttons rather than a list box. Look these examples over and post your code if you can.

    James

    There's never enough time to do it right, but always enough time to do it over...

      Hi James, Thanks for your reply. I did use few of the examples from the github (very useful and thanks for sharing it). Here is the code: (input is at the end of the file)
      use strict; use warnings; use Wx; use Wx::Event qw( EVT_BUTTON ); use Wx qw[:everything]; use base qw/Wx::Frame/; # Inherit from Wx::Frame our %panel; my $selectedChapter; Main( @ARGV ); exit( 0 ); sub Main { my $app = Wx::SimpleApp->new; my $frame = Wx::Frame->new( undef, -1, "Test window", [ 100, 100 ], [ 800, 600 ], Wx::wxDEFAULT_FRAME_STYLE()|Wx::wxTAB_TRAVERSAL() ); MakeChaptersPanel( $frame ); $frame->SetSizer( Wx::BoxSizer->new( Wx::wxVERTICAL() ) ); $frame->GetSizer->Add( $panel{first}, 1, Wx::wxEXPAND() ); $frame->Show(1); $app->SetTopWindow($frame); $app->MainLoop; } ## end sub Main sub MakeChaptersPanel { my( $frame ) = @_; $panel{'first'} = Wx::Panel->new( $frame, -1, [ -1, -1 ], [ -1, -1], ); Wx::StaticText->new( $panel{'first'}, 1, "Answer Verification App", [50, 50] ); my $SHOWQUESTION_BTNID = 1; my $showQuestions = Wx::Button->new( $panel{'first'}, $SHOWQUESTION_BTNID, "Show Questions", [150,300] ); my %chapters; my $data_pos = tell DATA; # save the position while (<DATA>) { if ( m@<questionId>.*?(\d\d)(\d{4})</questionId>@) { $chapters{$1}++; } } seek DATA, $data_pos, 0; my @chapters; foreach my $chapter (keys %chapters) { push(@chapters,$chapter); } my $CHAPTER_RADIOBOX = 2; my $selectChapter = Wx::RadioBox->new($panel{'first'}, $ CHAPTER_RADIOBOX, "Select the Chapter", Wx::Point->new(100,100), wxDefaultSize, \@chap +ters, 1, wxRA_SPECIFY_COLS); $selectChapter->SetSelection(1); Wx::Event::EVT_BUTTON( $frame, $showQuestions, sub{\&ShowQuestions(@_, $selectChapter->GetStringSelection())}); return; } ## end sub MakePanels sub MakeQuestionsPanel { my( $frame ) = @_; $panel{'second'} = Wx::Panel->new( $frame, -1, [ -1, -1 ], [ -1, -1 ], ); $panel{'second'}->Hide(); my $NEXTQUESTION_BTNID = 2; my $nextQuestionbtn = Wx::Button->new( $panel{'second'}, $NEXTQUESTION_BTNID, "Next Questions", [150,300] ); my $insideQuestion = 0; my @answerChoices; my $correctAnswer; my $weightage; my $QUESTIONS_RADIOBOX = 3; while (<DATA>) { if ( m@<Question>@ ) { $insideQuestion = 1; print $_; next; } if ( m@</Question>@ ) { $insideQuestion = 0; my $questionChoices = Wx::RadioBox->new($panel{'second'}, $QUESTIONS_RADIOBOX, "Answer Choices +", Wx::Point->new(100,100), wxDefaultSize, \@answerChoices, 1, wxRA_SPECIFY_COLS); $questionChoices->SetStringSelection($correctAnswer); last; } if ( $insideQuestion ) { if ( m@<questionId>.*?(\d\d)(\d{4})</questionId>@) { if ( $1 != $selectedChapter) { $insideQuestion = 0; next; } } if ( m@<question>(.*?)</question>@ ) { print "$1\n"; my $questionText = Wx::StaticText->new( $panel{'secon +d'}, 1, "$1", [50, 70] ); } elsif ( m@<Answer\d>(.*?)</Answer\d>@ ) { push(@answerChoices,$1); } elsif ( m@<CorrectAnswer>(.*?)</CorrectAnswer>@ ) { $correctAnswer = $1; } elsif ( m@<weightage>(.*?)</weightage>@ ) { $weightage = $1; } print "$_"; } } return; } sub ShowQuestions { my ( $frame, $event, $mySelectedChapter ) = @_; my $button = $event->GetEventObject; my $label = $button->GetLabel(); $selectedChapter = $mySelectedChapter; $frame->SetTitle("Chapter " . $selectedChapter); MakeQuestionsPanel( $frame ); $panel{first}->Hide(); $panel{second}->Show(); $frame->GetSizer->Add( $panel{second}, 1, Wx::wxEXPAND() ); $frame->GetSizer->Layout(); } __DATA__ <Question> <questionId>TNHSCS010001</questionId> <question>Jenkins is primiary used of ........</question> <Answer1> Nightly Builds </Answer1> <Answer3> CI Builds </Answer3> <Answer4> Report Generation </Answer4> <Answer1> All the above </Answer1> <CorrectAnswer> CI Builds </CorrectAnswer> </Question> <Question> <questionId>TNHSCS010002</questionId> <question>CI builds are setup to ............</question> <Answer1> catch potentail build errors</Answer1> <Answer2> find bugs </Answer2> <Answer3> reduce build time </Answer3> <Answer4> None of the above </Answer4> <CorrectAnswer> catch potentail build errors </CorrectAnswer> </Question> <Question> <questionId>TNHSCS020001</questionId> <question>Jenkins is primiary used of ........</question> <Answer1> Nightly Builds </Answer1> <Answer3> CI Builds </Answer3> <Answer4> Report Generation </Answer4> <Answer1> All the above </Answer1> <CorrectAnswer> CI Builds </CorrectAnswer> </Question> <Question> <questionId>TNHSCS020002</questionId> <question>CI builds are setup to ............</question> <Answer1> catch potentail build errors</Answer1> <Answer2> find bugs </Answer2> <Answer3> reduce build time </Answer3> <Answer4> None of the above </Answer4> <CorrectAnswer> catch potentail build errors </CorrectAnswer> </Question>

        I second the use of Wx::SingleChoiceDialog or Wx::MultiChoiceDialog like jmlynesjr sugested.

        Parsing XML like you do is not a good choice, use a dedicated module, something like this:

        use strict; use warnings; use XML::Simple; use Data::Printer; my $data = do { local $/; <DATA> }; # slurp DATA my $ref = XMLin( $data, #KeyAttr => { Question => 'questionId' }, # unordered data ForceArray => ['item'], ContentKey => '-content' ); p $ref; __DATA__ <Questions> <Question> <questionId>TNHSCS010001</questionId> <question>Jenkins is primiary used of ...</question> <Answers correct="no">Nightly Builds</Answers> <Answers correct="yes">CI Builds</Answers> <Answers correct="no">Report Generation</Answers> <Answers correct="no">All the above</Answers> </Question> <Question> <questionId>TNHSCS010002</questionId> <question>CI builds are setup to ...</question> <Answers correct="yes">Catch potentail build errors</Answers> <Answers correct="no">Find bugs</Answers> <Answers correct="no">Reduce build time</Answers> <Answers correct="no">None of the above</Answers> </Question> </Questions>

        Notice that a valid XML must have a root tag. I also changed a little the structure...

        Regards, Stefan

Re: WxPerl Next button
by jmlynesjr (Deacon) on Jan 05, 2013 at 14:20 UTC

    After reviewing and running your code, and having read a zillion of theses posts now, I knew that a more learned Monk would suggest using one of the CPAN XML parsers. Thanks stefbz. I have not gotten into XML at all yet.

    I do think that you should be using a dialog(modal) rather than individual controls. I would start with the wxSingleChoiceDialog and use it to get my application logic correct. Build and popup the dialog, extract your answer, destroy the popup, then repeat for all of your questions. Then if you still want a different look and feel you could implement a custom dialog like the wxSingleChoiceDialog, but using radio boxes instead of a list. See CppTrial-pg225.pl for the wxSingleChoiceDialog example and CppTrial-pg245.pl for the PersonalRecordDialog custom dialog example.

    The next more complicated option would be to create a wxWizard. Unfortunately I haven't yet implemented the wxWizard example from the "wxBook" in my github examples.

    See also the wxDemo wxWizard and wxSingleChoiceDialog examples. I run Citrus Perl 5.16 and on my system these can be found at home/CitrusPerl/perl/vendor/bin/wxperl_demo.pl. Look under the Managed Windows and Dialogs sections.

    Please repost your working application to add to the example base.

    Update1:See if the following code can be integrated with your XML code.

    Update2:Just for completeness a wxWizard example follows.

    James

    There's never enough time to do it right, but always enough time to do it over...

      Hi James/Stefan, Thanks for the valuable input. Since I have to print line-by-line as we select the correct answer (this app is just to verify the correct answers), I chose not to use XML parsers since anytime the actual XML file several additional nodes that I don't need in (both inside and outside the question node). I have made some good progress by destroying and recreating RadioBox when the user selects next button. After testing the code thoroughly, I will post it and you can modify (if required) and add it to the examples. Regards Saran

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1011675]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (6)
As of 2024-04-23 09:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found