Is there anything I need aware of using Tkinter and pygame together? - python

I am using pygame to write a program and I need some GUI configuration text field and button for control. I've already made the button using pygame, but I just can write a text field out of pygame. Maybe I need to use tkinter together with pygame.
I think if there is no way to made to pygame part and tkinter part together in 1 window, then I could put them into 2 separate windows.
I hope the tkinter part can update the global variable in my pygame part, would there if any problem? I might create a child process of tkinter from the pygame part so that the tkinter part can probably "see" the global variable in pygame part and modify them.
Can I do this? Are there any pitfalls?

Both Tkinter and Pygame have their own event loops, so doing what you want is far from simple. The problem is that Pygame wants to control both the screen and the events the user feeds into the computer. This doesn't work well with GUI libraries, which also want to be "in control".
I would suggest sticking with Pygame, it has some nice GUI toolkits that will help you create buttons and other controls. Go over this page - it should clear things out. You may also find this discussion useful.
Apart from the practical aspects, a GUI created with Pygame is also IMHO more suitable for a game than something done with Tkinter, since games usually have original, thematical user interfaces and not the bland "text box + button" windows we're used to in other applications.
Take a look at some of the sample games on the Pygame wiki, many have GUIs and you can borrow ideas and code from them.

from tkinter import *
import pygame
import random
import os
global playing
playing=False
def playpause():
global playing
if playing==True:
playing=False
else:
playing=True
root = Tk()
embed = Frame(root, width=640, height=480)
embed.grid(row=0,column=2)
playpausebutton=Button(root, command=playpause, text="Play/Pause")
playpausebutton.grid(row=1,column=2)
root.update()
os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
os.environ['SDL_VIDEODRIVER'] = 'windib'
pygame.display.init()
screen = pygame.display.set_mode((640,480))
pygame.display.flip()
while True:
#your code here
if playing:
screen.fill((random.randint(0,255),random.randint(0,255),random.randint(0,255)))
pygame.display.flip()
root.update()
This works just great, I have used this method successfully in multiple cases.

I have also found pgu is awful. However, what you say about the tkinter event loop taking control is wrong. You just call root.update instead of mainloop, and this can go inside of a while loop to replace the mainloop. Answering your main question however, there is something you should be aware of. It seems that whenever I run the two programs alongside each other, this traceback occurs:
TclError: expected boolean value but got "-1"
Fatal Python error: (pygame parachute) Segmentation Fault
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Because of this I would avoid the combination, although I suspect this particular issue may pertain to my use of threads.

Related

How to put a pygame in a tkinter application?

