1

I'm running into the following error when trying to open a Tkinter window from a pygame app


pygame 2.1.2 (SDL 2.0.18, Python 3.8.5)
Hello from the pygame community. https://www.pygame.org/contribute.html
2022-12-10 14:00:50.109 python[94676:3249298] -[SDLApplication macMinorVersion]: unrecognized selector sent to instance 0x7fd205b71790
2022-12-10 14:00:50.113 python[94676:3249298] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SDLApplication macMinorVersion]: unrecognized selector sent to instance 0x7fd205b71790'
*** First throw call stack:
(
        0   CoreFoundation                      0x00007ff80481843b __exceptionPreprocess + 242
        1   libobjc.A.dylib                     0x00007ff804367e25 objc_exception_throw + 48
        2   CoreFoundation                      0x00007ff8048af56b -[NSObject(NSObject) __retain_OA] + 0
        3   CoreFoundation                      0x00007ff80478269b ___forwarding___ + 1324
        4   CoreFoundation                      0x00007ff8047820d8 _CF_forwarding_prep_0 + 120
        5   libtk8.6.dylib                      0x0000000109b64db9 SetCGColorComponents + 265
        6   libtk8.6.dylib                      0x0000000109b6567a TkpGetColor + 250
        7   libtk8.6.dylib                      0x0000000109a9faa9 Tk_GetColor + 153
        8   libtk8.6.dylib                      0x0000000109a8f8e6 Tk_Get3DBorder + 134
        9   libtk8.6.dylib                      0x0000000109a8f74f Tk_Alloc3DBorderFromObj + 127
        10  libtk8.6.dylib                      0x0000000109aa0fad DoObjConfig + 941
        11  libtk8.6.dylib                      0x0000000109aa0ae5 Tk_InitOptions + 357
        12  libtk8.6.dylib                      0x0000000109aa09c5 Tk_InitOptions + 69
        13  libtk8.6.dylib                      0x0000000109ad1b5c CreateFrame + 1548
        14  libtk8.6.dylib                      0x0000000109ad1e37 TkListCreateFrame + 151
        15  libtk8.6.dylib                      0x0000000109ac97f8 Initialize + 2168
        16  _tkinter.cpython-38-darwin.so       0x000000010829f68b Tcl_AppInit + 91
        17  _tkinter.cpython-38-darwin.so       0x000000010829f34e Tkapp_New + 590
        18  _tkinter.cpython-38-darwin.so       0x000000010829f0ee _tkinter_create_impl + 222
        19  _tkinter.cpython-38-darwin.so       0x000000010829ebd6 _tkinter_create + 182
        20  python3.8                           0x00000001070a5644 cfunction_vectorcall_FASTCALL + 84
        21  python3.8                           0x000000010717ef20 _PyEval_EvalFrameDefault + 45072
        22  python3.8                           0x000000010717212d _PyEval_EvalCodeWithName + 557
        23  python3.8                           0x000000010704919a _PyFunction_Vectorcall + 426
        24  python3.8                           0x00000001070477dd _PyObject_FastCallDict + 93
        25  python3.8                           0x00000001070cdf52 slot_tp_init + 178
        26  python3.8                           0x00000001070dd4c1 type_call + 289
        27  python3.8                           0x0000000107047ad7 _PyObject_MakeTpCall + 167
        28  python3.8                           0x000000010717f086 _PyEval_EvalFrameDefault + 45430
        29  python3.8                           0x00000001070490e8 _PyFunction_Vectorcall + 248
        30  python3.8                           0x000000010717f2b0 _PyEval_EvalFrameDefault + 45984
        31  python3.8                           0x000000010717212d _PyEval_EvalCodeWithName + 557
        32  python3.8                           0x00000001071ea346 PyRun_FileExFlags + 358
        33  python3.8                           0x00000001071e9a91 PyRun_SimpleFileExFlags + 529
        34  python3.8                           0x00000001072122df pymain_run_file + 383
        35  python3.8                           0x00000001072119ab pymain_run_python + 523
        36  python3.8                           0x0000000107211745 Py_RunMain + 37
        37  python3.8                           0x0000000107212e11 pymain_main + 49
        38  python3.8                           0x000000010701b768 main + 56
        39  dyld                                0x00007ff804394310 start + 2432
)
libc++abi: terminating with uncaught exception of type NSException
zsh: abort      /Users/amanbasra/opt/anaconda3/bin/python 
import pygame as py
import tkinter as tk
import serial.tools.list_ports

# Pygame initialisation
py.init()

width = 500
height = 500

py.display.set_caption('MEP')
screen = py.display.set_mode((width, height))

buttonColour = (133, 133, 133)
black = (51, 51, 51)
white = (202, 202, 202)

screen.fill(black)

clock = py.time.Clock()
py.display.flip()

gridstate = {}

sysfont = py.font.get_default_font()
font = py.font.SysFont(None, 20)

# Draw Grid
resx = 10
resy = 10
buttonSize = 25
grid = []
startFallProcess = False

lineGroup = py.sprite.Group()

gridHeight = resy*buttonSize
gridWidth = resx*buttonSize

delayInterval = 15

restoreList = []

ports = serial.tools.list_ports.comports()
portList = []


def restore():
    for x in restoreList:
        x.active()


def repeat():
    start = True
    restore()


def config():
    window = tk.Tk()
    window.geometry(100, 100)
    optionVariable = tk.StringVar(window)
    tk.Label(window, text='Choose serial port')
    for x in sorted(ports):
        portList.append(x)
    tk.OptionMenu(window, optionVariable, portList)


