Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Wx::Perl: How to change/set font and size of Wx::ListCtrl column headings?

by HelenCr (Monk)
on Mar 26, 2013 at 10:21 UTC ( [id://1025489]=perlquestion: print w/replies, xml ) Need Help??

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

Dear esteemed PerlMonks

Continuing my odyssey into uncharted waters*, I need to be able to change (or set) the font and size of the Wx::ListCtrl column headings.
As you can see in the following program, I've succeeded in changing column heading text; but trying to change the font:

my $f = Wx::Font->new(12, -1, wxNORMAL, wxBOLD, 0, 'times new roman');
$column->SetFont($f);
has no effect (although it doesn't raise an error). Full program:

# Col header.pl - created 26 3 2013 # v 0-1 # taken from: http://wxpython-users.1045709.n5.nabble.com/ListCtrl-Set +ItemTextColor-SetItemFont-td2348263.html (main.py) # ported 23 3 2013 v 0-1 # with the help of: http://wxpython-users.1045709.n5.nabble.com/column +-header-doesn-t-change-td2341548.html use strict; use warnings; use Wx; use 5.014; use autodie; use Carp; use Carp qw {cluck}; use Carp::Always; package MyFrame; use Wx ':everything'; use Wx ':listctrl'; use Wx::Event 'EVT_BUTTON'; use parent -norequire, 'Wx::Frame'; sub new { #1 MyFrame:: my ($class, $parent, $title) = @_; my $self = $class->SUPER::new( $parent, -1, # parent window; ID -1 means any $title, # title [150, 150 ], # position [ 350, 400 ], # size ); my $panel = Wx::Panel->new($self); my $btn_header = Wx::Button->new($panel, -1, 'Header', wxDefau +ltPosition, wxDefaultSize); EVT_BUTTON ($self, $btn_header, sub { $self->{list_control}->M +yFrame::on_header }); $self->{list_control} = Wx::ListCtrl->new($panel, -1, wxDefaultPosition, [ +320,100], wxLC_REPORT); # create a list control $self->{list_control}->InsertColumn(0, 'Col1', wxLIST_FORMAT_LEF +T, 150); $self->{list_control}->InsertColumn(1, 'Col2', wxLIST_FORMAT_LEF +T, 150); $self->{list_control}->InsertStringItem( 0, 'Data 1' ); $self->{list_control}->SetItem( 0, 1, 'Data 3'); $self->{list_control}->InsertStringItem( 1, 'Data 2' ); $self->{list_control}->SetItem( 1, 1, 'Data 4'); my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($self->{list_control}, 0, wxALL, 10); $sizer->Add($btn_header, 0, wxALL, 10); $panel->SetSizer($sizer); $panel->Layout(); return $self; } #1 end sub new MyFrame:: sub on_header { my $this = shift; say 'In on_header'; my $column = $this->GetColumn(1); say '$column->GetText =', $column->GetText; $column->SetMask(wxLIST_MASK_TEXT); $column->SetText('NEW TITLE'); my $f = Wx::Font->new(12, -1, wxNORMAL, wxBOLD, 0, 'times new +roman'); $column->SetFont($f); $this->SetColumn(1, $column); } #1 end sub on_header # end package MyFrame:: package main; my $frame = MyFrame->new(undef, 'Demonstrate listctrl'); $frame->Show(1); my $app = Wx::SimpleApp->new; $app->MainLoop; 1;

In addition, can anyone suggest how to change width and height of the column headings?

Many TIA - Helen
___________________
*e.g. http://www.perlmonks.org/?node_id=1025321

Replies are listed 'Best First'.
Re: Wx::Perl: How to change/set font and size of Wx::ListCtrl column headings? (wxWidgets portability)
by Anonymous Monk on Mar 26, 2013 at 10:42 UTC
Re: Wx::Perl: How to change/set font and size of Wx::ListCtrl column headings?
by jmlynesjr (Deacon) on Mar 26, 2013 at 16:14 UTC

    The wxBook states, under the wxListItem class, "wxListItem is a class you can use to insert an item, set an item's properties, or retreive information from an item"..."Other functions set various additional visual properties: SetAlign, SetBackgroundColour, SetTextColour, and SetFont. These don't require a mask flag be specified. All wxListItem functions have equivalent accessors prefixed by Get for retrieving information about an item."..."An alternative to using wxListItem, you can use set and get properties for an item with wxListCtrl convenience functions such as SetItemText, SetItemImage...and so on"

    That said in the example that followed, a wxListItem was created first that was then used to create the columns. So in print, at least, it seems that this is the way to format the column headings. Try adding colour/font calls to the example below after appropriate translation from C++ :).

    // Insert three columns wxListItem itemCol; itemCol.SetText(wxT("Column 1")); itemCol.SetImage(-1); # itemCol.SetFont(....) etc listCtrlReport->InsertColumn(0, itemCol); listCtrlReport->SetColumnWidth(0, wxLIST_AUTOSIZE); itemCol.SetText(wxT("Column 2")); listCtrlReport->InsertColumn(1, itemCol); listCtrlReport->SetColumnWidth(1, wxLIST_AUTOSIZE); itemCol.SetText(wxT("Column 3")); listCtrlReport->InsertColumn(2, itemCol); listCtrlReport->SetColumnWidth(2, wxLIST_AUTOSIZE);

    James

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

      Pipe dream friend, pipe dream
      #!/usr/bin/perl -- use strict; use warnings; use Wx; my $f = Wx::Frame->new(undef, -1, ""); ## this, otherwise nothing on s +creen, nada my $l = Wx::ListCtrl->new( $f, -1, [-1,-1], [-1,-1], Wx::wxLC_REPORT() ); $l->InsertColumn( $_, "column $_" ) for 0 .. 3; for my $col( 0 .. 2 ){ for( 0 .. 10 ){ if( $col == 0 ){ $l->InsertStringItem( $_, qq{row $_ col $col} ); } $l->SetItemString( $_, $col, qq{row $_ col $col} ) } $l->SetColumnWidth($col, Wx::wxLIST_AUTOSIZE() ); ## autosize aft +er adding all items } for my $row ( 11 .. 20 ){ $l->AddStringItems ( map { "row $row col $_" } 0 .. 3 ) ; } $l->SetColumnWidth($_, Wx::wxLIST_AUTOSIZE() ) for 0 .. 3; for my $col ( 0 .. 3 ){ warn my $column0 = $l->GetColumn( $col ); $column0->SetText( $column0->GetText . " (?red?)" ); $column0->SetBackgroundColour( Wx::wxRED() ); $column0->SetTextColour( Wx::wxRED() ); warn my $column0font = $column0->GetFont; $column0font->SetPointSize( 12 + $column0font->GetPointSize ); $column0font->SetWeight( Wx::wxFONTWEIGHT_BOLD() ); $column0->SetFont( $column0font); warn $column0->GetFont; $l->Refresh; $l->SetColumn( $col, $column0); warn $l->GetColumn( $col ); } $f->Show(1); exit Wx::SimpleApp->new->MainLoop; sub Wx::ListCtrl::GetItemFont { $_[0]->GetItem($_[1])->GetFont } sub Wx::ListCtrl::SetItemFont { $_[0]->GetItem($_[1])->SetFont($_[2]) +} sub Wx::ListCtrl::AddStringItems { #~ warn "@_\n"; my $l = shift; my $ix = $l->GetItemCount; $l->InsertStringItem( $ix, 'placeholder' ); my $col = 0; while(@_){ #~ warn "$ix $col $_[0] ", $l->SetItemString( $ix, $col, shift @_); $col++; } }

        No color or font changes for me when I ran your example.

        James

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

      James: I tried to translate and run your example. As you can see from the program here, it lets you set/change the font of a ListCtrl item, but not the headers (tried a couple of approaches).
      (Unless I'm doing something wrong). (Although, interestingly, (as you can see by pressing the buttons), it does let you change the header text. But no font or color).
      It's a pity, since, if your approach worked, I wouldn't need to start wrestling with Wx::Grid.

      In the meantime, Anonymous Monk has provided another example based on your snippet - it's impressive to see DWIM in action.

      Many thanks - Helen

        Found the following hint in the wxWidgets Wiki

        Using Specific Colours for Each Item

        Trying to set specific item colours for a wxListCtrl doesn't have any effect with wxMSW 2.4.0 standard release. You have to enable it. Indeed, it is not set as default in the downloadable releases so you will have to recompile the library with _WIN32_IE at least defined as 0x300. To do so, just insert the -D_WIN32_IE=0x300 compile flag when making. See the Guides & Tutorials for further details about building wx. Then, just use wxListItem's methods to set the text colour, background colour and font of each item. For example:

        MyListCtrl::AppendColouredItem(const wxString& Label) { wxListItem NewItem; NewItem.SetMask(wxLIST_MASK_TEXT); NewItem.SetId(GetItemCount()); NewItem.SetText(sLabel); NewItem.SetFont(*wxITALIC_FONT); NewItem.SetTextColour(wxColour(*wxRED)); NewItem.SetBackgroundColour(wxColour(235, 235, 235)); InsertItem(NewItem); }

        This piece of code appends a new line (item) to MyListCtrl with the label of sLabel's value, an italic font, a red text colour and a light grey background.

        Important part of this mess:

        NOTE: It seems that these methods still don't work with columns so the tip is to set the global text/background colours and font of MyListCtrl and then, when you append an item, set its colours/font to the proper values.

        Try playing around with my attempt at the above suggestion.

        When you move to a virtual control I think you will have to also start using Wx::ListItemAttr to hold the color/font info for the virtual row items.

        James

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

Re: Wx::Perl: How to change/set font and size of Wx::ListCtrl column headings?
by jmlynesjr (Deacon) on Mar 31, 2013 at 03:29 UTC

    Based on references provided by AM above, attached is a stand-alone example of a customized "Virtual" wxGridTable control. I don't do SQL, so hopefully someone can expand this into a complete example of displaying SQL table results with wxPerl.

    James

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

      James: Thank you for this good work.

      In fact, like I said in an earlier post, I have realized I have to use "The Grid" (cringe) and I've written a little stand-alone program, which is, in many ways, similar to your example.
      Well, there is still something quite strange there: If you look at your example, line 94:

      sub GetValue { my( $grid, $y, $x ) = @_; return "($y, $x)"; }
      It seems that all cells should contain just
      "($y, $x)"
      Then,
      1. Why are the cells in column 1 empty (with alternating checkboxes - where did these come from)? and
      2. Why do we have in column 2:
      $r + $c / 1000;
      instead of
      "($y, $x)"
      (looks as if it came from line 122 in your code):
      sub GetValueAsDouble { # Row # plus (Col #/1000) my( $grid, $r, $c ) = @_; return $r + $c / 1000; }
      It's as if the system is calling GetValueAsDouble instead of GetValue. Why is that? I thought in wxVirtual, the system always calls GetValue?
      (I know that CanGetValueAs (line 108 in your code) is a cell accessor, and GetTypeName (line 100 in your code) sets column 1 type as boolean)

      Or, in other words, where is the renderer defined?
      I've read this wiki: http://wiki.wxperl.nl/Wx::GridTableBase but it doesn't make things much clearer

      Many TIA - Helen

        My pure guess is that sub GetTypeName() and sub CanGetValueAs() in defining column 0 as Bool, column 1 as Double and columns 2 through "last" as string is determining which cell renderer gets called for each column. Modify these subs to fit your column layout. Swap 0(bool) and 1(double) in both subs and see if the columns swap, I bet they will. (Tried this and they did swap!)

        Did you look at wxGridTableBase docs? You will probably have to create sub SetValue(), sub SetValueAsBool(), and sub SetValueAsDouble() subs to get your data into the Grid and possibly others to fit your specific data.

        I am out of ideas until there are specific questions to look into. I think you are close at this point.

        Update1: Swapped versions for completeness:

        sub GetTypeName { my( $grid, $r, $c ) = @_; return $c == 0 ? 'double' : # Col 0 Double $c == 1 ? 'bool' : # Col 1 Boolean 'string'; # All others String } sub CanGetValueAs { my( $grid, $r, $c, $type ) = @_; return $c == 0 ? $type eq 'double' : $c == 1 ? $type eq 'bool' : $type eq 'string'; }

        James

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

Re: Wx::Perl: How to change/set font and size of Wx::ListCtrl column headings?
by jmlynesjr (Deacon) on Apr 06, 2013 at 03:04 UTC

    Helen:

    Yet another idea from Steve Cookson from the mailing list is to use a Virtual ListCtrl with the no header option and then use a one line panel to create his own custom header. See his comments below:

    James

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

Re: Wx::Perl: How to change/set font and size of Wx::ListCtrl column headings?
by jmlynesjr (Deacon) on Mar 28, 2013 at 16:29 UTC

    Looks like Wx::Grid has more display formatting flexibility, however, it seems that getting the data into the grid may take more effort - no built in Virtual mode. Play with the expanded grid example below and see if you can get the look you need. Your color choices may(should) vary. :)

    Update 2: Skip down to the 2nd example.

    Update1:

    This version appends 1000 rows of dummy data. Tried with 10000 rows and it did work but took awhile for the screen to open.

    James

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

        AM, thank you for the correction. Always more to learn.

        Response to my inquiry on the wxPerl mailing list:

        Hi,

        It isn't implemented in wxWidgets - probably because the library attempts to either use the native platform controls or mimic them as closely as possible. If you cannot do it with a native control, you most likely can't do it in wxWidgets. I doubt this is seen as a missing feature so you're unlikely to see it implemented in the future.

        Wx::Grid is the way to go to do what you want.

        By the way, I noticed on Perl Monks some information regarding how Wx::ListCtrl handles a large number of items.

        For that you need to use the wxLC_VIRTUAL|wxREPORT style. See the Wx::Demo where the virtual list control reports 100,000 items.

        For a Wx::Grid control with a large number of items, you should use a custom Wx::GridTable. The example in Wx::Demo reports 100,000 columns by 100,000 rows.

        Hope it helps. Sorry no positive answer on the column formatting.

        Regards

        Mark(Dootson)

        James

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

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2024-03-19 09:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found