wx.Frame.Show() not working

I’ve pretty mutch worked out the errors in my code so far in the current segment, However there is one issue in my code. I can run the code in bmud.py without any error but but no Frame or top level window of any kind appeered. I checked to see if maybe it’d started in another process, even thow I haden’t coded it to do that, just to see if that was built-in behavior but there was nothing new besides my instance of command prompt. In order to close the program’s loop I had to terminate my command prompt session. Yet when I checked the log, I saw nothing but empty curly braces and no trace or error message.
Things I tried:
In my original code, I had the call to window.Show after I declared window to be a Frame. So I commented it out and added it in just before my call to app.MainLoop. That did nothing. I even checked the log again but just saw a second set of braces Underneeth the first. Again no error. I’m thinking it might be because I’m running it from the command line, But I’m not sure.
I also saw people passing True to the Show method so I changed it from window.Show() to window.Show(True). It didn’t seem to make a difference. I am blind, and am using NVDA as my screenreader, but I don’t think that’s the issue because NVDA’s menus and dialog boxes were writen with wxpython, I’d think It wood be able to read other gui’s created with it.
Using python 3.9 with the latest wxpython, on windows 11 x64
I am using py_setenv for environment variable manipulation.
I have imported telnetlib but haven’t used it yet in this segment.
Note, I have a broken if statement with old code and definitions witch doesn’t execute write now because I have another one writen in the initialization segment witch sets the environment variable. The else statement contains the clean new function. The point was to make it so that the Add button is the only thing in the Frame until the user as created a character. I plan on fixing it before bringing it into beta stage.
File: bmud.py:

import os
from py_setenv import setenv
import telnetlib
import wx
from ast import literal_eval
name = mud = host = port =  None
if "chars" in os.environ:
	first_run = 0
else:
	first_run = 1
if first_run == 0:
	setenv("chars", value = "{}")
	chars = literal_eval(setenv("chars"))

app = wx.App(1, "bmud.log")

window = wx.Frame()
#window.Show()
window.Title = "character list"
pnl = wx.Panel(window)
#chars = setenv("chars")
if len(setenv("chars")) < 1:
	def new():
		dlg = wx.Dialog(window)
		try:
			dlg.Title = "New character"
		except:
			setenv("errors", value = ["Title Error"])
		pnl2 = wx.Panel(dlg)
		#chars = os.environ[chars]
		class edit(wx.Button()):
			#a text control with label support
			def __init__(self, parent, id, value, pos, size, style, label = ""):
				return wx.TextCtrl(parent, id = id, value = value, size = size, pos = pos, style = style)
				if len(label) > 0:
					self.SetLabel(label)
		name = edit(pnl2, -1, "name")
		mud = edit(pnl2, -1, "mud name")
		
		host = edit(pnl2, -1, "host")
		port = edit(pnl2, -1, "port")
		ok = wx.Button(pnl2, label = "ok")
		ok.Bind(wx.EVT_BUTTON(), dlg.destroy())
		def erase():
			setenv("abort", value = 1)
			dlg.destroy()
		cancel = wx.Button(pnl2, label = "Cancel")
		cancel.Bind(wx.EVT_BUTTON, erase())
		dlg.ShowModal()
	add = wx.Button(pnl, label = "add")
	add.Bind(wx.EVT_BUTTON(),  new())
else:
	def new():
		dlg = wx.Dialog()
		try: #I didn't think it wood work.
			dlg.Title = "New character"
		except:
			setenv("errors", value = ["Title Error"])
		pnl2 = wx.Panel(dlg)
		#chars = os.environ[chars]
		#creating a text control inside a static box as a solution to not having a label parameter.
		lname = wx.StaticBox(pnl2, id = -1, label = "Character name")
		name = wx.TextCtrl(lname, id = -1, value = "")
		lmud = wx.StaticBox(pnl2, id = -1, label = "mud name")
		mud = wx.TextCtrl(lmud, id = -1, value = "")
		lhost = wx.StaticBox(pnl2, id = -1, label = "host")
		host = wx.TextCtrl(lhost, id = -1, value = "")
		lport = wx.StaticBox(pnl2, id = -1, label = "port")
		port = wx.TextCtrl(lport, id = -1, value = "")
		ok = wx.Button(pnl2, label = "ok")
		ok.Bind(wx.EVT_BUTTON, handler = dlg.Destroy)
		def erase():
			setenv("abort", value = 1)
			dlg.Destroy()
		cancel = wx.Button(pnl2, label = "Cancel")
		cancel.Bind(wx.EVT_BUTTON, handler = erase)
		dlg.ShowModal()
	
	def get_names():
		names = []
		for I in chars:
			names.append(I)
		return names
	charlist = wx.ComboBox(pnl, choices = get_names(), style = wx.CB_READONLY)
	add = wx.Button(pnl, label = "add")
	add.Bind(wx.EVT_BUTTON, new())


window.Show(True)

app.MainLoop()

file bmud.log:
{}

Hi @trunio7578,

