I've been trying to close a QDialog window that is branching off of my main window. The following have not worked for me so far:
self.close()
QDialog.close()
I tried other commands such as exit and exec_() with no luck.
The most common error I get is
[className] object has no attribute 'close'
# Creating our window
class Ui_MainWindow(object):
# Sets up GUI
def setupUi(self, MainWindow):
[GUI CODE]
# Sets text for parts of GUI
def retranslateUi(self, MainWindow):
[MORE GUI CODE]
# Function handling screencap on click and metadata for filenames
def cap_on_Click(arg1,arg2):
popup = QDialog()
popup_ui = Ui_Dialog()
popup_ui.setupUi(popup)
popup.show()
sys.exit(popup.exec_())
The above is my main window
class Ui_Dialog(object):
def setupUi(self, Dialog):
[GUI CODE]
def retranslateUi(self, Dialog):
[MORE GUI CODE]
def button_click(self, arg1):
self.close()
The second block is the dialog window code. How do I close this dialog window?
First of all, sorry for the links related to C++, but Python has the same concept.
You can try using the reject or accept or done function to close the dialog box. By doing this, you're setting the return value appropriately (Rejected, Accepted or the one you specify as the argument).
All in all, you should try calling YourDialog.done(n) to close the dialog and return n and YourDialog.accept() or YourDialog.reject() when you want it accepted/rejected.
Since a QDialog is a QWidget, and a QWidget has the close() method, I don't understand how it can not work. You should never invoke popup.exec_() though, since it will happily require a lot of your code to be reentrant without you realizing it. It is unnecessary - you already have the application event loop running and on the call stack when cap_on_Click is executing.
After popup.show(), the dialog will be visible and usable until it gets accepted or rejected by the user. Hopefully your design for the dialog connects the button box's accepted() and rejected() signals to the dialog's accept() and reject() slots. That is the default behavior of a QDialog template provided with Qt Creator and perhaps Qt Designer as well, but you should check it by going into the signal/slot editor mode while viewing the Ui file.
I guess the problem is that Ui_Dialog does not inherit QDialog, so reject(), accept() and done() is not defined. I think
class Ui_Dialog(object):
should be changed to
class Ui_Dialog(QDialog):
But I can not test it because minimal working example is not provided.
I know it's over 5months but I choose to drop this comment here, it might be of help to others tomorrow.
To be able to close or cancel an opened dialog box, using only self.close would close the entire program.
use this example:
self.dlg = QDialog(self)
self.dlg.setWindowTitle("Admin")
self.dlg.setGeometry(100,100,300,200)
btnBox = QDialogButtonBox()
btnBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
btnBox.rejected.connect(self.close1)
def close1():
self.dlg.close()
Related
Basically I have created a Dialog without buttons window as an alert box using Qt5 designer and compiled to Python using Pyuic5 which resulted into partial code as below:
class Ui_alertwindow(object):
def setupUi(self, alertwindow):
alertwindow.setObjectName("alertwindow")
alertwindow.resize(400, 300)
alertwindow.setStyleSheet("background:#222;")
# much more code
Later on, I will have to modify parts of this window which I could not using Qt5 designer, hence I created a separate class to make the changes, as below:
class alertWindowCustom(QDialog, Ui_alertwindow):
def __init__(self):
QDialog.__init__(self)
self.setupUi(self)
self.run()
def run(self):
print("Changes will be made here")
And then finally call this function in QMainWindow when a button is pressed:
def CreateAlertWindow(self):
alertWindow = alertWindowCustom()
alertWindowInput = alertWindow.exec_()
This creates a white dialog box while not responding and in the console I am getting below errors:
Changes will be made here
Unknown property justification
Unknown property justification
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
Can anyone tell me what is wrong here?
In this simple pyqt5 app, I have a QPushButton and I define a shortcut for it. I want to change its text every time it is triggered. Problem is that the shortcut works only for the first time. How can I fix it?
from PyQt5.QtWidgets import QPushButton, QMainWindow, QApplication
import sys
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.btn = QPushButton('&Connect', self)
self.btn.setShortcut('Ctrl+C')
self.btn.pressed.connect(self.btn_func)
def btn_func(self):
if self.btn.text() == '&Connect':
self.btn.setText('Dis&connect')
else:
self.btn.setText('&Connect')
def main():
app = QApplication(sys.argv)
win = window()
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
As explained in the text property documentation [emphasis mine]:
If the text contains an ampersand character ('&'), a shortcut is automatically created for it. [...] Any previous shortcut will be overwritten or cleared if no shortcut is defined by the text
I know that the above might seem confusing, as it seems that the shortcut is overwritten or cleared only if no shortcut is defined by the text, consider it like this:
Any previous shortcut will be overwritten, or it is cleared if no shortcut is defined by the text
The solution is to always reset the shortcut after setting the new text:
def btn_func(self):
if self.btn.text() == '&Connect':
self.btn.setText('Dis&connect')
else:
self.btn.setText('&Connect')
self.btn.setShortcut('Ctrl+C')
Note that using the button's text for comparison is considered bad practice, for three reasons:
the text of a button could (should) be localized;
you could easily forget to correctly update all the & texts, making the function behave in the wrong way;
some QStyles override existing mnemonics and change them by themselves, which also causes the text to change without any warning;
The most preferred way to achieve what you want would be to use an internal flag for the current state, and also a QAction with its own shortcut.
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.btn = QPushButton('&Connect', self)
self.btn.clicked.connect(self.btn_func)
self.connectAction = QAction('Toggle connection', self)
self.connectAction.setShortcut('Ctrl+c')
self.connectAction.triggered.connect(self.btn.animateClick)
self.addAction(self.connectAction)
self.connected = False
def btn_func(self):
self.connected = not self.connected
if self.connected:
self.btn.setText('Dis&connect')
else:
self.btn.setText('&Connect')
Also note that:
you should not use the pressed() signal, as it's standard convention to consider a button clicked when the user presses and releases the mouse button while inside the button area (so that the pressed action could be "undone" by moving the mouse away if the mouse button was pressed by mistake on the button); use the clicked() signal instead;
I changed the class name using a capitalized Window, as classes should always use capitalized names and lower cased names should only be used for functions and variables;
I used the animateClick slot to show that the button was clicked (as a visual feedback is always preferable), but you can directly connect to the function: self.connectAction.triggered.connect(self.btn_func);
#^^^^class stuff here for setting UI^^^^
# connecting combobox to slot/function get_baffle_number
self.baffle_number_combobox.currentIndexChanged.connect(get_baffle_number)
# connecting PushButton action "clicked" to function on_click
self.pushButton.clicked.connect(on_click)
#connecting lineEdit to slot/function get_baffle_cost
self.baffle_cost_lineEdit.textEdited.connect(get_baffle_cost)
#pyqtSlot()
def get_baffle_cost(text):
baffle_cost = text
return baffle_cost
def get_baffle_number(text):
#add 1 to the index returned by comboBox to get the number desired by user
baffle_number = text + 1
return baffle_number
def calc_baffle_cost():
test_total = (get_baffle_cost() * get_baffle_number())
return test_total
#pyqtSlot()
def on_click(self):
baffle_cost = calc_baffle_cost()
print(baffle_cost)
After I connect that lineEdit to the function via the pyqtSlot(), it seems to get the value, but immediately dumps it if I attempt to use baffle_cost from another function. I watch it in PyCharm during debugging and it holds it just as long as the lineEdit has focus it seems. Pressing the pushButton is right when it loses its value.
I cannot use the returned baffle_cost anywhere from get_baffle_cost.
Am I missing something? The furthest I've got is that attempting to simply print calc_baffle_cost() and a hexadecimal is printed. I am assuming that is a memory location, but can't be sure. (new to Python)
Sorry if this isn't enough information. I am simply attempting to take baffle_cost from a lineEdit and multiplying that by a value taken from a comboBox.
It seems my problem was two-fold, or more.
I was not correctly scoping my functions and not utilizing the right namespaces. (Sorry if this terminology is incorrect. I am new to Python and PyQt.)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# sizing of widgets
def retranslateUi(self, MainWindow):
# UI stuff here QlineEdits, etc.
self.baffle_cost_lineEdit.editingFinished.connect(self.get_baffle_cost)
def get_baffle_cost(self):
baffle_cost = self.baffle_cost_lineEdit.text()
return baffle_cost
This needed to be in the same scope(indentation) as my retranslateUi() function in my Ui_MainWindow Class like above.
I think if I had better structured my project this wouldn't have been an issue. I have definitely learned my lesson about having it all in one script. (program.py)
The other issue(s) I encountered is that the PyQt function text() called from a QlineEdit returns a QString and not a str. I simply needed to cast it to a string.
I was losing the value because the function get_baffle_cost wasn't properly scoped with the baffle_cost_lineEdit
I need to show a QWidget, which code is written in another module, when a certain button is pressed. To accomplish this, I wrote this code:
class Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
#A lot of stuff in here
#The button is connected to the method called Serial_connection
self.connect(self.btn_selection_tool3, SIGNAL("clicked()"), self.Serial_connection)
def Serial_connection(self):
LiveData.LiveData(self).show()
Doing this, I open a QWidget and it works fine. But, when I want to close this QWidget, I can not do it. This is the code of the QWidget:
class LiveData(QWidget):
def __init__(self,parent = None):
super(QWidget, self).__init__(parent)
#Another stuff in here
#I create a "close" button connected to another method
self.connect(self.closeBtn, QtCore.SIGNAL("clicked()"), self.StopAndClose)
def StopAndClose(self):
print "Closing window"
self.close() #HERE IS WHERE I HAVE THE PROBLEM
I´ve tried several options like: self.close(), self.accept() or even sys.exit(1). The problem with the latter sys.exit(1) is that it closes the QWidget and the QMainWindow. So, how can I close this QWidget only? Hope you can help me.
You probably want your QWidget to be a QDialog. If it's a temporary modal widget, you should be calling the dialog like this
dialog = LiveData.LiveData(self)
dialog.exec_()
If you just want to show the dialog at the same time as your main window, and users are meant to interact with both (though from a design perspective, this doesn't sound like a great idea), you can continue to use .show()
Also, you should use the new-style signal/slot syntax. The old syntax hasn't been used for many years.
self.closeButton.clicked.connect(self.StopAndClose)
Though, for a QDialog you can just do
self.closeButton.clicked.connect(self.accept)
I am following a tutorial on zetcode.com and I seem to have run into trouble. This code is supposed to be very straight forward and so I pasted it below.
This is all a part of an instance of the QWidget class (the base class of all UI objects). I have realized that this is one of the fundamental classes I need to understand in order to write a GUI, and I am simply puzzled on what is going on in the program.
The program is simple enough: PyQt opens a window, you are then able to exit out of that window via the 'x' button. And upon clicking the 'x' a message inquiring "Are you sure to quit?" allows you to continue to exit or cancel.
import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Message box')
self.show()
def closeEvent(self, event):
reply = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
event.accept()
else:
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
So what doesn't make sense?
The closeEvent() method that QWidget calls. The method seemingly accepts a variable "event" that is never initialized but somehow passed into the function. The methods "event.accept()" and "event.ignore()" are then called on an object that previously was never initialized.
I am a noob in PyQt/Qt and maybe it's a misunderstanding of Python too. Here is documentation on the function http://doc.qt.io/qt-5/qwidget.html#closeEvent, that may clarify things.
The method seemingly accepts a variable "event" that is never
initialized but somehow passed into the function.
That is how a method works. Consider this simple function:
def print_a_word(word):
print(word)
It takes an argument word, that we did not initialized. When you call the function, then you need to define what word is:
word = "unicorn"
print_a_word(word)
If you look at the doc in more details, you'll see that event is a QCloseEvent, and it is "initialized" somewhere else in QWidget
The QCloseEvent class contains parameters that describe a close event.
Close events are sent to widgets that the user wants to close, usually
by choosing "Close" from the window menu, or by clicking the X title
bar button. They are also sent when you call QWidget::close() to close
a widget programmatically.