I programmed a board game in pygame, which is cool and all but I'd like to put it in a tkinter window so that I have space above my game, in which I can put buttons for resetting the board, etc.
How do I embed this? I would like to only have a tkinter window and not a seperate pygame window.
I made a window using
win = pygame.display.set_mode((WIDTH, HEIGHT)
pygame.display.set_caption('Game')
And then I displayed it using a while loop with
pygame.display.update()
I genuinely don't know how to make a tkinter that embeds this.
I tried using this solution, however when I ran this program I got two windows, which isn't what I want
This is complicated.
Both toolkits have their own windowing subsystems.
I remember once coming across a way to have Pygame's SDL render into a canvas in another window - but I can't now recall if that was X11 (~Linux) specific.
You will jabe to either have your buttons and controls rendered by Pygame - in that case there are complementary libraries such as Phil's Pygame Utilities ("PGU" - I have republished a version of it for Python3 https://pypi.org/project/pygame-pgu/ ) or another similar library.
Another option is to have your game application use 2 independent, related windows - in this case, running tkinter in a separate thread should be enough to have both working - or calling the .update() method on the root tkinter object in the pygame mainloop should suffice.

how to make a tkinter window with a lot of properties

I am trying to make a game overlay with python and it needs to support a lot of features for my game overlay to work the way it was intended to.
It needs to have a transparent window, pass clicks both right and left (to the application underneath it), pass all keyboard keys (to the application underneath it), and FINALY can still collect all the mouse movement and keyboard press events.
I don't even know if all of this is possible, or if I need to do this in another pip or language
I am on windows 10
jesus.py :
from tkinter import *
jesus = Tk()
jesus.title("Minecraft's Jesus")
jesus.attributes("-fullscreen", True)
jesus.attributes("-topmost", True)
jesus.attributes("-alpha", 0.002)
jesus.configure(background='grey')
jesus.mainloop()
Edit: I was completely unaware of hooks at the time and now this question is useless. A thanks to Tim Roberts for suggesting to use hooks.

Is it possible to 'hide' or disable the turtle screen and just capture the final graphic?

How necessary is viewing the canvas window that a Turtle object draws on? Can it be hidden or disable and just the final graphics captured?
I have a python script that uses the turtle library and am wondering is it crucial for the canvas window, where one can view the actual drawing being created, to be open during the script's runtime? Is it possible to not even load the visual portion of the canvas and simply capture the data at the end? (which btw I create a .ps file with and use PIL to convert it to a .jpg).
Would this perhaps make the overall script run faster as I am planning on bumping up my iteration count significantly and it is already fairly slow as is (which could of course be the nature of the library and I have to just deal with it)?
Having searched Google, the only issues I could find with terms like, "hide turtle canvas" or "disable canvas window" just netted me issues unrelated to my question. I have also searched through the turtle library documentation and no function or methods seemed to do the job, but of course I could have missed it.
I'm not familiar with the root package tkinter so if there is something on that end that I could mess with I can look into that as a solution. But I wouldn't know where to begin as I don't fully comprehend the relationship between tkinter and turtle.
Using embedded turtle, we can create and withdraw the Tk root window immediately and then simply work with a Canvas:
from tkinter import *
from turtle import RawTurtle
(root := Tk()).withdraw()
canvas = Canvas(root)
turtle = RawTurtle(canvas)
turtle.speed('fastest')
turtle.begin_poly()
for _ in range(5):
turtle.forward(100)
turtle.right(360/5)
turtle.end_poly()
print(turtle.get_poly())
OUTPUT
> python3 test.py
((0.00,0.00), (100.00,0.00), (130.90,-95.11), (50.00,-153.88), (-30.90,-95.11), (0.00,0.00))
>
I'm intentionally avoiding the TurtleScreen and ScrolledCanvas wrapper classes as we don't need any interactive methods.
The same thing could probably be done from standalone turtle by digging into the underpinnings via getcanvas() and finding the root window to withdraw.
Not perfect, but on my system I don't see any window. If you see a flash of one, look up the tkinter overrideredirect(1) method, calling it just before the withdraw() to avoid the flash.

How to accept text input from a pygame GUI

I am working on a RPG game using Python and Pygame, and am trying to make a two-part GUI, including a lower part that is like the basic command line, and a top part that will show all graphical "action."
What I need to find out is a way to include both in a pygame window, instead of using a pygame window and terminal window. As well, are there any Pygame GUI toolkits that would be appropriate for this use?
Thanks All!
May I suggest using ezText instead?
It's a cool way to add text inupt bars to pygame. I used it before my self, and It's really easy to use.
http://www.pygame.org/project-EzText-920-.html
(feel free to leave a comment if you want help using it, although everything you need to know is in the example.py that comes with it)
Take a look here (http://wiki.python.org/moin/PythonGameLibraries) for a whole list of ToolKits for both Pygame and Pyglet. Albow (http://www.cosc.canterbury.ac.nz/greg.ewing/python/Albow/) has worked well for me in the past.
The easiest way to accomplish what you're talking about would be to make two Surfaces, one for each part of the interface, and then constantly update them in separate modules to finally blit them every frame. That way your main module can be simplified to something like:
import action_gui
import cl_gui
import pygame
pygame.init()
MAIN_SURF = pygame.display.set_mode((x, y))
pygame.display.set_caption('My Game')
while (True):
action_surf = action_gui.update()
cl_surf = cl_gui.update()
MAIN_SURF.blit(action_surf, my_position_1)
MAIN_SURF.blit(cl_surf, my_position_2)
Best of luck.

How to keep a python window on top of all others (python 3.1)

I'm writing a little program that basically has a bunch of buttons that when you click one, it inputs a certain line of text into an online game I play. It would be a lot easier to use if the GUI would stay on top of the active game window so the user could be playing and then press a button on the panel without having to bring it to the front first.
Any help on how to do this would be great. Thanks
EDIT: Using tkinter
You will need to provide the information on which GUI framework you are using for detailed answer at SO.
On windows you could do something like this with the handle of your window.
import win32gui
import win32con
win32gui.SetWindowPos(hWnd, win32con.HWND_TOPMOST, 0,0,0,0,
win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)
Also with Tkinter, you might want to try. I have not tried it though.
root = Tk()
root.wm_attributes("-topmost", 1)

Categories