Проблемы с размерами сетки Wxwidgets / Wx Perl

#c #perl #wxwidgets

#c #perl #wxwidgets

Вопрос:

ОК. Я застрял на этом уже несколько дней, и здесь я в тупике. Я ни в коем случае не эксперт в Perl.

Я пишу приложение с графическим интерфейсом, используя wxPerl. Чтобы уменьшить шум, я воссоздал часть приложения, в которой у меня возникли проблемы. Я разработал макет в FormBuilder, а затем использовал полученный файл XRC. Данные XRC включены ниже, сохраните их в файле с именем noname.xrc.

В двух словах, графический интерфейс имеет две сетки (левую и правую) с двумя кнопками посередине. Для тестирования в верхней части основного фрейма есть кнопка «добавить строку», которая добавляет строку в левую сетку. Я написал функцию EVT_SIZE для настройки последнего столбца сетки слева, чтобы заполнить оставшееся пространство, которое затем изменяет сетку справа таким же образом, чтобы сохранить их равные пропорции.

Проблемы:

1) Нажмите кнопку Добавить 20 раз, затем отрегулируйте размер окна основного фрейма. Обратите внимание, как сетка внезапно расширяется и поглощает всю нижнюю часть фрейма. Нажмите кнопку добавить еще несколько раз, и она продолжит съедать дно… Кажется, я не могу настроить высоту, чтобы она не съедала нижнюю часть. Может быть, мне не хватает очевидной настройки формы? Даже удаление флага growablecols из wxGridBagSizer не останавливает это.

2) Досадная визуальная проблема, которая, вероятно, связана с пропорциональным размером. В принципе, на каждой стороне сетки есть отступы от границ (5×2), что равно 10. Итак, я вычел 11 из ширины до ее установки, но в идеале она должна быть 10. Однако, если для него установлено значение 10, при изменении размера последний столбец продолжает расти вечно…

3) Если вы нажмете кнопку «Развернуть» в правом верхнем углу основного фрейма, а затем снова нажмете ее (тогда она называется «Восстановить вниз»), чтобы вернуть ее к предыдущему размеру, вы увидите, что правая сетка, очевидно, никогда не корректируется, поскольку левая сетка не изменилась.не изменен размер, который никогда не запускает событие EV_SIZE… Я провел мозговой штурм, как это исправить, может быть, событие on size может проверить положение правой сетки и определить, выходит ли она за пределы ширины основного фрейма? Есть ли более простой способ получить правильный размер?

В идеале я хотел бы установить минимальные размеры для определенных столбцов сетки, но чтобы все столбцы увеличивались по мере изменения размера главного окна. Но на данный момент это, вероятно, несбыточная мечта.

 #!/usr/bin/perl

package wxToplevelFrame;
 use strict;
 use warnings;
 use Wx qw(:everything);
 use Wx::Grid;
 use Wx::XRC;
 use base 'Wx::Frame';
 use Data::Dumper;
 use diagnostics;

# import event registration function
use Wx::Event qw(:everything);

use base qw(Wx::Panel Class::Accessor::Fast);
__PACKAGE__->mk_ro_accessors( qw(xrc) );

$| = 1;

### GUI CODE BEGINS ###

# create specialized constructor for new subclass
sub new {
    my $class = shift;
    my $self = $class->SUPER::new();

    $self->initialize();    
    return $self;
}


