How to create Dialog without buttons window in PyQt5 - python

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?

Related

Multiple QRadioButton error

I'm using PyQt5 to create a program. I created 3 Radio Buttons, but when I check the first button and check the second button after that. The program will run both of the functions which are connected to these buttons. How I can make it only run the function which is connected to that button. Thanks.
def __init__(self):
super(Program, self).__init__()
self.ui = Ui_APIManager()
self.ui.setupUi(self)
self.show()
self.ui.add_btn.toggled.connect(self.start)
self.ui.check_btn.toggled.connect(self.start)
self.ui.delete_btn.toggled.connect(self.start)
def start(self):
if self.ui.add_btn.isChecked():
self.ui.third_lbl.setEnabled(True)
self.ui.first_lbl.setText('Tool name')
self.ui.second_lbl.setText('ID')
self.ui.third_lbl.setText('Username')
self.ui.action_btn.clicked.connect(self.add_user)
elif self.ui.check_btn.isChecked():
self.ui.first_lbl.setText('Type of search')
self.ui.second_lbl.setText('Keyword')
self.ui.third_lbl.setEnabled(False)
self.ui.action_btn.clicked.connect(self.check_user)
elif self.ui.delete_btn.isChecked():
self.ui.first_lbl.setText('Type of search')
self.ui.second_lbl.setText('Keyword')
self.ui.third_lbl.setEnabled(False)
self.ui.action_btn.clicked.connect(self.delete_user)
Qt signals can have multiple slots attached to them. Every time you click a button the start function is adding another connection to the action_button.clicked signal.
You will need to disconnect any existing slots from the signal first to achieve the desired behaviour. You can disconnect everything from self.ui.action_btn all at once by calling its disconnect() function.
Rather than trying to reassign the roles of the GUI elements you have created, you would be better off creating separate widgets containing the elements for each checkbox state and switching between them. You might find QStackedWidget useful.

How to create Multiple / cascading windows PyQt4?

I want to create 2 windows the upper one needs to be a new project window and the lower one is the project GUI, I have created my lower window completely now I am planning to create a the upper window. How do I create my Upper(New project window)? Can I do it by including a function in my class and calling my function from my run()? or should I create a new class? I am completely confused help me!
My Lower Window(Main Project Code) Code:
class Softw(QtGui.QMainWindow, Doftw.Ui_MainWindow):
def __init__(self, parent=None):
super(Softw, self).__init__(parent)
self.setGeometry(50, 50, 700, 565)
self.setWindowTitle("Softy Softw")
-------------------------
--------(some Functions in Code)
And then finally my run() function which creates and calls the class
def run():
app=QtGui.QApplication(sys.argv)
GUI = Softw()
GUI.show()
sys.exit(app.exec_())
run()
If I do a new function in my class the window shows the upper window first then disappears and then shows the lower window:
def newProject(self):
window = QtGui.QWidget()
window.setGeometry(700,330,500,300)
window.setWindowTitle("New Project")
window.show()
I think the mistake is when to call the function when do I add my function call in this senario? In init method? or Somewhere else?
Thanks!
You can create QWidget using Qt Designer to every window that you want and then you can add them as a class to your file:
For example consider, you have created the .ui file for one window you want to create then convert it to .py using pyuic4 and then create your class like:
from Ui_created import the UI_class
class NewProject(QtGui.QMainWindow, Ui_class):
def __init__(self, parent = None):
super(NewProject, self).__init__(parent)
self.setupUi(self)
Now you can connect this to some button in the main class

How to close a QDialog

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()

PyQt - Do not want modeless dialog always on top

