How do we add a popup window using PyQt? - pyqt4

Hi I need to create a pop up window when user clicks a button in the MainWindow.
So I created a DialogWindow and linked it with MainWindow with below line of code.
For note I've three modules 1. MainWindow_Ui.py 2. About_Ui.py 3. UiShow.py
Below line of code is included in MainWindow_Ui.py and the module imports < from About_Ui import * >, but still I get the error "global name 'dialog' is not defined". Please suggest. Thanks!
QtCore.QObject.connect(self.menuAbout, QtCore.SIGNAL(_fromUtf8("triggered()")), dialog.setupUi(aboutDialog))

Put in your dialog init
QtGui.QDialog.__init__(self, parent)
self.ui = Ui_your_dialog_window()
self.ui.setupUi(self)
then connect your self.menuAbout to a slot that creates that dialog
Example:
QtCore.QObject.connect(self.menuAbout, QtCore.SIGNAL(_fromUtf8("triggered()")), self.createDialog)
slot:
def createDialog(self):
myDialog= your_class_dialog()
myDialog.exec_()

Related

Cant make changes to global list using a function activated through a tkinter button

I am working on a python project , a "Basketball scorecard" which uses tkinter.
my first window is where the user enters the names of players in the ballgame, I have used a simple submit button which grabs the values from the input boxes and stores it in a list, However I cannot access the list outside the func.
#Define the submit button callback function
def submit_names():
#Get the names from the entry widgets
home_names = (home_player1.get(), home_player2.get(), home_player3.get(), home_player4.get(), home_player5.get())
away_names = (away_player1.get(), away_player2.get(), away_player3.get(), away_player4.get(), away_player5.get())
#Print the team names
print(f"Home team: ",home_names)
print(f"Away team: ",away_names)
window.destroy()
#Create the button to submit the names
submit_button = Button(window, text="Submit",command = submit_names,width=20,height=2)
submit_button.grid()
submit_button.place(relx=0.45,rely=0.9)
print(home_names)
I tried initialising the list outside the func and then using 'global' keyword but it threw errors.
I tried passing already global list as arguments in the command func, it resulted in the same.
I would like to access the list globally further in the program

The second time I use a ttk button (in root) to create a toplevel window, the toplevel window cannot be destroyed

Basically, I have a button in root which creates a Toplevel. Then in Toplevel, I also have a ttk.Button, which when clicked will destroy the Toplevel. I am using .destroy(), NOT .quit() or any other wrong commands, which is evident as the first time I create the Toplevel with my root button, my Toplevel button WILL destroy the Toplevel.
However, the second time I click the root button to re-create the Toplevel (in other words, to re-create the Toplevel), the Toplevel will successfully be recreated, but the Toplevel button will not destroy the Toplevel, and I can't understand why. Here is my code (I left in all the additional widgets because when I don't include them, the destroying of the Toplevel works just fine):
from tkinter import *
from tkinter import ttk
class App():
def __init__(self,root):
root.title('My Flashcards')
root.resizable(False,False)
button_create = ttk.Button(root,text='Create New',command=self.create_new).grid(column=1,row=2)
def create_new(self):
self.create_branch = Toplevel()
self.create_branch.resizable(False,False)
self.create_branch.title('Create new flashcards')
ttk.Label(self.create_branch,text='CREATE A NEW FLASHCARD HERE:').grid(column=1,row=1,pady=(10,10),padx=(10,10))
ttk.Label(self.create_branch,text='Type the question:').grid(column=1,row=4,padx=(10,10),pady=(10,10))
self.create_question = Entry(self.create_branch,width=70)
self.create_question.grid(column=1,row=5,padx=(10,10))
ttk.Label(self.create_branch,text='Type the answer:').grid(column=1,row=6,padx=(10,10),pady=(10,10))
self.create_answer = Text(self.create_branch)
self.create_answer.grid(column=1,row=7,padx=(10,10))
self.submit_new_flashcard = ttk.Button(self.create_branch,text='Submit',command=self.submit_new_flashcard)
self.submit_new_flashcard.grid(column=1,row=8,pady=(10,10))
def submit_new_flashcard(self):
#Do some things here with self.create_answer.get() and self.create_question.get()
self.create_branch.destroy()
if __name__ == "__main__":
root = Tk()
App(root)
root.mainloop()
You have a method submit_new_flashcard. When you create the button and assign command=self.submit_new_flashcard the button is created and the command property bound to the method. Then you assign the self.submit_new_flashcard field to be the result of creating that button. When you destroy the button, the reference name is still held in the variable. So in creating the second form you create a button that tries to call the original button name as a function which doesn't do anything but raises a background error.
In short, improved naming and avoiding reuse of the same names in the same scope. eg:
self.submitButton = ttk.Button(..., command=self.submit)
would avoid the issue.

Tkinter button only works once

