【问题标题】:Wxwidgets / Wx Perl grid sizing issuesWxwidgets / Wx Perl 网格大小问题
【发布时间】:2017-02-21 14:18:10
【问题描述】:

好的。我已经坚持了好几天了,我在这里束手无策。我绝不是 Perl 专家。

我正在使用 WxPerl 编写一个 GUI 应用程序。为了减少噪音,我重新创建了我遇到问题的应用程序的一部分。我在 FormBuilder 中设计了布局,然后使用了生成的 XRC 文件。 XRC 数据包含在下面,将其保存在名为 noname.xrc 的文件中。

简而言之,GUI 有两个网格(左和右),中间有两个按钮。为了进行测试,在主框架的顶部有一个“添加行”按钮,它在左侧网格中添加了一行。我写了一个 EVT_SIZE 函数来调整左侧网格的最后一列以填充剩余空间,然后以相同的方式修改右侧的网格以保持它们的相等比例。

问题:

1) 点击添加按钮 20 次,然后调整主框架窗口的大小。注意网格是如何突然扩展并吞噬整个框架底部的。再点击几次添加按钮,它会继续吃掉底部......我似乎无法调整高度以防止它吃掉底部。也许我缺少一个明显的表单设置?即使从 wxGridBagSizer 中删除 growablecols 标志也不能阻止这种情况的发生。

2) 一个恼人的视觉问题,可能与比例尺码有关。基本上,网格 (5x2) 的每一侧都有边框填充,即 10。所以我在设置之前从宽度中减去了 11,但理想情况下应该是 10。但是,如果设置为 10,则在调整大小时发生最后一列永远增长......

3) 如果你点击主框架右上角的“最大化”按钮,然后再次点击它(它被称为“恢复向下”),将它恢复到以前的大小,你会看到右网格永远不会明显调整,因为左网格没有改变大小,永远不会触发 EVT_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, \&on_size ); # adjust grid when size changes
    #EVT_SIZE( $grid_right, \&on_size ); # adjust grid when size changes

    my $on_size = \&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 = \&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 args\n";
    #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 = \&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 sub\n";

    # 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_cols\n";
    print "initial width: $width\n";

    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_0\n";

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

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

    print "width after iterating over each column: $width\n";

    # 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_width\n";
        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_diff\n";

        $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 == 2\n";
            print "reset\n";
            print "what is row: $row\n";
            $col = 0;
        } else {
            $row = $self->{ grid_left }->GetNumberRows() - 1;
        }
        print "value: $value\n";

        $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>&gt;</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>&lt;</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

【问题讨论】:

    标签: c++ perl wxwidgets


    【解决方案1】:

    这里的代码太多,无法仔细阅读,但我立即觉得可疑的一件事是,您没有在 on_size 处理程序中的事件上调用 $event-&gt;Skip()EVT_SIZE 处理程序应该几乎总是调用 Skip() 以允许对 size 事件进行默认处理,因此虽然它可能无法解释您的所有问题,但如果它至少没有解释一些问题,我会感到惊讶其中。

    【讨论】:

    • 感谢VZ的回复。我可能会重新审视这个并尝试一下你的建议。我不得不继续前进并通过锁定表单来解决大小问题以防止调整大小,然后在播放时考虑垂直滚动条。
    猜你喜欢
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 2016-05-05
    • 1970-01-01
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多