sub initialize {
    my ($self) = @_;

    my $xrc_path = 'noname.xrc';

    Wx::InitAllImageHandlers();

    $self->{ xrc } = Wx::XmlResource->new();
    $self->xrc->InitAllHandlers();
    $self->xrc->Load($xrc_path);
    $self->xrc->LoadFrame($self, undef, 'MyFrame1',);

    # main frame close
    EVT_CLOSE( $self, 
        sub {
            my ($self) = @_;
            $self->Destroy();
        }
    );


    # LEFT GRID
    my $grid_left = $self->{ grid_left } = $self->FindWindow('m_grid4');
    $grid_left->CreateGrid(0, 3);

    $grid_left->SetColLabelSize(25); # label height
    $grid_left->SetRowLabelSize(25); # row width (far left, the numbers column basically)

    $grid_left->SetColLabelValue(0, 'col_1');
    $grid_left->SetColLabelValue(1, 'col_2');
    $grid_left->SetColLabelValue(2, 'col_3');

    $grid_left->EnableDragColSize(0);
    $grid_left->EnableDragRowSize(0);
    $grid_left->EnableEditing(0);

    $grid_left->SetDefaultRowSize(20);

    $grid_left->SetColSize( 0, 190 ); # col 1
    $grid_left->SetColSize( 1, 50 );  # col 2
    $grid_left->SetColSize( 2, 179 ); # col 3


    # RIGHT GRID
    my $grid_right = $self->{ grid_right } = $self->FindWindow('m_grid5');

    $grid_right->CreateGrid(0, 3);

    $grid_right->SetColLabelSize(25); # label height
    $grid_right->SetRowLabelSize(25); # row width (far left, the numbers column basically)

    $grid_right->SetColLabelValue(0, 'col_');
    $grid_right->SetColLabelValue(1, 'col_2');
    $grid_right->SetColLabelValue(2, 'col_3');

    $grid_right->EnableDragColSize(0);
    $grid_right->EnableDragRowSize(0);
    $grid_right->EnableEditing(0);

    $grid_right->SetDefaultRowSize(20);

    $grid_right->SetColSize( 0, 190 ); # col 1
    $grid_right->SetColSize( 1, 50 );  # col 2
    $grid_right->SetColSize( 2, 179 ); # col 3

    #EVT_SIZE( $grid_left, amp;on_size ); # adjust grid when size changes
    #EVT_SIZE( $grid_right, amp;on_size ); # adjust grid when size changes

    my $on_size = amp;on_size;
    EVT_SIZE($grid_left, callback($on_size, $self, $grid_left) );


    my $button = $self->{ button } = $self->FindWindow('m_button3');

    EVT_BUTTON(
        $button,
        $button->GetId(),
        callback(my $button_sub = amp;add_row, $self, $button),
    );

    my $gui_actions_text_ctrl = $self->FindWindow('m_textCtrl1');
    my $gui_log = Wx::LogTextCtrl->new( $gui_actions_text_ctrl );
    $self->{ gui_log_text_ctrl } = Wx::Log::SetActiveTarget( $gui_log );

    $self->SetStatusBarPane(-1);
    return;
}

sub callback { 
    my $coderef = shift; 
    my @args = @_;

    #print "what is argsn";
    #print Dumper @args;

    sub { $coderef->(@args) } 

    # callback function.  when we want to pass addition args to a method call, such as an event (EVT_*), we can use this
    # example:
    # my $on_size_test = amp;on_size_test;
    # EVT_SIZE($grid_left, callback($on_size, $grid_left, $self) );
} 

sub on_close {
    my ($self) = @_;
    $self->Destroy();
}

sub on_size {
    my ($self, $grid) = @_;
    print "in on_size subn";

    # get the number of columns and the initial width which includes the far left number column (gutter column, with row indicators 1, 2, 3 ...)
    my $num_cols   = $grid->GetNumberCols();
    my $width      = $grid->GetRowLabelSize();
    my $gutter_col = $width;

    print "num_cols: $num_colsn";
    print "initial width: $widthn";

    my $col_0;
    my $col_1;
    my $col_2;

    # iterate over each column, get size and add it to our width
    for (my $col = 0; $col < $num_cols; $col  ) {

        # conditionals of no importance currently, but used during testing
        if ($col == 0) {
            $col_0 = $grid->GetColSize($col);
            print "col: $col, width col_0: $col_0n";

        } elsif ($col == 1) {
            $col_1 = $grid->GetColSize($col);
            print "col: $col, width col_1: $col_1n";

        } elsif ($col == 2) {
            $col_2 = $grid->GetColSize($col);
            print "col: $col, width col_2: $col_2n";
        }
        $width  = $grid->GetColSize($col);
    }

    print "width after iterating over each column: $widthn";

    # get sizer that grid is contained in
    # get width of sizer and subtract it from the total width
    # the difference will be the size we set for our last column
    if ($num_cols > 0) {

        my $static_box_sizer = $grid->GetContainingSizer();
        my $sizer            = $static_box_sizer->GetSize();
        my $sizer_width      = $sizer->GetWidth();

        print "sizer_width: $sizer_widthn";
        print "we are setting width for the last column.  sizer_width: $sizer_width minus the total width: $width (gutter_col: $gutter_col, col_0, col_1, col_2)n";

        my $width_diff = $sizer_width - $width   $col_2 - 11;   # ideally this should be 10 for padding (5x2) on each side of sizer
                                                                # but setting it at 10 causes the col to keep expanding...

        print "width_diff result of above calc: $width_diffn";

        $grid->SetColSize($num_cols - 1, $width_diff); # last column

        # adjust grid right to reflect same proportions
        $self->{ grid_right }->SetColSize($num_cols - 1, $width_diff); # last column        
    }

    return;
}

