2015-07-24 5 views
0

Я пишу небольшое приложение, которое отлично работает на linux, но у меня есть проблемы с окнами. Вот пример кода:wxPython: проблемы с окнами с использованием нескольких sizers, но хорошо работает на linux

import wx 
#####################################################################  
class Main(wx.Frame): 
    def __init__(self): 

     wx.Frame.__init__(self, None, title="StackOverflow", pos=wx.DefaultPosition, size=(800,600)) 
     self.SetMinSize(self.GetSize()) 

     p = wx.Panel(self) 
     nb = wx.Notebook(p) 

     page1 = AddToCollection(nb) 
     page2 = CollectionStatistics(nb) 
     nb.AddPage(page1, "Page 1") 
     nb.AddPage(page2, "Page 2") 

     # finally, put the notebook in a sizer for the panel to manage 
     # the layout 
     sizer = wx.BoxSizer() 
     sizer.Add(nb, 1, wx.EXPAND) 
     p.SetSizer(sizer) 
######################################################################### 
class CollectionStatistics(wx.Panel): 
    def __init__(self, parent):   

     wx.Panel.__init__(self, parent) 
######################################################################### 
class AddToCollection(wx.Panel): 
    def __init__(self, parent):   

     wx.Panel.__init__(self, parent) 

     self.v1_qty_list = [str(x) for x in range(9)] 
     self.v2_qty_list = [str(x) for x in range(9)] 

     self.sizername = wx.GridBagSizer(5, 5) 
     self.sizername.AddGrowableCol(0,0) 

     self.name_txt = wx.StaticText(self, label="Enter Name :") 
     self.sizername.Add(self.name_txt,(2,0),(1,1),wx.EXPAND) 

     self.name = wx.TextCtrl(self,style=wx.TE_PROCESS_ENTER,value=u"") 
     self.sizername.Add(self.name,(3,0),(1,1),wx.EXPAND) 
     self.Bind(wx.EVT_TEXT_ENTER, self.OnPressEnter, self.name) 

     self.SetSizerAndFit(self.sizername) 
     self.SetSizeHints(-1,self.GetSize().y,-1,self.GetSize().y) 
########################################################################## 
    def OnPressEnter(self,event): 
     self.selected_name = self.name.GetValue() 
     self.AddToCol() 
########################################################################## 
    def AddToCol(self): 

     self.sizerAdd = wx.GridBagSizer(5, 5) 
     self.sizerAdd.AddGrowableCol(0, 0) 

     self.name.Enable(False) 

     ### Expansion 
     self.expansion = wx.Choice(self, -1, choices=['test 1', 'test 2']) 
     self.expansion.SetSelection(0) 
     self.sizerAdd.Add(self.expansion,(5,0),(1,6),wx.EXPAND) 

     ### Quantities txt 
     self.v1_txt = wx.StaticText(self, label="V1 Quantity :") 
     self.sizerAdd.Add(self.v1_txt,(7,0),(1,1),wx.EXPAND) 

     self.v2_txt = wx.StaticText(self, label="V2 Quantity :") 
     self.sizerAdd.Add(self.v2_txt,(8,0),(1,1),wx.EXPAND) 

     ### Quantities choices 
     self.v1_qty = wx.Choice(self, -1, choices=self.v1_qty_list) 
     self.v1_qty.SetSelection(0) 
     self.sizerAdd.Add(self.v1_qty,(7,5),(1,1),wx.EXPAND) 

     self.v2_qty = wx.Choice(self, -1, choices=self.v1_qty_list) 
     self.v2_qty.SetSelection(0) 
     self.sizerAdd.Add(self.v2_qty,(8,5),(1,1),wx.EXPAND) 

     ### Ok Button   
     self.Add_btn = wx.Button(self, -1, "Add") 
     self.Add_btn.Bind(wx.EVT_BUTTON, self.OnAdd) 
     self.sizerAdd.Add(self.Add_btn,(9,5),(1,1),wx.EXPAND)   

     ### Reset Button   
     self.Reset_btn = wx.Button(self, -1, "Reset") 
     self.Reset_btn.Bind(wx.EVT_BUTTON, self.OnResetPanel) 
     self.sizerAdd.Add(self.Reset_btn,(9,4),(1,1),wx.EXPAND)    

     self.SetSizerAndFit(self.sizerAdd) 
     self.SetSizeHints(-1,self.GetSize().y,-1,self.GetSize().y)  
###################################################################### 
    def OnResetPanel(self,event): 
     ### Kill all children 
     self.expansion.Destroy() 
     self.v1_txt.Destroy() 
     self.v1_qty.Destroy() 
     self.v2_txt.Destroy() 
     self.v2_qty.Destroy() 
     self.Add_btn.Destroy() 
     self.Reset_btn.Destroy() 
     ### Reinitialise sizer 
     self.name.Enable(True) 
     self.name.SetValue("") 
###################################################################### 
    def OnAdd(self,event): 
     print 'Add' 
     self.OnResetPanel(self) 