Tkinter button only runs a separate script once
Hello all, Im a new to python and raspberry pi and have been searching high and low on how to get a Tkinter button to run a script more than once on my raspberry pi. From research I believe it has something to do with name="main", but I cant figure out what needs to be done and why. My button runs a separate python file (called SendRF.py) in the same directory that generates an RF signal, it works the first time but then the button click does nothing else after. Any advice would be much appreciated :)
from tkinter import *
#create a window
window =Tk()
window.title("Chappers Home Automation project")
#define a function
def test_function ():
import SendRF
#create a button
B = Button(text ="Test Button 1", command=test_function)
B.pack(padx = 100, pady = 50)
window.mainloop()
No error messages appear. The button sends the RF signal when pressed the first time, but nothing happens for further button clicks.
You can't import a module multiple times. Each additional import for the same module is a NOP. You need to functionize whatever is in sendRF, and call that function in test_function.
You can check if the function is working correctly by adding a simple print statement inside your function
from tkinter import *
#create a window
window =Tk()
window.title("Chappers Home Automation project")
#define a function
def test_function ():
import SendRF
print('CHECK')
#create a button
B = Button(text ="Test Button 1", command=test_function)
B.pack(padx = 100, pady = 50)
window.mainloop()
It is working one time, cause you alredy have the SendRf function mported, you need to close it, after to import again

Is there a way to change a buttons colour when the button is made in a function?

I have made a button within a function and when the button is clicked a command is run to change the button color.
However this does not work as I get an error, but I need to create the button in the function.
It works when the button is defined outside the function and I assume the issue is that the data is forgotten after a function ends.
from tkinter import *
root = Tk()
def ColourChange(Letter):
NameButton.config(bg = "red")
def Change():
Letter = "a"
NameButton=Button(root, text = "This", command = lambda Letter = Letter:
ColourChange(Letter)
NameButton.pack()
Change()
When I click the button I would like the color of the background to change.
The actual error is
NameButton.config(bg="red") NameError: name 'NameButton' is not defined"
Set your global variable so it can be access by other function.Also move NameButton.pack() to new line after NameButton=Button(root,text="This",command=lambda Letter=Letter: ColourChange(Letter)).
from tkinter import *
root=Tk()
def ColourChange(Letter):
NameButton.config(bg="red")
def Change():
global NameButton # global variable
Letter="a"
NameButton=Button(root,text="This",command=lambda Letter=Letter: ColourChange(Letter))
NameButton.pack()
#NameButton.pack()
Change()

Tkinter display different frames

UPDATE : The problem was solved by removing the window.mainloop() in my second function.
I'm trying to make a game in Python 3.7 using tkinter.
The game begins with a menu (button-widgets in a frame). Clicking in the 'Play' button should open another menu using a different frame. This second menu should contain a 'back' button to return to the first menu.
Each menu is defined in a function. So to go from the main menu to the play menu I call the function playMenu(window) in the function used as command by the 'Play' button.
It looks like this :
def clickButtonPlay():
menuFrame.grid_remove()
playMenu(window)
menuFrame.grid()
In the play menu, the function used as 'back button' command put an end to the function by destroying its frame and using return.
So the program should get back to the clickButtonPlay() function and show the frame of the main menu back, but instead I get a tkinter error :
_tkinter.TclError: can't invoke "grid" command: application has been destroyed
But my frame menuFrame hasn't been destroyed, just un-grid!
Can anyone help me understand what's wrong with the code or find an easier way to do the same thing?
Thank you very much!
Here's a sample of how my program works:
mainMenu file :
import tkinter as tk
from PlayMenu import playMenu
window = tk.Tk()
window.grid()
def menu(window):
def clickButtonPlay():
menuFrame.grid_remove()
playMenu(window)
menuFrame.grid()
menuFrame = tk.Frame(window)
menuFrame.grid()
background = tk.Label(menuFrame, image= backgroundImage)
background.grid()
playButton = tk.Button(menuFrame, image= playButtonImage[0], command= clickButtonPlay)
playButton.place(relx= 0.5, rely= 0.15)
window.mainloop()
menu(window)
playMenu file :
class MyError(Exception):
pass
def _playMenu(window):
def clickButtonBack():
playMenuFrame.destroy()
raise MyError
playMenuFrame = tk.Frame(window)
playMenuFrame.grid()
background = tk.Label(playMenuFrame, image= backgroundImage)
background.grid()
backButton = tk.Button(playMenuFrame, image= backButtonImage[0], command= clickButtonBack)
backButton.place(relx=0.375, rely=0.8)
window.mainloop()
def playMenu(window):
try:
return _playMenu(window)
except MyError:
return
The problem (or at least a problem) is that you're calling mainloop more than once. Each time you call it, a new infinite loop is created. The new loop won't exit until the main window is destroyed. Once that happens, the previous loop will likely throw errors since the widgets it's managing no longer exist.

Resources