sub add_row {
    my ($self, $button) = @_;

    $self->{ grid_left }->AppendRows(1);

    my $col = 0;
    foreach my $value ('testing', 100, 'Sat Aug 20 20:52:20 2016') {
        my $row;    
        if ($col == 3) {
            $self->{ grid_left }->AppendRows(1);
            $row = $self->{ grid_left }->GetNumberRows() - 1; # minus one from total rows
            print "col == 2n";
            print "resetn";
            print "what is row: $rown";
            $col = 0;
        } else {
            $row = $self->{ grid_left }->GetNumberRows() - 1;
        }
        print "value: $valuen";

        $self->{ grid_left }->SetCellValue(
            $row,
            $col,
            $value,
        );

        if ($col == 1) {
            $self->{ grid_left }->SetCellAlignment(
                $row,
                $col,
                wxALIGN_RIGHT,
                wxALIGN_CENTRE,
            );

        } elsif ($col == 2) {
            $self->{ grid_left }->SetCellAlignment(
                $row,
                $col,
                wxALIGN_CENTRE,
                wxALIGN_CENTRE,
            );
        }
        $col  ;

    }
}
### GUI CODE ENDS ###

# END: wxToplevelFrame package


# create an app object
package MyApp;
 use strict;
 use warnings;
 use base 'Wx::App';

# OnInit is called automatically when an app object is first constructed
sub OnInit {
    my $self = shift;
    my $toplevel_frame = wxToplevelFrame->new();
    $self->SetTopWindow($toplevel_frame);   
    $toplevel_frame->Show(1);
}
# END: MyApp package


package main;
 use strict;
 use warnings;
 use Data::Dumper;

$| = 1;

my $app = MyApp->new(); # instantiate our app first
$app->MainLoop();

exit;
  

