PySimpleGUI / PySimpleGUI

Python GUIs for Humans! PySimpleGUI is the top-rated Python application development environment. Launched in 2018 and actively developed, maintained, and supported in 2024. Transforms tkinter, Qt, WxPython, and Remi into a simple, intuitive, and fun experience for both hobbyists and expert users.
https://www.PySimpleGUI.com
Other
13.33k stars 1.84k forks source link

Accessing root TK() #841

Closed eagleEggs closed 5 years ago

eagleEggs commented 5 years ago

Hello! I'm wondering if there is a way to get access to the TK functions through PSG - Without also importing tkinter.

I need to access TK.bind()

win = Tk.Tk()
win.bind()

I've looked through the docs and such and tried many things. I can't seem to get access to it from a window made with PSG.

If not I suppose I could spawn a TK window just for this purpose.

Thanks!

edit: I think I can do what I need with your canvas or graph element actually - Mouse X,Y click position.

MikeTheWatchGuy commented 5 years ago

window.TKroot is a window's TK window.

eagleEggs commented 5 years ago

So, this should work?

window.TKroot.bind

MikeTheWatchGuy commented 5 years ago

It's a call, bind(...).

I have no clue what you're doing so I cannot tell you if it work or not.

Straying into gray-area.

eagleEggs commented 5 years ago

Right. Here is some stripped code as I will try to explain better from now on :)

import PySimpleGUI as sg

canvas_column = [[sg.Graph(key="graph", canvas_size=(100, 100),
                           graph_bottom_left=100, graph_top_right=100)]]

canvasWindow = sg.Window('Test Anatomy - Canvas', grab_anywhere=False, no_titlebar=False,
                                    auto_size_text=True, location=(100,100),size=(100,100), resizable=True, background_color="Blue", alpha_channel=0.3, keep_on_top=True).Layout(
                    [[sg.Column(canvas_column)]])

canvas_graph = canvasWindow.FindElement("graph")

while True:

    b, values = canvasWindow.Read(timeout = 100)  # read input values from GUI

    if b is None:
        break

    else:
        pass

If you add canvasWindow.TKroot.bind() or any other function in TK, it doesn't show up nor work. Am I missing something? I can't access the root at all.

MikeTheWatchGuy commented 5 years ago

You cannot act upon elements nor any other tk resource until after a window is Read or Finalized.

If you're looking for Canvas events, I return drag and click events.

I still don't know what you're trying to do. What are you trying to do?

eagleEggs commented 5 years ago

Ok, I didn't have the latest update with enable_events...

When I use enable_events, I'm getting an error about the int object not being subscriptable:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1702, in __call__
    return self.func(*args)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\PySimpleGUI\PySimpleGUI.py", line 1833, in ButtonPressCallBack
    self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\PySimpleGUI\PySimpleGUI.py", line 1688, in _convert_canvas_xy_to_xy
    scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
TypeError: 'int' object is not subscriptable
canvasWindow  graph {'graph': (None, None)}

The new code:

import PySimpleGUI as sg

canvas_column = [[sg.Graph(enable_events=True, key="graph", canvas_size=(100, 100),
                           graph_bottom_left=100, graph_top_right=100)]]

canvasWindow = sg.Window('Test Anatomy - Canvas', grab_anywhere=False, no_titlebar=False,
                                    auto_size_text=True, location=(100,100), size=(100,100), resizable=True, background_color="Blue", alpha_channel=0.3, keep_on_top=True).Layout(
                    [[sg.Column(canvas_column)]])

canvas_graph = canvasWindow.FindElement("graph")

while True:

    b, values = canvasWindow.Read(timeout = 100)  # read input values from GUI

    if b != sg.TIMEOUT_KEY:
        print("canvasWindow ", b, values)

    if b is None:
        break

    else:
        pass

I'm just looking to get the X, Y position of mouse click.

eagleEggs commented 5 years ago

You have to be kidding me, ok I got it. After looking into the source and some research I found that somewhere there was an int that should be read as iterable... I wasn't specifying X,Y for graph_bottom_left and right. Was only passing a single int.

Thanks again!

MikeTheWatchGuy commented 5 years ago

Note that you can also enable "drag" events. The enable_events enables click events. I am going to add another "new" parameter, enable_drag_events that is a duplication of the drag_submits parameter.

eagleEggs commented 5 years ago

Cool. This does exactly what I need it to do.

Although I've noticed something strange, the graph isn't actually going from 0 to max for width, height. The X starts a bit to the right, and the Y is missing 0 through 17:

image

image

Maybe you know of this issue and have some advice.

Here is some test code if needed (Thanks!):

import PySimpleGUI as sg

canvas_column = [[sg.Graph(enable_events=True, key="graph", canvas_size=(1000, 1000),
                           graph_bottom_left=(0, 0), pad=(0,0), graph_top_right=(1000,1000))]]

canvasWindow = sg.Window('Test Anatomy - Canvas', grab_anywhere=False, no_titlebar=False,
                                    auto_size_text=True, location=(100,100), size=(1000,1000), resizable=True, background_color="Blue", alpha_channel=9, keep_on_top=True).Layout(
                    [[sg.Column(canvas_column)]]).Finalize()

canvas_graph = canvasWindow.FindElement("graph")

while True:

    b, values = canvasWindow.Read(timeout = 100)  # read input values from GUI

    if b != sg.TIMEOUT_KEY:
        print("canvasWindow ", b, values)
        saveXY = values

        print(saveXY["graph"][0], saveXY["graph"][1])

    if b is None:
        break

    else:
        pass

edit: It seems to have correlation with the canvas size, as changing the canvas size changes this empty space and where the Y values begin on the graph.

MikeTheWatchGuy commented 5 years ago

That's a very weird thing. THANK YOU for the test code. It made it all make sense. Without it it was a difficult thing to describe. You described it really well; it's just difficult to describe. 👍

I dunno.... perhaps I have sometime wrong in my math, like a rounding error.

MikeTheWatchGuy commented 5 years ago

Back at you.

Here's what the problem was.... a size parameter on your window. It was set to 1000,1,000, yet your graph is also that size. This will compress and cut off your graph.

Try turning the background color to yellow so you can see where the graph actually resides.

After removing the size fixed the problem.

import PySimpleGUI as sg

canvas_column = [[sg.T('test')],[sg.T('test')],
    [sg.Graph(enable_events=True,drag_submits=False, key="graph", canvas_size=(1000, 1000),
                           graph_bottom_left=(0, 0), pad=(5,5), graph_top_right=(1000,1000), background_color='yellow')]]

canvasWindow = sg.Window('Test Anatomy - Canvas', grab_anywhere=False, no_titlebar=False,
                                    auto_size_text=True, location=(100,100),  resizable=True, background_color="Blue", alpha_channel=9, keep_on_top=True).Layout(
                    [[sg.Column(canvas_column)]]).Finalize()

canvas_graph = canvasWindow.FindElement("graph")

while True:

    b, values = canvasWindow.Read(timeout = 100)  # read input values from GUI

    if b != sg.TIMEOUT_KEY:
        print("canvasWindow ", b, values)
        saveXY = values

        print(saveXY["graph"][0], saveXY["graph"][1])
    if b is None:
        break
    else:
        pass
eagleEggs commented 5 years ago

Oh wow. The background color makes it all make sense! Thanks!!!!!

MikeTheWatchGuy commented 5 years ago

Check out the crossword puzzle demo program for more info on using clicks with a Graph. I use it to detect when a crossword square is clicked on and then place a letter in that square. It's a lesson in 'rounding'.

image