When I add another panel, the other disappears

I am a visually impaired coder and I am trying to create a frame with 2 panels (each having a widget). The first panel has some text and the second one has a button. However, only the one with the button will show.This was just a test and my real aim is to have 3panels (two with text and the other with a button) Can someone please assist me?
here is the cod:
import wx

class MyFrame(wx.Frame):

def __init__(self, parent, id, title):

    wx.Frame.__init__(self, parent, id, title,size=(250, 250))

    topPanel = wx.Panel(self)

    panel1 = wx.Panel(topPanel, -1,pos=(0,100),size=(100,100))

    t1 = wx.StaticText(panel1, -1, "Welcome to TQ Reminders")

    panel2 = wx.Panel(topPanel, -1,pos=(0,200))

    button2 = wx.Button(panel2, -1, label="hey girl")

    sizer = wx.BoxSizer(wx.VERTICAL)

    sizer.Add(panel1,0,wx.EXPAND|wx.ALL,border=10)

    sizer.Add(panel2,0,wx.EXPAND|wx.ALL,border=10)

    topPanel.SetSizer(sizer)

class MyApp(wx.App):

 def OnInit(self):

     frame = MyFrame(None, -1, 'frame')

     frame.Show(True)

     return True

app = MyApp(0)

app.MainLoop()

When I run your code on linux it does actually display both the panel with the text and the panel with the button, one above the other. I assume you are running this on a different OS?

There is one issue that could be causing your problem. That is you are passing the positions of panel1 and panel2 in their constructors as well as putting them in a sizer. I don’t think you should be doing both. The sizer should be responsible for the layout of the two panels, so I suggest deleting the pos parameters from the constructors and check if that works for you.

I am using windows 10. Because I am using a screen reader, when I tab to the first panel it just says ‘panel’ but when i tab to the next one with the button it says the text that is on the button. Yet still when I use my keystroke that allows me to read everything that is in a window, it reads the text that should be in the first panel. I have no idea what is going on here. Is there a way to make it more accessible?

Your architecture with the panels is a bit unusual.

You hear ‘panel’ as the panel has the focus.

Static texts will be read when you move the mouse over them or when they seem to be associated to another control.
E.g. if you create a static text followed by a text ctrl or button, the static text will be spoken when the other controls gains the keyboard focus.
A static text itself will not gain the keyboard focus, so you will never hear it when just using the keyboard.

I have create an example with a static text, a text ctrl and a button on the same panel.
The static text and the text ctrl have the same text, with “(static text)” and “(text ctrl)” added, respectively. So you will hear your text twice.

Here’s the code:

import wx

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.SetTitle("frame")

        self.panel_1 = wx.Panel(self, wx.ID_ANY)

        sizer_1 = wx.BoxSizer(wx.VERTICAL)

        label_1 = wx.StaticText(self.panel_1, wx.ID_ANY, "Welcome to TQ Reminders (static text)")
        sizer_1.Add(label_1, 0, wx.ALL, 4)

        self.text_ctrl_1 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "Welcome to TQ Reminders (text ctrl)", style=wx.TE_READONLY)
        sizer_1.Add(self.text_ctrl_1, 0, wx.ALL | wx.EXPAND, 4)

        self.button_1 = wx.Button(self.panel_1, wx.ID_ANY, "hey girl")
        sizer_1.Add(self.button_1, 0, wx.ALL, 4)

        self.panel_1.SetSizer(sizer_1)

        self.Layout()

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True


app = MyApp(0)
app.MainLoop()

You may want to try wxGlade. It’s quite accessible and it has some visually impaired users. Whenever there are accessibility issues, I try to address them. When you start with wxGlade, have a look at Preferences->Accessibility. There you can enable some options for better screen reader access.

I have attached a zip archive with the wxGlade file and the generated Python code.

What wxPython version are you using? There are some version that don’t work well with screen readers. E.g. 4.0.3 is working while 4.0.4 to 4.0.7 are causing problems. 4.1 should be fine, though.

accessibility.zip (1.5 KB)

Awesome! This one works great. The only issue is that when I open the window, it automatically focuses the screen reader on the button instead of the welcome text. Any fix for that?

By default, a read-only text control will not gain the focus.

You can add a call to SetFocus:

        self.text_ctrl_1 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "Welcome to TQ Reminders (text ctrl)", style=wx.TE_READONLY)
        self.text_ctrl_1.SetFocus()

In wxGlade, you would have to check the Common->Focus checkbox for the widget.

1 Like

Thank you very much. The last thing i want to know. When i navigate to the text control in the window it always says “Edit read only” before it reads the text. is there anyway to stop this? it can get a bit annoying. (keep in mind that i am reading a screen reader)

You probably have to make it not read-only.

I think for text controls there is no event that can be vetoed to turn it into a read-only control.
So, to simulate a read-only text control, you probably need to:

  • set the background colour to grey
  • bind an event handler for wx.EVT_CHAR_HOOK
  • implement the handler to call evt.Skip() only for keys like tab and enter.
        self.Bind(wx.EVT_CHAR_HOOK, self.on_char_event, self.text_ctrl_1)
    def on_char_event(self, event):
        if event.GetKeyCode() in (wx.WXK_RETURN, wx.WXK_ESCAPE, wx.WXK_TAB):
            event.Skip()

P.S.: The correct background colour is probably set by this call:

self.text_ctrl_1.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))

Thank you, you have been very helpful. The only problem now is that when i add a button the second text control dissappears. My aim is to create a window with two lines of text first(centered), and and 3 butons below them(two in one line and the other uder them) and they should be centered as well. Could someone please assist me? this is what i have right now:

import wx

import menus

class MyFrame(wx.Frame):

def __init__(self, *args, **kwds):

    kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE

    wx.Frame.__init__(self, *args, **kwds)

    self.SetSize((400, 300))

    self.SetTitle("TQ Reminders")

    self.panel_1 = wx.Panel(self, wx.ID_ANY)

    sizer_1 = wx.BoxSizer(wx.VERTICAL)

    label_1 = wx.StaticText(self.panel_1, wx.ID_ANY, "")

    sizer_1.Add(label_1, 0, wx.ALL, 4)

    self.text_ctrl_1 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "Welcome to TQ Reminders", style=wx.TE_READONLY)

    sizer_1.Add(self.text_ctrl_1, 0, wx.ALL | wx.EXPAND, 4)

    label_2 = wx.StaticText(self.panel_1, wx.ID_ANY, "")

    sizer_1.Add(label_2, 0, wx.ALL, 4)

    self.text_ctrl_2 = wx.TextCtrl(self.panel_1, wx.ID_ANY, "Please choose an option below to begin:", style=wx.TE_READONLY)

    sizer_1.Add(self.text_ctrl_2, 0, wx.ALL | wx.EXPAND, 4)

    button_1 = wx.Button(self.panel_1, wx.ID_ANY, "hey girl")

    sizer_1.Add(button_1, 0, wx.ALL | wx.EXPAND, 4)

    self.panel_1.SetSizer(sizer_1)

    self.Layout()

           

    mainMenu = menus.build_main_menu(self)

def onExit(self, event):

    self.Close()

class MyApp(wx.App):

def OnInit(self):

    self.frame = MyFrame(None, wx.ID_ANY, "")

    self.SetTopWindow(self.frame)

    self.frame.Show()

    return True

app = MyApp(0)

app.MainLoop()