Файл XRC: noname.xrc

 <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
    <object class="wxFrame" name="MyFrame1">
        <style>wxCAPTION|wxCLOSE_BOX|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU|wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL</style>
        <size>998,700</size>
        <title>Grid Issues</title>
        <centered>1</centered>
        <aui_managed>0</aui_managed>
        <object class="wxPanel" name="m_panel6">
            <style>wxTAB_TRAVERSAL</style>
            <object class="wxBoxSizer">
                <orient>wxVERTICAL</orient>
                <object class="sizeritem">
                    <option>1</option>
                    <flag>wxALL|wxEXPAND</flag>
                    <border>5</border>
                    <object class="wxFlexGridSizer">
                        <rows>0</rows>
                        <cols>6</cols>
                        <vgap>0</vgap>
                        <hgap>0</hgap>
                        <growablecols></growablecols>
                        <growablerows></growablerows>
                        <object class="sizeritem">
                            <option>0</option>
                            <flag>wxALL</flag>
                            <border>5</border>
                            <object class="wxButton" name="m_button3">
                                <label>add row</label>
                                <default>0</default>
                            </object>
                        </object>
                    </object>
                </object>
                <object class="sizeritem">
                    <option>3</option>
                    <flag>wxEXPAND|wxLEFT|wxRIGHT</flag>
                    <border>5</border>
                    <object class="wxGridBagSizer">
                        <vgap>0</vgap>
                        <hgap>0</hgap>
                        <growablecols>0,2</growablecols>
                        <growablerows>0</growablerows>
                        <object class="sizeritem">
                            <cellpos>0,0</cellpos>
                            <cellspan>1,1</cellspan>
                            <flag>wxALL|wxEXPAND</flag>
                            <border>5</border>
                            <object class="wxStaticBoxSizer">
                                <orient>wxHORIZONTAL</orient>
                                <label>left</label>
                                <object class="sizeritem">
                                    <option>1</option>
                                    <flag>wxALL|wxEXPAND</flag>
                                    <border>5</border>
                                    <object class="wxGrid" name="m_grid4" />
                                </object>
                            </object>
                        </object>
                        <object class="sizeritem">
                            <cellpos>0,1</cellpos>
                            <cellspan>1,1</cellspan>
                            <flag>wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL</flag>
                            <border>5</border>
                            <object class="wxBoxSizer">
                                <orient>wxVERTICAL</orient>
                                <object class="sizeritem">
                                    <option>0</option>
                                    <flag>wxALL</flag>
                                    <border>5</border>
                                    <object class="wxButton" name="m_button4">
                                        <style>wxBU_EXACTFIT</style>
                                        <label>amp;></label>
                                        <default>0</default>
                                    </object>
                                </object>
                                <object class="sizeritem">
                                    <option>0</option>
                                    <flag>wxALL</flag>
                                    <border>5</border>
                                    <object class="wxButton" name="m_button5">
                                        <style>wxBU_EXACTFIT</style>
                                        <label>amp;<</label>
                                        <default>0</default>
                                    </object>
                                </object>
                            </object>
                        </object>
                        <object class="sizeritem">
                            <cellpos>0,2</cellpos>
                            <cellspan>1,1</cellspan>
                            <flag>wxALL|wxEXPAND</flag>
                            <border>5</border>
                            <object class="wxStaticBoxSizer">
                                <orient>wxHORIZONTAL</orient>
                                <label>right</label>
                                <object class="sizeritem">
                                    <option>1</option>
                                    <flag>wxALL|wxEXPAND</flag>
                                    <border>5</border>
                                    <object class="wxGrid" name="m_grid5" />
                                </object>
                            </object>
                        </object>
                    </object>
                </object>
                <object class="sizeritem">
                    <option>2</option>
                    <flag>wxEXPAND | wxALL</flag>
                    <border>5</border>
                    <object class="wxNotebook" name="m_notebook2">
                        <object class="notebookpage">
                            <label>a page</label>
                            <selected>0</selected>
                            <object class="wxPanel" name="m_panel2">
                                <style>wxTAB_TRAVERSAL</style>
                                <object class="wxBoxSizer">
                                    <orient>wxHORIZONTAL</orient>
                                    <object class="sizeritem">
                                        <option>1</option>
                                        <flag>wxALL|wxEXPAND</flag>
                                        <border>5</border>
                                        <object class="wxTextCtrl" name="m_textCtrl1">
                                            <value></value>
                                        </object>
                                    </object>
                                </object>
                            </object>
                        </object>
                    </object>
                </object>
            </object>
        </object>
        <object class="wxStatusBar" name="m_statusBar1">
            <style>wxST_SIZEGRIP</style>
            <fields>2</fields>
        </object>
    </object>
</resource>
  

Любая помощь с благодарностью,

Спасибо,

-Jdun

Ответ №1:

Здесь слишком много кода, чтобы внимательно его читать, но одна вещь, которая сразу кажется мне подозрительной, заключается в том, что вы не вызываете $event->Skip() событие в своем on_size обработчике. EVT_SIZE Обработчик должен почти всегда вызывать Skip() , чтобы разрешить обработку события size по умолчанию, поэтому, хотя это может и не объяснить все ваши проблемы, я был бы удивлен, если бы это не объясняло хотя бы некоторые из них.

Комментарии:

1. Спасибо за ответ VZ. Я могу вернуться к этому и попробовать ваше предложение. Мне пришлось двигаться дальше и решить проблему с размерами, заблокировав форму, чтобы предотвратить изменение размера, а затем учитывал вертикальную полосу прокрутки, когда она была в игре.