This question already has answers here:
How to create an independent non-modal dialog
(1 answer)
PyQt window closes immediately after opening
(3 answers)
Closed 10 months ago.
I have QDialog designed by PyQt5 designer, I basically need to execute this dialog box from QMainWindow app in a separate process. Although I don't get any errors with below code but the Dialog box never show up. Can anyone tell me what am I doing wrong?
Main Window App on button click:
def alertWindow(self, alertInfo):
p = Process(name="alertwindow", target=alertWindowCustom, args=(alertInfo,))
Dialog Box Class:
class alertWindowCustom(QDialog, Ui_alertwindow):
def __init__(self, alertwindowData):
QDialog.__init__(self)
self.setupUi(self)
self.alertwindowData = alertwindowData
self.run()
self.exec_()
def run(self):
print("brah", self.alertwindowData)
If I just call alertWindowCustom class as a = alertWindowCustom(alertInfo) without a process, the dialog box is created but the MainWindow become unresponsive.
If using QThread is a better option to use over multiprocessing, I would rather use that.
Credit to #musicamante and #ekhumoro.
You don't have to use a thread or a process to create a dialog box that does not block main thread.
To keep your MainWindow responsive while dialog box is open, avoid using exec_() but rather use show(). This will create a non-modeled dialog box and store the dialog box in memory which you will always have to keep a reference of. To do that make a reference of it in your MainWindow as below:
self.alertwindowclass = alertWindowCustom(alertInfo)
Make sure to use self, otherwise as soon as the function is done, dialog box data will be moved to python recycle bin which will destroy you dialog box.
My new full code is below:
class mainWindow(QMainWindow):
# Below function is called to create the dialog box
def alertWindow(self, alertInfo):
self.alertwindowclass = alertWindowCustom(alertInfo)
class alertWindowCustom(QDialog, Ui_alertwindow):
def __init__(self, alertwindowData):
QDialog.__init__(self)
self.setupUi(self)
self.alertwindowData = alertwindowData
self.run()
self.show()
def run(self):
print("brah", self.alertwindowData)
I had to read many forms to gather this information. I wrote an article here if you want to learn more about it. Hope that help people in the future.
Related
My two files AAA.py and BBB.py have a QMainWindow and a QWidget respectively. QMainWindow has a button showing QWidget. QWidget has a button and let's say its function is clearing the lineEdit on the widget when it's clicked. These files work fine when directly connect lineEdit to be cleared but I want it to be done when I make a function and call it inside .connect().
I tried to specify the problem and found that UDF is the thing. What I really want to do is save the text in lineEdit into SQL. Clear() is just an example, so please don't say not to use udf.
These files work fine when I implement the clearing like:
self.pushButton.clicked.connect(self.lineEdit.clear)
clear() is just about clearing the lineEdit.
self.pushButton.clicked.connect(self.clear)
Although it also works in BBB.py, but it doesn't when I open the QWidget through AAA.py.
Can you guess what the problem is?
I am trying to make a PyQt5 application, I am trying to get that filename out of a QFileDialog. However, when trying to actually get the filename after the dialog was accepted, another QFileDialog pops out. I do not know how to solve this, here is the code snippet that is blocking me.
from PyQt5 import QtWidgets as qtw
loadfile = qtw.QFileDialog()
if loadfile.exec_() != 1:
pass
else:
path = loadfile.getOpenFileName(self, 'Open a file', '', 'All Files (*.*)')
As far as I am aware, I am just checking if the user pressed the cancel or the close button here. If not, I call the getOpenFileName in the loadfile object. But this opens the QFileDialog again.
I have an application with multiple win forms. I have noticed is that if the user has multiple screen displays and changes the application to one screen, the other forms that are called by other buttons, will open in the main display and not where my main application or form is.
How can I change this?
You can use the Form.CenterToParent Method on your Forms, they will then open up centered on your the creating Form, Or you can use the Screen Class to get the Bounds of the Display that your Main application is running on, then pass it to your created forms.
Edit:
On second thought assigning the Owner might just be enough, I don't have a dual monitor computer booted up at this time to test though
Dim frm As Form1 = New Form1()
frm.Owner = Me
frm.CenterToParent()
frm.Show()
Edit
Just had a chance to check it out. It was as I thought assigning the Owner to the new Form or using the Form.Show(IWin32Window) will open the new Form on the same screen as the originating Form.
frm.Show(Me)
Looks like the CenterToParent property is protected now.
According to the MSDN link
Do not call the CenterToParent method directly from your code. Instead, set the StartPosition property to CenterParent.
If the form or dialog is top-level, then CenterToParent centers the form with respect to the screen or desktop
I have a form in a vb.net windows form application called PolicyRefreshStatus.vb that has a ProgressBar control on it. From the main form called EditPolicy.vb I need to show PolicyRefreshStatus.vb over top of EditPolicy.vb - but the way things are wired I'm controlling the the ProgressBar and it's steps from logic inside EditPolicy.vb.
If I display the PolicyRefreshStatus.vb bar using the .show() method things work fine. The problem is if the user clicks back on the main form then PolicyRefreshStatus.vb losses focus. If I show PolicyRefreshStatus.vb as a modal form using .ShowDialog() then execution halts in EditPolicy.vb after the .ShowDialog() statement.
so for example in the code:
mPolicyRefreshStatus = New PolicyRefreshStatus
mPolicyRefreshStatus.pbMax = mPolicy.ClaimsUpdateMax
mPolicyRefreshStatus.ShowDialog()
mPolicy.UpdateFromFIS()
The line mPolicy.UpdateFromFIS() never executes because it's waiting for the PolicyRefreshStatus form to close.
How can I show PolicyRefreshStatus in a modal form but let execution continue in EditPolicy.vb?
You've got a couple of related options.
This first is to pass the unit of work to the progress bar in the form of a delegate or a class implementing an Interface. Something like this (not checked for correctness, just a rough example):
mPolicyRefreshStatus = New PolicyRefreshStatus
mPolicyRefreshStatus.pbMax = mPolicy.ClaimsUpdateMax
mPolicyRefreshStatus.UnitOfWork = AddressOf(mPolicy.UpdateFromFIS())
mPolicyRefreshStatus.ShowDialog()
Then within the progress form you can call back to the routine that actually does the work.
Another approach is to define events on your ProgressForm and then the owning/launching object can handle those events to do the work in. With this option you can create a fairly detailed set of events to be able to handle incremental work or cancels, but the concept is the same, youu are calling back from the progress form into launcher to perform the actual business logic.
You cannot show the form modally and let your routine continue. You must show the form Non-modally and then do your other stuff, closing the form when you've finished. Maybe a loop until the task has finished?
Using Show() with a parent form parameter will give you better usability. More like a tool window.
I'm using glade and pygtk and I have a window with a treeview with a button that opens a dialog that creates a new entry for the treeview. I want to update the treeview in the main window when the dialog is destroyed but I can't see a simple way to do this.
--Edit--
Found the answer, I just needed to connect the windows destroy signal
(dialog).window.connect('destroy', self.foo)
The correct approach is to handle the response of the dialog in the main window:
def on_menu_item_activated(self, widget, data=None):
dialog = FunkyDialog()
response = dialog.run()
if response == gtk.RESPONSE_OK:
// update treeview
Perhaps a better way of doing this would be to use the Observer design pattern. When the user presses Ok, you save your data. This notifies the treeview that a change has been made, which causes it to reload.