I hope I have a simple question here. I have created a very large GUI with QT Designer and a subwindow for the MDI area. I have used pyuic5 to convert it from a .ui file to a .py file. I have written a function to open that subwindow when a button is pressed. The first time I push the button it works fine. The problem I'm having is the second time the button is pushed it just displays a blank subwindow within the MDI area. How do I get it to display correctly every time the button is pressed. I will attach the code for how I launch the subwindow below. Any advice would be very appreciated. Thank you for your time and your help
Code that is called when button is clicked
def windowaction(self):
sub = QtWidgets.QMdiSubWindow()
sub.setWidget(self.Load_Input)
sub.setObjectName("Load_Input_window")
sub.setWindowTitle("Load Input")
self.mdiArea.addSubWindow(sub)
sub.show()
First time clicking the button
Second time clicking the button
The problem arises from adding the same widget object to different QMdiSubWindow, you must create a new object and add it to the new QMdiSubWindow.
def windowaction(self):
sub = QtWidgets.QMdiSubWindow()
Load_Input = LoadInput()
sub.setWidget(Load_Input)
sub.setObjectName("Load_Input_window")
sub.setWindowTitle("Load Input")
self.mdiArea.addSubWindow(sub)
sub.show()
Related
I created a button and defined it a messagebox.showinfo() on successfully running and when the OK button is pressed it takes me to the first (Main) Page rather than staying on the current window where the button is situated. Is there a solution for this issue?
Code:
#Defining Export Button
def export(result):
with open ('students.csv', 'a', newline="") as f:
w = csv.writer(f, dialect='excel')
for record in result:
w.writerow(record)
messagebox.showinfo("Success!","Record Exported Successfully")
gate.mainloop()
Add a parent argument to your messagebox, like:
messagebox.showinfo("Success!","Record Exported Successfully",parent=gate)
This will direct it to show the message box with respect to that window. And gate.mainloop() is not necessary as long as it's a Toplevel. And if the window where your button is situated is not gate then change the parent argument to that windows name you want it to show message box on.
I work with Python 3.5 and TKinter.
I defined a label and file dialog that updates this label.
A button is responsible to launch this dialog.
self.sel_folder_val = the label that will be updated.
The code:
self.sel_folder_val['text']=filedialog.askdirectory()
After pressing the button in order to launch this dialog, the button stays pressed. Any dialog that a button is responsible to open cause the button to stay low (pressed) after closing this dialog.
I have tried this also with no help...:
self.select_folder_btn.config(relief=RAISED)
Code example:
self.select_folder_btn = Button(self.top)
self.select_folder_btn.place(relx=0.07, rely=0.57, height=34, width=187)
self.select_folder_btn.configure(activebackground="#d9d9d9")
self.select_folder_btn.configure(activeforeground="#000000")
self.select_folder_btn.configure(background="#d9d9d9")
self.select_folder_btn.configure(disabledforeground="#a3a3a3")
self.select_folder_btn.configure(font=self.font3)
self.select_folder_btn.configure(foreground="#000000")
self.select_folder_btn.configure(highlightbackground="#d9d9d9")
self.select_folder_btn.configure(highlightcolor="black")
self.select_folder_btn.configure(pady="0")
self.select_folder_btn.configure(text='''Select destination folder''')
self.select_folder_btn.bind('<Button-1>',self.update_folder_value)
def update_folder_value(self,event):
self.sel_folder_val['text']=filedialog.askdirectory()
return
After executing update_folder_value() function, self.select_folder_btn stays down.
I used the command:
self.select_folder_btn.configure(command=self.update_folder_value)
Instead of bind:
self.select_folder_btn.bind('<Button-1>',self.update_folder_value)
It solved my problem.
Thanks
First for future reference this is a minimal working example:
from Tkinter import *
import tkFileDialog as filedialog
class app:
def __init__(self):
self.top = Tk()
self.select_folder_btn = Button(self.top)
self.select_folder_btn.place(relx=0.07, rely=0.57, height=34, width=187)
self.select_folder_btn.configure(activebackground="#d9d9d9")
self.select_folder_btn.configure(activeforeground="#000000")
self.select_folder_btn.configure(background="#d9d9d9")
self.select_folder_btn.configure(disabledforeground="#a3a3a3")
#self.select_folder_btn.configure(font=self.font3)
self.select_folder_btn.configure(foreground="#000000")
self.select_folder_btn.configure(highlightbackground="#d9d9d9")
self.select_folder_btn.configure(highlightcolor="black")
self.select_folder_btn.configure(pady="0")
self.select_folder_btn.configure(text='''Select destination folder''')
self.select_folder_btn.configure(command=self.update_folder_value)
self.sel_folder_val = {}
self.top.mainloop()
def update_folder_value(self):
self.sel_folder_val['text']=filedialog.askdirectory()
self.top.update_idletasks()
app()
and even that's not minimal. Second your problem is hard to find since this isn't minimal- you're doing something really weird - binding the button to a click. You're overriding the built-in binding, and apparently it still affects the state of the button on press, but not going back. What you wanted is:
self.select_folder_btn.configure(command=self.update_folder_value)
instead of your:
self.select_folder_btn.bind('<Button-1>',self.update_folder_value)
You could also define that in the Button command. What you did is bypassed the button mechanism, so apparently only half of it is executed, and the relief is not raised. Note you have to remove the event parameter your method accepts.
I am new to PyQt4 and after several searches I have not found info on the issue I am seeing in my GUI.
The issue is that when a user clicks on getSingleItems button, the function runs the same amount of times that the user has clicked getAllItems. An example is if the user clicks getAllItems to populate the items field, and then they click on getSingleItem, getitems runs once and they will get the result printed once per expectation. But if the user selects another item from list and clicks on getAllItems again, then on getSingleItem, the results is that getitem runs 2x and therefore prints 2x. This increments with each run through so clicking getAllItems 4x, even without changing selection, then clicking getitem will run 4x with a single click on getSingleItem. Only way to refresh it is to close the GUI and reopen. Any help is appreciated.
class UpdateItem(QDialog, updateitem_ui.Ui_updateitem):
def __init__(self):
QDialog.__init__(self)
self.setupUi(self)
tests = ['Test1', 'Test2', 'Test3']
self.list.addItems(tests)
self.exit.clicked.connect(self.close)
self.setFocus()
self.getAllItems.clicked.connect(self.getitems)
def getitems(self):
self.items.clear()
self.items.addItems(self.list.currentText())
self.getSingleItem.clicked.connect(self.getitem)
def getitem(self):
self.item_id = self.items.currentText()
print(self.item_id)
app = QApplication(sys.argv)
gui = UpdateItem()
gui.show()
app.exec_()
Apparently you are are adding new connection to getSingleItem.clicked in each run of getitems,
so the clicked signal gets connected multiple times to the same slot,
which causes the behaviour you observe.
Moving the line
self.getSingleItem.clicked.connect(self.getitem)
from getitems to __init__ should fix the issue, I guess.
I am making a box that is similar to the tkMessageBox. There are two simple behaviors that I want to the box to have. First I want the button to be selected automatically when the window opens, and second I want to be able to press enter to push the button. Sounds simple and I realize that I could use the tkinterMessageBox to do this same thing, but this is a stepping stone, and I would like to know how to do this in the future for other things.
The current behavior of the window below is that it opens, and if I press tab it will select the button, but then i can only press the button with the mouse. Again the desired functionality is to have the button selected right away and be able to press the button with the enter key.
import Tkinter, tkMessageBox
from Tkinter import *
def closewindow():
Messagebox.destroy()
Messagebox=Tk()
l3=Label( Messagebox, text="This is your preview! Align camera then press ESC")
b3=Button(Messagebox, text="Okay", command=closewindow)
l3.grid(row=1,column=1)
b3.grid(row=2,column=1)
Messagebox.mainloop()
You can actually do this with just two lines of code:
b3.bind('<Return>', lambda _: closewindow())
b3.focus_set()
The first binds the button to the Enter key and the second sets the application's focus on the button.
Note that I had to use a lambda with the binding to handle the event object that will be sent to the callback. You could however change the definition of closewindow to handle this:
def closewindow(event=None):
Messagebox.destroy()
Now you can just do:
b3.bind('<Return>', closewindow)
For more information on bindings in Tkinter, see Events and Bindings over on Effbot.
It's my first time trying out Python's GUI and I've decided to go with Tkinter. I have a function in my script which would convert all .txt files in a folder to .xml files. But I would like to create a GUI button which would run my function only if I were to click the button. If I don't click the button, then the files would not be converted at all. How should I do this?
Use the command option of a Button:
from Tkinter import Tk, Button
root = Tk()
def func():
'''Place code to convert files in here'''
print "Button has been pushed"
Button(text="Push me", command=func).grid()
root.mainloop()
func will only run when the button is pressed.