Unfortunately, when you just paste your code directly into a post on this forum, the forum’s software reformats in such a way that makes it difficult to run. For example it changes double and single quotes to characters that aren’t valid in code, it removes double underscores and displays the text they enclose in a bold format. The worst effect is that it wrecks the indentation so it’s very difficult to tell which lines are part of an ‘if’ or ‘else’ block and also which lines are part of a class, method or function.

There are two ways to preserve the formatting of the code:

  1. Enclose the code in tags for pre-formatted text. These tags consist of three grave characters (`). You need to put three grave characters just before the lines of code and three grave characters just after the lines of code.

or

  1. Upload the file containing the code. If you click on the “Upload” button in the toolbar at the top of the post editing panel, your browser should display a dialog to upload an image or text file. Click on the dialog’s Browse button and then select the file to be uploaded. Then click on the dialog’s Upload button. The file will be uploaded and a link to it will be placed in your post on the forum.

Either of these techniques will make it easier for members here to test your code and figure out why it isn’t working.

Thanks, I edited the post.

Thanks for editing the post.

Here are some initial thoughts:

In the definition of the edit class, the base class should not be followed by parentheses. i.e use: class edit(wx.Button)

Also in the edit class, your __init__()method returns a wx.TextCtrl. The __init__() method should not return anything, its purpose is to initialise an instance of the class.

In the Bind() calls you should not include parentheses after the name of the methods to be called. Doing so causes the method to be called when Bind() is called and not when the event is triggered.

Hi trunio7578,

I think your code has some problems. There seems to be no syntax error, but some wrong code as Richard has pointed out. I recommend starting with a minimal executable program like this:

app = wx.App()
window = wx.Frame(None)
window.Title = "character list"
pnl = wx.Panel(window)
window.Show()
app.MainLoop()

Make sure you get a blank wx.Frame window.
image

The next step is adding an button and the event handler:

def new(evt):
    pass

app = wx.App()
window = wx.Frame(None)
window.Title = "character list"
pnl = wx.Panel(window)
if 1:
    add = wx.Button(pnl, label="add")
    add.Bind(wx.EVT_BUTTON,  new)
window.Show()
app.MainLoop()

image

At this step, you don’t have to implement the new function yet, just make your application look the way you want it to.

Then, implement the new function:

def new(evt):
    with Dialog(window, title="New character") as dlg:
        if dlg.ShowModal() == wx.ID_OK:
            ## do something here if ok.
            print('ok')

I think that it is easier and more convenient to design by inheriting wx.Dialog and using it so:

class Dialog(wx.Dialog):
    def __init__(self, *args, **kwargs):
        wx.Dialog.__init__(self, *args, **kwargs)
        
        sizer = wx.BoxSizer()
        sizer.AddMany((
            wx.Button(self, wx.ID_OK, 'OK'),
            wx.Button(self, wx.ID_CANCEL, 'Cancel'),
            ),
        )
        self.SetSizer(sizer)

The next step would be the implementation and design of the Dialog.
So you can program step by step and build your application more reliably.

Yes, I figured out most of what he’d said about it, especially when I continued to get AssertionErrors particularly for some line number 1589 I think, but it took a while before I’d thought: “I think it’s actually trying to call the function during the process of binding it to the event handler, and that’s why i’m geting assertion errors”, and removed the parenthesis.
I did what you suggested and tested to see if a Frame was even creatable by my wxpython and my python interpreter. Originally I had used wx.Frame with no arguments, because I thought the default for the parent was None and that all other parameters were optional. Then, when it refused to show, I looked at your code and saw that you passed a None to the constructer. So I fixed the file to say wx.Frame(None).
That caused it to display. However I noticed one big difference. When I run bmud.py from the command line, however, the title bar changes to “command prompt python bmud.py”, and the word false displays as the last line of output instead of the current working directory in this case c:\users\taylo\documents\projects. To me I think this means that the if statement got executed, but I think an error shood’ve been throne since the MainLoop call doesn’t happen until either statement is executed. This means that it can’t be the broken if statement that richard pointed out, but I’ll fix it to meeror the else statement witch is cleaner.
The edit class was ment to be a way to attach a label to the TextCTRL like with a Button, ComboBox, or any other control with a label parameter, but when that got to complex, I had to switch to using static boxes, as you’ve seen me do in my else statement.
In your code, you write multiple times:

def new(evt):

Why the evt parameter? I don’t think I need it since i’ve hard coded EVT_BUTTON as my event to bind in my if and else statements.
Also, I usually don’t enharit widget classes like wx.Frame and define my own class unless I need to override some functions or add functionality for example:

class autoloop(wx.Frame):
    #automatic calling of app.MainLoop when Show is called
    def setapp(self, obj):
        self.object = obj
    def __init__(self, *args, **kw):
        wx.Frame.__init__(*args, **kw)
        self.object = None
    def Show(self):
        wx.Frame.Show()
        self.object.MainLoop()
window = autoloop(None)

An event handler receives an event object. In your case, the function new is called with a wx.CommandEvent object when the button is pressed. So we need to add one argument to the event handler:

def new(evt):
    ...
add.Bind(wx.EVT_BUTTON,  new)

or, if you don’t want to (or for some reason can’t) add an argument to the function new, write:

def new():
    ...
add.Bind(wx.EVT_BUTTON,  lamabda evt: new())