панель прокрутки wxpython не обновляет полосы прокрутки

#python #wxpython #scrolledwindow

#python #wxpython #scrolledwindow

Вопрос:

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

Итак, вопрос в том, как я могу обновить ScrolledPanel в режиме реального времени? У меня есть настройка события, ожидающая изменения текста в TextCtrl, и я думаю, что именно там потребуется обновление. Я пробовал обновление, Refresh и Layout, но, похоже, они мало что сделали. Более важный вопрос заключается в том, что делает минимизация окна и его повторное максимальное сведение к минимуму, чего не делают обновление, 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. Я думаю, что здесь могут быть соответствующие части вашего кода. Это поможет вам получить лучший ответ. У меня не так много знаний в этой области, но я предполагаю, что это очень специфическая проблема и, вероятно, ошибка в вашей программе, поэтому трудно угадать проблему, не видя, что вы делаете.

2. Спасибо за ваш ответ, добавил то, что мог выше

3. Также забыл упомянуть, что я использую ОС Windows XP

4. Нет проблем! желаю вам удачи в решении этой проблемы! Еще одна вещь, всякий раз, когда вы используете систему комментариев, я рекомендую вам использовать @Isaac или, в данном случае, @Trufa, чтобы пользователь получал уведомления.

5. Клянусь, вы могли бы решить вашу проблему! добро пожаловать в StackOverflow.

Ответ №1:

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

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

  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 или что-то в этом роде. Такой подход поможет сделать ваш код намного более читаемым.

Редактировать:

Вам нужно добавить 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()    
  

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

1. 1. Я установил размер для фрейма, я просто не перечислил код. Я предположил, что это было дано. Я вижу, что это не так. Я добавил это в приведенный выше код. 2. Я попытался вызвать SetupScrolling, но это мало что дало. Я также исходил из предположения, что настройка скорости прокрутки и тому подобное позволит выполнять прокрутку. Разве это не так? В любом случае я изменил ее, чтобы использовать SetupScrolling, и проблема все еще существует 3. У меня есть это см. Новый код P.S. Очевидно, я просмотрел примеры wxpython, иначе у меня не было бы знаний о том, как это работает, я считаю, что вашему замечанию не хватает понимания.

2. @Isaac Проблема вашего кода в том, что вы не «уведомляете» панель о том, что размер ее дочерних элементов управления изменился, однако размеры всех элементов управления пересчитываются автоматически при изменении размера, вот почему все работает при изменении размера окна. Чтобы заставить ваш код работать, просто добавьте self.test_panel. FitInside() для метода TextChanged. Также я произвел некоторую очистку вашего кода. Смотрите обновленный ответ.

3. Спасибо, это работает. Эта подходящая функциональность была внутренней работой, о которой я не знал. Спасибо, что научили меня чему-то новому.

4. Всем, кто также искал ответ — смотрите комментарий Вейдера, а не пространный ответ. Все, что мне было нужно, это команда FitInside(). Мне не нужны были два размера.