QDialog keeps blocking mouse input even after close - python

PyQt4/5 on OSX El Capitan
I have a QMessageBox/QDialog which I want to be modal and want to block input from other GUI items while a process is running. The QDialog should provide the user the option to cancel the said process, but not allow him or her to do anything else with the GUI in the meantime.
Once the process is finished, it should close the QDialog and enable input to the main application again. Because things should happen in the background while the dialog is shown, I am not using exec_() to display the dialog.
Here is a simple example of my code:
self.openingDialog = QtWidgets.QMessageBox(self.main_window)
self.openingDialog.setText(_(u"Opening experiment. Please wait"))
self.openingDialog.setStandardButtons(QtWidgets.QMessageBox.Cancel)
self.openingDialog.reject.connect(<some_function>)
self.openingDialog.show()
self.openingDialog.raise_()
... [Perform process] ...
self.openingDialog.done(0)
self.openingDialog.close()
self.openingDialog.deleteLater()
Everything works nicely in the sense that the dialog box is shown, and that no interaction is possible with other GUI elements while it is displayed. However, when has process is finished, the dialog box is automatically closed but it is still not possible to interact with other GUI elements afterwards. The GUI does not respond to mouse clicks, menu items are not accessible, and you can't even click the close button, so the application needs to be Force Quit.
What am I doing wrong in automatically closing the QDialog?

Ok, I have found sort of a workaround, although I don't think it is an elegant solution.
If I set the window modality to 'window modal' instead of 'application modal' by using:
self.openingDialog.setWindowModality(QtCore.Qt.WindowModal)
then the application regains focus and accessibility after the dialog has been closed by the program.
Still this doesn't solve the problem when the dialog is an application modal, but for now this serves my needs.

Related

Tkinter: What's the difference between grab and focus?

In tkinter I am creating a Toplevel widget to prompt the user with "Are you sure you want to exit?" every time they try to exit my application. While this is happening, I want the Toplevel widget to have full focus of my application and the user to be unable to click anything on the root window, if possible.
While trying to figure out to do this, I discovered grabs and the ability to set the focus of the application. What is the difference between these two things?
Thanks in advance.
Focus means that your window will receive all keyboard events until some other window gets the focus. A grab tells the window manager that your window should have the focus until you explicitly tell it that it is allowed to take it away (ungrab).

Selenium::Python::Pop Up Window

I am trying to automate some basic web browser manipulation. As part of this sequence there is a popup window that must be dealt with. Once the python code the causes the popup window to appear happens, no other code past that point will run until I manually close that window. Then all remaining code runs fine.
I've try this below to try to deal with handling the popup but to no avail:
for handle in browser.window_handles:
print "Handle = ",handle
browswer.switch_to_window(handle);
elem=browser.find_element_by_tag_name("title")
print elem.get_attrbitue("value")
I cannot even get a basic 'print' command to execute until I close the popup window. Is there a need to set some type of event handler BEFORE the code is called that brings the popup menu?
Thanks for any suggestions.

Is wait_window() required for creating a modal dialog in Python Tkinter?

I try to create a modal dialog using Python Tkinter. I found no difference between using and not using wait_window().
import tkinter as tk
def button_click():
dlg = tk.Toplevel(master=window)
tk.Button(dlg, text="Dismiss", command=dlg.destroy).pack()
dlg.transient(window) # only one window in the task bar
dlg.grab_set() # modal
#window.wait_window(dlg) # why?
window = tk.Tk()
tk.Button(window, text="Click Me", command=button_click).pack()
window.mainloop()
I've seen some examples in that use wait_window() for creating a modal dialog. So I'm not sure whether the function is required for creating a modal dialog.
I'm using Python 3.5.
Strictly speaking, no, wait_window() is not required to make a modal dialog box. What makes a dialog modal is the grab that you put on the window.
Often, however, once the window is destroyed you may need to run some other code. You can use wait_window() for this purpose, as it will wait for the window to be destroyed before continuing. You can then have code after that, such as a return statement, or some cleanup code. In your case there's nothing to do, so you don't need to call wait_window.
running your code using window.wait_window(dlg) won't change anything as dlg.grab_set() already creates a modal dialog. this does only mean that you cannot close window while dlg is still alive. you cannot close window as the modal dialog grabs all mouse events from window and redirects them to null.
If you want to create a modal dialog without grab_set(), you would need to bind all mouse events to one handler and then decide if they should be allowed or dismissed and use wait_window.
As a modal dialog is defined by "is anything outside the dialog and in my application available to be clicked" == False , you already have a modal dialog only using grab_set().
If your application shall not be able to programatically close window, you would need wait_window() as well.
Hope I made everything clear.

Make a window appear on top of another, block access to other windows until button clicked

Python 2.7, PyQt4.8.5
I want to have a main app window and then a second pop up window to display com port settings. This window should always be on top of the parent window until either the ok or the cancel button is clicked; closing the child window. (sort of like a required answer i.e. cant process until you choose the settings from the child window)
Is there a Python Qt command to do this?
Apologies if this has been asked/answered before, my search returned nothing useful.
You want a modal dialog. For example:
dialog = QInputDialog()
dialog.exec_()
You can either implement your own dialog widget (by subclassing QDialog) or use one of the several available.

GtkAboutDialog Close Button Bug

I use GtkAboutDialog and everything works fine except the close button of this widget. All other buttons works fine, I don't know how but all buttons have default callbacks and they create and destroy the windows.
But the "Close" button of GtkAboutDialog widget does not work. I can not even see it's widget. So, can I access it?
[CLARIFICATION] What you're looking at is gtk.AboutDialog — popup window displaying information about an application (new in PyGTK 2.6). This window contains the 'close' button widget which is contained in a GtkHButtonBox widget. The GtkHButtonBox widget is the highest level widget I am able to access for some. Any ideas on how to get to the "close" button and connect a handler for a callback signal?
You don't conenct signals in the same way for a dialog as you do for a window. I made the same mistake when learning PyGTK.
The most basic form of a dialog is you display and run the dialog with:
aboutdialog.run()
Often you will then immediately call:
aboutdialog.destroy()
The .run() line is a loop, which runs until something happens within the dialog.
There is a working example here.
The gtk.AboutDialog is just a gtk.Dialog, and you handle responses from it in the same way. Instead of connecting to the clicked signal of the buttons, the dialog code handles that for you and returns a reponse from your run() call. You can check the value of the response returned to figure out what button was clicked.
If you're trying to override some behaviour instead, you can connect to the response signal of gtk.Dialog.
This is an old question, but since it's one of the first hits from google, I thought I'd throw in the solution that I found. You need an event handler to show the about dialog and one to close it. The first will likely be connected to your help->about menuitem's activate signal. The latter should be connected to the response signal of the about dialog. The two handlers will look something like this:
def on_menuitemHelpAbout_activate(self, *args):
self.builder.get_object('aboutdialog').show()
def on_aboutdialog_response(self, *args):
self.builder.get_object('aboutdialog').hide()
In the example above, I'm using the GtkBuilder to find my about dialog because I've constructed the interface with glade. Note that I'm using .show() over .run() because I don't see the sense in pausing program execution until the dialog is closed. Finally, the response handler can be made to take whatever action depending upon the response, but I'm ignoring it here.

Categories

Resources