I am currently creating a quiz game in Tkinter. This game consists of a login page, the quiz, a graph to show results and a pong game. The quiz and login use the Tkinter library for the GUI, the graph uses MatPlotLib and pong uses pygame. Is there any way that I would be able to link all of these modules in the main menu, for example creating a Tkinter GUI and then assigning a command to each button to launch the respective python files?
EDIT: Adding code that I have tried.
from tkinter import *
import sqlite3
import sys
import time
import importlib
importlib.import_module('Quiz')
class Menu:
def __init__(self, master):
#Setting up the window
self.master = master
self.master.geometry("1350x800+50+50")
self.master.title("Main Menu")
self.quizLaunch = Button(self.master, text="Quiz", command = quizApplication)
self.quizLaunch.pack()
root = Tk()
Menu(root)
root.mainloop()
Yes, it is completely possible. You can do this by importing packages like what you do in normal codes. You will be needed to import the following libraries to embed matplotlib into tkinter.
import matplotlib
import pygame
from tkinter import *
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
I recently made a basic GUI application using pygame in the python script along with tkinter library.
It would be great if you could post your code.
You can find the complete guide at:
https://pythonprogramming.net/how-to-embed-matplotlib-graph-tkinter-gui/
Related
I am trying to open a web page using PyQt5 after a button press in tkinter window.
As soon as the new window opens, it resizes (downsizes in this case) the tkinter window permanently.
Minimal code required to reproduce this
import sys
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWidgets import QApplication
from tkinter import *
from threading import Thread
class Web:
def __init__(self,url,title='',size=False):
self.title=title
self.url=url
self.size=size
self.app=QApplication(sys.argv)
self.web=QWebEngineView()
self.web.setWindowTitle(self.title)
self.web.load(QUrl(self.url))
if size:
self.web.resize(self.size[0],self.size[1])
def open(self):
self.web.show()
sys.exit(self.app.exec_())
def launch():
web=Web('https://www.example.com')
web.open()
root=Tk()
button=Button(root,text='open',command=lambda:Thread(target=launch).start())
button.pack(padx=100,pady=100)
root.mainloop()
Images for reference
Both the images have the same height.
I would like to know the reason and a way to prevent this.
I have figured it out myself. PyQt changes the dpi awareness which does not happen by default with tkinter. Due to which the tkinter window resized itself as soon as PyQt was launched in the same main loop.
Since I am on a windows machine, using this solved the problem.
ctypes.windll.shcore.SetProcessDpiAwareness(1)
I am currently working on a GUI using python tkinter and matplotlib. However, after adding the matplotlib features to my GUI, I couldn't kill the program by closing all the windows anymore. I was able to do that previously when I experimented with some simple matplotlib plots. I would really appreciate if anyone could help me by giving some suggestions to try. Thank you! Here is the code that is relevant to my problem:
import tkinter as tk
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.backend_bases import MouseEvent, key_press_handler
import sys
sys.path.append('/Users/YangQing/Desktop/eMPRess')
import empress
class App:
def plot_cost_landscape(self):
"""Plots the cost landscape using matplotlib and embeds the graph in a tkinter window."""
# creates a new tkinter window
plt_window = tk.Toplevel(self.master)
plt_window.geometry("550x550")
plt_window.title("Matplotlib Graph DEMO")
# creates a new frame
plt_frame = tk.Frame(plt_window)
plt_frame.pack(fill=tk.BOTH, expand=1)
plt_frame.pack_propagate(False)
recon_input = empress.read_input("./examples/heliconius.newick")
cost_region = empress.compute_cost_region(recon_input, 0.5, 10, 0.5, 10) # create
cost_region.draw_to_file('./examples/cost_poly.png') # draw to a file
fig = cost_region.draw() # draw to figure (creates matplotlib figure)
canvas = FigureCanvasTkAgg(fig, plt_frame)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas, plt_frame)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP)
# prints the x,y coordinates clicked by the user inside the graph otherwise prints an error message
fig.canvas.callbacks.connect('button_press_event', self.get_xy_coordinates)
Try adding os._exit(0) at the end of the script!! For this you also need to import the os module into your script.os._exit() method in Python is used to exit the process with specified status.
I have my principal script running with terminal that works perfectly. Im trying to make a gui for it but im stuck at this point.
Like you see on the screen, at the start of the script it asks if it should check the database. And just after, it asks first the platform before opening the captcha for the database check. The problem happens exactly here on my GUI version, look.
Like you see, the gui starts, but when i click on check for new database, it directly opens the captcha without asking the platform... And it asks me the platform only after i solved the captcha which i dont want to after...
Here is the main testkinter.py code:
import tkinter as tk
from tkinter import messagebox
import commands
import CheckDatabase
import SetPlatformfile
def check_and_hide():
CheckDatabase.db_download(root)
checkdb.pack_forget()
checkdb1.pack_forget()
root = tk.Tk()
checkdb = tk.Button(root, text="Check for new databases", command=check_and_hide)
checkdb.pack()
checkdb1 = tk.Button(root, text="No")
checkdb1.pack()
root.mainloop()
Here is the set_platform function called in the Checkdatabse file:
import tkinter as tk
import config
from tkinter import messagebox
def set_platform(root):
platform = tk.Label(root,text="'a'|Android -- 'i'|iOS: ")
platform.pack()
androidbutton=tk.Button(root,text="Android",command=renameplatformandroid)
iosbutton=tk.Button(root,text="iOS",command=renameplatformios)
androidbutton.pack()
iosbutton.pack()
def renameplatformandroid():
config.platform = 'android'
print(config.platform)
def renameplatformios():
config.platform = 'ios'
print(config.platform)
And cuz of my checkdatabase file is really really long, i'll just put a screen at the exact moment where set_platform is called (its called in the func signup which itself is directly called at the beginning of db_download) .
I hope my question is clear! Let me know if you need more details.
When running a tkinter program in the standard python idle program the window displays and you are able to interact with it, yet running the same program in pycharm causes the program window to flash up briefly then close.
I'm assuming its to do with the mainloop, what do you need to modify in your code to prevent the program from automatically closing when running in pycharm
An excert from my code follows
from tkinter import *
import tkinter
from tkinter import Text, Tk, ttk
import csv
from csv import DictReader
import sys
import os
class GUI:
def __init__(self, root):
....
def main():
global label
root = Tk()
root.title(" My program")
root.geometry("550x330+600+300")
mycolor = '#%02x%02x%02x' % (39, 39, 39) # background color
root.configure(bg=mycolor)
gui = GUI(root)
main()
Update : After a bit of mucking around, partly due to my code not being the best (rookie), I've managed to get it to work. For anyone interested heres the modification:
from tkinter import *
import csv
from csv import DictReader
import sys
import os
class GUI:
def __init__(self, master):
self.master = master
master.title(" My Programs")
master.geometry("550x330+600+300")
master.iconbitmap('logo.ico')
mycolor = '#%02x%02x%02x' % (39, 39, 39) # background color
master.configure(bg=mycolor)
....... Most of the above is program set up stuff but shown
MAIN CODE HERE
root = Tk()
gui = GUI(root)
root.mainloop()
Works now as expected
Python has a -i startup option which cause Python to enter interactive move when the program finishes, instead of exiting. IDLE executes code as if one entered python -i file.py at the terminal. This allows one to interactively explore the live gui by entering code in the Shell.
From this question and the one referenced by flyingmeatball, it appears that PyCharm does not use or simulate -i. So one must finish a tkinter program with root.mainloop to see anything. Unless one adds a button to quit the mainloop without destroying the application, one will not be able to interact with interactive statements. (Again, this is completely based on what has been posted on SO, as I have no experience with PyCharm.)
The following code runs fine within IDLE, but otherwise I get "NameError: global name 'messagebox' is not defined". However, if I explicitly state from tkinter import messagebox, it runs fine from where ever.
from tkinter import *
from tkinter import ttk
root = Tk()
mainFrame = ttk.Frame(root)
messagebox.showinfo("My title", "My message", icon="warning", parent=mainFrame)
Why does IDLE not need the explicit import statement but elsewhere it is required?
the messagebox is a separate submodule of tkinter, so simply doing a complete import from tkinter:
from tkinter import *
doesn't import messagebox
it has to be explicitly imported like so:
from tkinter import messagebox
in the same way that ttk has to be imported explicitly
the reason it works in idle is because idle imports messagebox for its own purposes, and because of the way idle works, its imports are accessible while working in idle
IDLE is written in Python and uses Tkinter for the GUI, so it looks like your program is using the import statements that IDLE itself is using. However, you should explicitly include the import statement for the messagebox if you want to execute your program outside the IDLE process.
messagebox.showinfo is defined inside tkinter/showinfo.py but when you use from tkinter import * you only import tkinter/__init__.py which holds the definitions of Label, Entry, Button, ... That is how python imports work.
When you use from tkinter import messagebox it looks for messagebox inside tkinter/__init__.py but it can't find it so it tries to import tkinter/messagebox.py
As for the IDLE anomaly, it is a bug in IDLE and I believe that it was patched.