###################################################################### 
###################################################################### 
if __name__ == "__main__": 
    app = wx.App() 
    Main().Show() 
    app.MainLoop() 

В принципе, у меня есть TextCtrl в первом классификаторе, который ждет запись. Когда пользователь нажимает enter, во втором sizer появляется несколько объектов.

Проблема с окнами, по-видимому, исходит от использования двух gridbagsizers (sizername и sizerAdd). После нажатия ввода (ожидание события в __init__) объекты, определенные в пределах sizerAdd, не отображаются. Когда я расширяю окно, где работает скрипт, эти объекты появляются волшебным образом!

Любая идея?

EDIT: Код теперь работоспособной

+0

Можете ли вы создать небольшой рабочий пример? –

ответ

1

Я думаю, что проблема в вашем коде эти две строки в конце вашего AddToCol метода:

 self.SetSizerAndFit(self.sizerAdd) 
     self.SetSizeHints(-1,self.GetSize().y,-1,self.GetSize().y)  

На данный момент, вы изменение размера блока AddToCollection от self.sizername до self.sizerAdd. Однако метка Enter Name: и текстовое поле находятся в пределах self.sizername sizer. Однако этот sizer не является sizer для любого окна, и не был добавлен ни к одному другому sizer.

Как правило, в wxPython каждый sizer должен быть установлен как sizer для окна или добавлен в другой sizer. Этот другой sizer затем будет сигаром для окна или будет содержаться в другом sizer и так далее. В вашем случае ваш self.sizername sizer не будет ни тем, ни другим, и в этой ситуации я ожидал бы непредсказуемого поведения. Если ваш код работает на Linux, я бы сказал, что это происходит случайно.

Я могу думать о нескольких вещах, которые вы могли бы сделать здесь:

  1. Добавить self.sizerAdd как ребенок self.sizername. Это может быть сделано путем замены двух линий выше

     self.sizername.Add(self.sizerAdd,(4,0),(1,1),wx.EXPAND) 
         self.sizername.Layout() 
    
  2. В AddToCol добавить виджеты непосредственно к self.sizername классификаторе вместо добавления их в self.sizerAdd.

  3. Создание wx.BoxSizer() с вертикальной ориентацией, установить, что быть Сайзером для AddToCollection панели, и добавьте self.sizername и self.sizerAdd классификаторов к вашим BoxSizer.

Во всех трех случаях, после создания новых виджетов вам нужно будет вызвать метод Layout() на классификаторе верхнего уровня, будь то либо self.sizername или верхний уровень BoxSizer. Фрагмент кода в опции 1 включает эту строку уже.

Кроме того, вам может потребоваться изменить ваш метод OnResetPanel().Если вы выбрали варианты 1 или 3, вам нужно будет удалить self.sizerAdd sizer от любого из sizer, к которому вы добавили его. Например, в варианте 1, можно добавить линии

 self.sizername.Remove(self.sizerAdd) 

Другой подход был бы для AddToCol метода для создания всех виджетов в пределах панели и добавить, что на главной панели в конце. Затем вашему методу AddToCol необходимо создать дочернюю панель, добавьте дополнительные элементы управления в качестве дочерних элементов этой панели вместо основной панели (self), установите для параметра sizer дочерней панели значение self.sizerAdd и, наконец, добавьте эту панель в симулятор self.sizername.

def AddToCol(self): 

     self.sizerAdd = wx.GridBagSizer(5, 5) 
     self.sizerAdd.AddGrowableCol(0, 0) 

     self.name.Enable(False) 

     self.child_panel = wx.Panel(self) 

     ### Expansion 
     self.expansion = wx.Choice(self.child_panel, -1, choices=['test 1', 'test 2']) 
     self.expansion.SetSelection(0) 
     self.sizerAdd.Add(self.expansion,(5,0),(1,6),wx.EXPAND) 

     # Create other widgets as before but with the parent set to self.child_panel 
     # instead of self. 

     self.child_panel.SetSizer(self.sizerAdd) 
     self.sizername.Add(self.child_panel,(4,0),(1,1),wx.EXPAND) 
     self.sizername.Layout() 

Вы тогда также необходимо будет заменить строку

 self.sizername.Remove(self.sizerAdd) 

в OnResetPanel() с двумя линиями:

 self.sizername.Remove(self.child_panel) 
     self.child_panel.Destroy() 

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

+0

Я пробовал быстро вариант 1, и он работает! Спасибо ... Но у меня все еще есть странное поведение в окнах: при выполнении скрипта на панели появляется черная область. Кажется, эта апара соответствует idx (0,0) «GridBagSizer». –

+0

@IpseLium: я не мог воспроизвести черную область, о которой вы упоминаете, но я видел, как виджеты появляются в верхнем углу, прежде чем переходить туда, где они должны быть. Я придумал другой подход, который избавится от этого, и отредактировал мой ответ, чтобы включить его. Это может также решить вашу проблему. Попробуйте и дайте мне знать. –

+0

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

Смежные вопросы