class gridLine:
    def __init__(self, start, end):
        self.start = start
        self.end = end
        py.draw.line(screen, white, start, end)


class Line(py.sprite.Sprite):

    def __init__(self, x, y):
        super().__init__()
        self.x = x
        self.y = y
        self.image = py.Surface([5, 10])
        self.image.fill(white)
        self.rect = self.image.get_rect()

    def update(self):
        self.rect.x = self.x
        self.rect.y += 2.27*10
        if self.rect.y > height + 50:
            self.kill()


class Button:
    def __init__(self, x, y, w, h, getCo=None, text=None, action=False):

        self.textval = text
        self.presstime = 0
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.text = font.render(self.textval, True, white)
        self.getCo = getCo
        self.colour = buttonColour
        self.clicked = False
        self.box = py.draw.rect(screen, self.colour, (x, y, w, h), 1)
        self.action = action

    def draw(self):
        pos = py.mouse.get_pos()
        if self.box.collidepoint(pos):
            if py.mouse.get_pressed()[0] == 1 and self.clicked == False:
                self.clicked = True
                if self.action == False:
                    self.action = True
                    self.colour = (255, 0, 0)
                elif self.action == True:
                    self.action = False
                    self.colour = buttonColour
        if py.mouse.get_pressed()[0] == 0:
            self.clicked = False
        self.box = py.draw.rect(screen, self.colour,
                                (self.x, self.y, self.w, self.h), 3)
        gridstate.update({self.getCo: self.action})
        self.textrect = self.text.get_rect(center=(self.box.center))
        screen.blit(self.text, self.textrect)
        return self.action

    def oneTimeClick(self):
        pos = py.mouse.get_pos()
        if self.box.collidepoint(pos):
            if py.mouse.get_pressed()[0] == 1 and self.clicked == False:
                self.clicked = True
                self.action = True
                self.presstime = py.time.get_ticks()
                self.colour = (255, 0, 0)
            if py.mouse.get_pressed()[0] == 0:
                self.clicked = False
                self.action = False
                self.colour = buttonColour
        self.box = py.draw.rect(screen, self.colour,
                                (self.x, self.y, self.w, self.h))
        self.textrect = self.text.get_rect(center=(self.box.center))
        screen.blit(self.text, self.textrect)
        return self.action

    def clear(self):
        self.colour = buttonColour
        self.action = False
        gridstate.update({self.getCo: self.action})
        self.box = py.draw.rect(screen, self.colour,
                                (self.x, self.y, self.w, self.h))

    def active(self):
        self.colour = (255, 0, 0)
        self.action = True
        gridstate.update({self.getCo: self.action})
        self.box = py.draw.rect(screen, self.colour,
                                (self.x, self.y, self.w, self.h))


# Create Action Buttons
startButton = Button(0, 475, 50, 25, None, 'Start')
clearButton = Button(75, 475, 50, 25, None, 'Clear')
restoreButton = Button(150, 475, 50, 25, None, 'Restore')
repeatButton = Button(225, 475, 50, 25, None, 'Repeat')
configButton = Button(450, 475, 50, 25, None, 'Conf')

for x in range(resx):
    for y in range(resy):
        grid.append(Button((x*buttonSize), (y*buttonSize),
                           buttonSize, buttonSize, (x, y)))

running = True
while running:
    clock.tick(50)
    for event in py.event.get():
        if event.type == py.QUIT:
            running = False

    screen.fill(black)

    gridLine((275, 0), (275, height))
    clear = clearButton.oneTimeClick()
    start = startButton.oneTimeClick()
    restoreState = restoreButton.oneTimeClick()
    repeatState = repeatButton.draw()
    configState = configButton.oneTimeClick()

    if startFallProcess:
        for index, (buttonreset, (key, value)) in enumerate(zip(reversed(grid), reversed(gridstate.items()))):
            if value == True:
                restoreList.append(buttonreset)
                delaytime = (delayInterval *
                             abs(key[1]-10)) + startButton.presstime
                currenttime = py.time.get_ticks()
                if currenttime > delaytime:
                    lineGroup.add(Line((key[0]*10)+300, 0))
                    buttonreset.clear()
            if all(value == False for value in gridstate.values()):
                startFallProcess = False

    if clear == True:
        restoreList.clear()
        for x in grid:
            x.clear()

    if start == True:
        startFallProcess = True

    if repeatState:
        repeat()

    if restoreState:
        restore()

    if configState:
        config()

    for row in grid:
        row.draw()

    lineGroup.draw(screen)
    lineGroup.update()
    py.display.flip()

Not really sure where to begin in trying to establish what the problem is here. I've seen a variety of posts about the same error happening in different languages but has seemingly no relevance to this issue. Similar issues seem to have no answers.

For context I'm running MacOS 13.0.1 (Ventura). Can't see any known issues with Tkinter with the OS.

It seems I can open a Tkinter window if I initialise it outside of the function, but I only wish to display the window if the config button is pressed.

Aman
  • 31
  • 5

1 Answers1

1

Pygame is not necessarily compatible with tkinter. You should generally not mix frameworks unless the possibility is explicitly documented in one. Mixing frameworks is actually always based on undefined behavior and if you get it to work on one system it doesn't mean it will work on another. Alse see Embedding a Pygame window into a Tkinter or WxPython frame.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174