I know that using multiple tk.Tk() in a single app is a bad practice and if I want to create multiple windows I should use tk.Toplevel() instead. But what if I destroy the previous tk.Tk() instance and then call other instance? Technically the first endless loop has ended, so I should be fine, right?
For example, I've written an application that starts off with login screen and then I move to, let's say, "mainwindow" and this is the screen the user will be watching the most often. Login screen is only a one-time thing when starting the app and user will not return to it again (unless he closes the "mainwindow" and runs the app again). Would it be more logical to call tk.Tk() on login window and after choosing "login" button destroy login window and then call "mainwindow" as tk.Tk()?
Technically, I could just withdraw the login window and create all windows as children of the login window using tk.Toplevel (and the flow would be loginwindow -> mainwindow -> otherwindows), but I wonder - is keeping windows whitdrawn when you won't need them again a good practice?
You can actually create as many windows as you want.
This code right here does perfectly work for me. You just create several objects from one class.
from tkinter import *
windows = []
for x in range(5):
windows.append(Tk())
Button(windows[-1], text='Destroy this window', command=windows[-1].destroy).pack()
windows[-1].mainloop()
So, you can destroy one window, then create another, or even make them work at the same time.
Related
I have an application flow which looks like this. At startup a MainWindow is shown and asks the user to choose a project or create a new one. After a project is created or chosen from the list, I want to close this MainWindow and open another MainWindow.
In my main.py the code looks like this:
app = QApplication([])
ui_project_list_view = ProjectListView()
ui_project_list_view.show()
app.exec_()
Now I want to close the first main window (ui_project_list_view) and open the other main window (ui_project_view). This code is called from within ui_project_list_view.
ui_project_view = ProjectView()
ui_project_view.show()
main_view.close()
No matter in which order I show or close, the application quits. How should I design my "window-flow" ?
Thanks for your help.
If you open most programs like Word or Excel- or QtDesigner for example- you'll see a blank main window initialize, and then a popup will appear asking you to choose your project.
If you wanted to apply this to your code, the ProjectView should be the main window and the ProjectListView would be the popup. The ProjectView would call this after initializing, in a setup function perhaps. After ProjectListView finishes, then ProjectView would just need to update the screen with the information that ProjectListView has.
I'm having a trouble while implementing a log-in system in an interface I'm creating:
I want it to have two type of user: admin and user, so depending on what you choose you input your credentials and then if they're correct the system opens either the admin interface or the user interface.
My problem is that given the knowledge I have right now, I have to have a "mother window" while executing tkinter which is the first windows that opens when you run the program, in this case that mother window would be the log-in window, the thing is that if I close that log-in window once the user inputs his/her credentials, then the whole program doesn't work.
Is there a solution for this?
The simplest solution is to create two functions or two classes, one for the login window and one for the main window. Have these functions or classes return a single frame that contains everything needed for that part of the code.
Then, call the first function or class to login in, then destroy it and call the second function or class. When you destroy a frame, all of its children are also automatically destroyed.
Let me quickly explain the background to this. I'm developing a custom menu system inside a 3D application called Softimage XSI. It has a PyQt application object created already and ProcessEvents is being called a certain number of times every second so that PyQt applications can exist in a non-modal state within XSI.
To implement the menu, I've got a webpage embedded in a toolbar which is calling a plugin for XSI that I've written to show a PyQt menu. This all works fine (albeit, slightly contrived!).
The issue is that when I show the menu, it won't disappear when I click away from it. If I move the mouse over the menu, and then click away from it, it will disappear. It's only when it first pops up.
I've tried everything I can think of. Here's a list:
Using QtGui.qApp.installEventFilter(menu) to try and catch the mousepressed signal. It never gets triggered. I suspect the application itself isn't receiving the click.
Using menu.raise_() makes no difference
Neither does QtGui.qApp.setActiveWindow(menu)
Or menu.setFocus()
I've also tried:
event = QtGui.QMouseEvent(QtCore.QEvent.MouseMove, pos, QtCore.Qt.NoButton, QtCore.Qt.NoButton, QtCore.Qt.NoModifier)
QtGui.qApp.sendEvent(menu, event)
I had a go writing my own QEventLoop, but it just crashed XSI. I suspect trying to run a modal loop inside the other one probably isn't a legal thing to do. Either that, or I really don't know what I'm doing (equally probable)
The only thing I have partial success with is using grabMouse(). This is what makes the menu close if I click away from the menu (only after the mouse has passed over the menu once), but I have to call it a couple of times for it to "stick".
So this is my code at the moment:
class MyMenu (QtGui.QMenu):
def __init__(self, parent = None):
QtGui.QMenu.__init__(self, parent)
self.grabbed=2
def getMouse(self):
if self.grabbed>0:
self.grabMouse()
self.grabbed-=1
def paintEvent(self, event):
QtGui.QMenu.paintEvent(self, event)
self.getMouse()
def hideEvent(self, event):
self.releaseMouse()
def ShowMenu():
menu = MyMenu()
menu.addAction("A")
menu.addAction("B")
menu.addAction("C")
submenu = MyMenu()
submenu.addAction("D")
submenu.addAction("E")
submenu.addAction("F")
menu.addMenu(submenu)
menu.setTearOffEnabled(True)
menu.setStyleSheet("font: 8pt \"Sans Serif\";")
submenu.setStyleSheet("font: 8pt \"Sans Serif\";")
submenu.setTitle("Window")
submenu.setTearOffEnabled(True)
pos = QtGui.QCursor.pos()
pos.setX(105)
menu.popup(pos)
#Prevent garbage collection
QtGui.XSIMenu=menu
QtGui.XSISubMenu=submenu
#Desperate acts!
menu.raise_()
QtGui.qApp.setActiveWindow(menu)
menu.setFocus()
Any thoughts or random suggestions would be very gratefully received as this is driving me nuts! Don't be afraid to suggest modifications to stuff I've already tried, as I'm relatively new to PyQt and I may well have missed something.
Many thanks,
Andy
Just before calling popup with self.trayMenu.popup(QtGui.QCursor.pos()), call self.trayMenu.activateWindow(). Putting activateWindow before popup makes the left-click menu work the same as the right-click menu and it goes away when you click elsewhere. :)
I've created an application with lwuit on java-me, however, each time the user receives a phone call the applications is minimized and when the user restores it, the first Form is shown again (a splash form). How can I avoid the application from starting again?
Try overriding onHideNotify() and onShowNotify(), In hideNotify, store the last shown form to a variable and display that in onShowNotify()
I load a single instance of a window on php-gtk, I have a button named "Cancel" that hide(); the window, so when the window is needed again I just show();.
But when I click on the close button instead of the cancel button the window is destroyed. Even when I redirect the event (I'm not sure if i'm doing it right) it calls the first(just hide() function) and then the destroy method.
Any idea?
PD: I wouldn't want to destroy and recreate the windows because of php's crappy garbage collector and to be able to maintain previous data without having to refill the whole window(after all is supposed to be a desktop app).
Following the advice here: delete-event.
I changed my code to return TRUE:
function on_multipleCancelButton_activate()
{
global $GladeMultiple;
$MultipleWindow = $GladeMultiple->get_widget('multipleWindow');
$MultipleWindow->hide();
return TRUE;
}
On the GTK designer I linked the delete-event to this function.