I have a main window that creates modeless dialogs. That's working well, but the dialogs are always in front of the main window. Even if I go back to the main window and use it to give it focus, the dialogs always remain on top. I cannot slide the main window on top of the dialogs.
I'm passing the main window's self as the parent to the dialog.
#In my main window
self.beacon_dlg = dialog_beacon.BeaconDialog(self)
#In the dialog class
class BeaconDialog(QDialog, ui_dialog_beacon.Ui_Dlg_beacon_soh):
def __init__(self, parent):
super(BeaconDialog, self).__init__(parent)
self.setupUi(self)
Any idea how to allow the main window to be in front of the dialogs, and still close the dialog when the main window is closed (parent control)?
(I'm using PyQt 4.10 and Python 2.7 on Windows)
Thanks.
I ended up using the following and it seems to work, but not sure if it's the best method. Instead of using:
def __init__(self, parent):
super(BeaconDialog, self).__init__(parent)
I used:
def __init__(self, parent):
super(BeaconDialog, self).__init__()
thus not making the dialog a child of the main window. (I still passed the main window as an argument to the class for other reasons)
However then in order to have the dialog shutdown correctly I had to overload the main window's closeEvent() and shut down the dialog myself with:
def closeEvnet(self):
if (self.beacon_dlg) : self.beacon_dlg.reject()
From QDialog Class Reference: "A dialog is always a top-level widget, but if it has a parent, its default location is centered on top of the parent's top-level widget (if it is not top-level itself). It will also share the parent's taskbar entry."
You could try to use QWidget instead.

PyQt Multiple Windows - how to pass functions between modules Qt Designer

I'll start with the question and then try to explain:
Is there a way for an imported module to call a function in the module that imports it?
I am just learning to use Qt and am starting with Qt Designer to get some fundamentals worked out.
I have figured out how to create more than one ".ui" file in order to get the code for multiple windows and have managed to work out how to call the multiple windows from a main application by importing the code for the two windows.
For example, starting with win1.ui and win2.ui I create win1.py and win2.py - from my main application I import win1 and win2...
Note - I got this far by following this simple tutorial : http://www.youtube.com/watch?v=bHsC6WJsK-U&list=PLF4575388795F2531&index=10&feature=plpp_video
OK - now the question. If I have a button in win2, I know how to link that button to a function in the win2.py code. What I don't know how to do is link the button in win2 to a function in my main application.
My only thought would be to add a function as an argument to the class that sets up the second window but if I do that then any changes to win2.ui will wreck the code that I have changed.
Thus, Is there a way for an imported module to call a function in the module that imports it?
I hope this is clear without adding a bunch of code that isn't really relevant...
Qt is based on event-driven programming. Generally when you start building up your widgets, what you are going to be wanting to do is providing information to receiver widgets via signals that are then processed. You don't want to explicitly have a child widget know or require to call methods on a parent widget (this is not always the case, but it is good to avoid when possible).
I'm gonna post some examples that don't have UI files for ease here, but just assume you can build the same widget with designer and have it work the same way...
testwidget.py
from PyQt4 import QtGui, QtCore
class TestWidget(QtGui.QWidget):
textSaved = QtCore.pyqtSignal(str)
def __init__( self, parent = None ):
super(TestWidget, self).__init__(parent)
# create the ui (or load it)
self.__edit = QtGui.QTextEdit(self)
self.__button = QtGui.QPushButton(self)
self.__button.setText('Save')
layout = QtGui.QVBoxLayout()
layout.addWidget(self.__edit)
layout.addWidget(self.__button)
self.setLayout(layout)
# create connections
self.__button.clicked.connect(self.emitTextSaved)
def emitTextSaved( self ):
# allow Qt's blocking of signals paradigm to control flow
if ( not self.signalsBlocked() ):
self.textSaved.emit(self.__edit.toPlainText())
testwindow.py
from PyQt4 import QtGui, QtCore
import testwidget
class TestWindow(QtGui.QMainWindow):
def __init__( self, parent == None ):
super(TestWindow, self).__init__(parent)
# create the ui (or load it)
self.__editor = testwidget.TestWidget(self)
self.setCentralWidget(self.__editor)
# create connections
self.__editor.textSaved.connect(self.showMessage)
def showMessage( self, message ):
QtGui.QMessageBox.information(self, 'Message', message)
So, here you can see that instead of thinking about it like - "when I click the button in TestWidget, I want to show a message in TestWindow" and explicitly link the two methods, you expose a signal that the TestWidget will emit out when the user performs an action, then connect that signal to the showMessage slot of the TestWindow. This way, your smaller widgets become more independent, and its more a matter of how you connect to each event that drives your application.
I could have done something like self.parent().showMessage(self.__edit.toPlainText()) within the TestWidget's emitTextSaved method to call the method directly - but this is not a good design.

Categories

Resources