Панель прокрутки wxpython не обновляет полосы прокрутки - PullRequest
4 голосов
/ 06 мая 2011

Я использую winxp и wxpython (wxpython 3.1, python 2.6) для создания программы с графическим интерфейсом, которая будет копировать текст из TextCtrl в ScrollablePanel, который содержит StaticText.Это все работает нормально, однако, прокручиваемая часть работает не совсем правильно.Кажется, что он не будет обновляться в режиме реального времени.Когда я максимизирую окно и снова максимизирую его, полоса прокрутки обновляется.Однако, если я снова начну вводить TextCtrl (тем самым добавляя текст в StaticText внутри ScrollablePanel, используя событие), полоса прокрутки на панели не обновится, пока я снова не сверну и так далее.

Итак, вопрос в том, как я могу обновить ScrolledPanel в режиме реального времени?У меня есть настройка события, ожидающая изменения текста в TextCtrl, и я думаю, что обновление должно быть выполнено.Я пробовал Update, Refresh и Layout, но, похоже, они мало что сделали.Более важный вопрос: что минимизирует окно и максимизирует его снова, что Update, Refresh и Layout не делают?Спасибо за помощь в этом.Извините, я не могу опубликовать код, конфиденциально.Буду признателен за любую помощь, которую вы мне можете оказать.Обычно я могу самостоятельно найти проблемы, выполнив поиск, но я просто не нашел никакой документации об этом.Это впервые для меня, но я получаю большую помощь от ваших ответов.Еще раз спасибо!:)

Добавлено:

import wx
import wx.lib.inspection
from wx.lib.scrolledpanel import ScrolledPanel

class MyFrame( wx.Frame ):

    # TODO: add all class variables here for convention
    tin         = None

    hsizer      = None

    def __init__( self, parent, ID, title ):
        wx.Frame.__init__( self, parent, ID, title,
                     wx.DefaultPosition, wx.Size( 200, 150 ) )

        self.InitWidgets()
        self.InitBindings()
        self.InitFinish()


    def InitWidgets( self ):
        self.hsizer = wx.BoxSizer( wx.HORIZONTAL )

        # Add the TextCtrl
        vsizer = wx.BoxSizer( wx.VERTICAL )
        self.tin = wx.TextCtrl( self, style=wx.TE_MULTILINE )
        vsizer.Add( self.tin, 1, wx.EXPAND  )
        self.hsizer.Add( vsizer, 3, wx.TOP|wx.LEFT|wx.BOTTOM|wx.EXPAND, border=20 )

        # Add ScrolledPanel widget
        self.hsizer.Add( wx.Size( 200, -1 ), 1 )
        vsizer2 = wx.BoxSizer( wx.VERTICAL )
        self.test_panel = ScrolledPanel( self )
        self.test_panel.SetupScrolling()

        # Setup static text ( label ) tvs is the 
        # vertical sizer inside the panel
        self.tvs = wx.BoxSizer( wx.VERTICAL )
        self.tin2 = wx.StaticText( self.test_panel )
        self.tvs.Add( self.tin2, 0, wx.EXPAND )
        vsizer2.Add( self.test_panel, 1, wx.EXPAND  )
        self.hsizer.Add( vsizer2, 3, wx.TOP|wx.LEFT|wx.BOTTOM|wx.EXPAND, border=20 )

        # Add Spacer
        self.hsizer.Add( wx.Size( 500, -1 ), 1 ) 

    def InitBindings( self ):
        self.tin.Bind( wx.EVT_TEXT, self.TextChange ) 

    def InitFinish( self ):

        # Setup sizers and frame
        self.SetAutoLayout( True )
        self.test_panel.SetAutoLayout( True )
        self.test_panel.SetSizer( self.tvs )
        self.SetSizer( self.hsizer )
        self.Layout()
        self.Update()
        self.Maximize()

    def TextChange( self, event ):

        #self.CopyValues()
        self.tin2.Label = self.tin.GetValue()
        self.Layout()
        self.Update()
        self.test_panel.Refresh()
        self.test_panel.Update()
        print self.tin.GetValue().split( "\n" )


class MyApp( wx.App ):

    fr = None

    def OnInit( self ):
        self.fr = MyFrame( None, -1, "TitleX" )
        self.fr.Show( True )
        self.SetTopWindow( self.fr )
        return True

app = MyApp( 0 )
app.MainLoop()

def main():

    win = 1
if ( __name__ == "__main__" ):
    main()    

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

1 Ответ

7 голосов
/ 06 мая 2011

Было бы лучше, если вы опубликуете что-то, что может быть запущено сразу после копирования и вставки.

В любом случае кажется, что вы упустили следующие вещи, которые являются обязательными для работы прокручиваемой панели:

  1. Прокручиваемая панель должна иметь размер. Это можно сделать методом self.test_panel.SetSizer(self.a_sizer). Все остальные элементы управления внутри панели должны быть прикреплены к данному классификатору.

  2. Вы должны вызвать метод SetupScrolling () на своей панели, например, self.test_panel.SetupScrolling()

  3. Вы должны включить автоматическое расположение панели, например, self.test_panel.SetAutoLayout(1)

P.S. Вы когда-нибудь видели примеры кода wxPython? Я спрашиваю, так как почти у всех есть замечательный метод, например __do_layout или что-то в этом роде. Этот подход поможет сделать ваш код более читабельным.

EDIT:

Вам необходимо добавить self.test_panel.FitInside () в метод TextChange, чтобы заставить панель пересчитывать размеры дочерних элементов управления и обновлять свой собственный виртуальный размер.

Вот полное решение:

import wx
from wx.lib.scrolledpanel import ScrolledPanel

class MyFrame( wx.Frame ):
    def __init__( self, parent, ID, title ):
        wx.Frame.__init__( self, parent, ID, title,
                         wx.DefaultPosition, wx.Size( 600, 400 ) )
        #Controls
        self.tin = wx.TextCtrl( self, 
                                size = wx.Size( 600, 400 ),
                                style=wx.TE_MULTILINE )        
        self.test_panel = ScrolledPanel( self, 
                                         size = wx.Size( 600, 400 ) )
        self.test_panel.SetupScrolling()
        self.tin2 = wx.StaticText( self.test_panel )

        #Layout
        #-- Scrolled Window
        self.panel_sizer = wx.BoxSizer( wx.HORIZONTAL )
        self.panel_sizer.Add( self.tin2, 0, wx.EXPAND )
        self.test_panel.SetSizer( self.panel_sizer )
        self.panel_sizer.Fit(self.test_panel)
        #-- Main Frame
        self.inner_sizer = wx.BoxSizer( wx.HORIZONTAL )        
        self.inner_sizer.Add( self.tin, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 50  )
        self.inner_sizer.Add( self.test_panel, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 50  )

        self.sizer = wx.BoxSizer( wx.VERTICAL )
        self.sizer.Add(self.inner_sizer, 1, wx.ALL | wx.EXPAND, 20)        
        self.SetSizer(self.sizer)
        self.sizer.Fit(self)
        self.sizer.Layout()

        self.test_panel.SetAutoLayout(1)

        #Bind Events
        self.tin.Bind( wx.EVT_TEXT, self.TextChange )

    def TextChange( self, event ):
        self.tin2.SetLabel(self.tin.GetValue())
        self.test_panel.FitInside()


class MyApp( wx.App ):
    def OnInit( self ):
        self.fr = MyFrame( None, -1, "TitleX" )
        self.fr.Show( True )
        self.SetTopWindow( self.fr )
        return True

app = MyApp( 0 )
app.MainLoop()

def main():

    win = 1

if ( __name__ == "__main__" ):
    main()    
...