PyQt: Connecting a button in a dialog - python

I'm writing my first PyQt program, but I have a problem with a pushbutton. I read some other Q&A's but I wasn't able to solve it.
Basically I have a main window with a menu bar. By clicking on the menu item "actionSelect", a new dialog called SelectFiles is opened. It contains a pushbutton called "ChooseDirButton" that should open the select directory widget and change the "ShowPath" linedit text with the selected directory.
My code looks like this:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import TeraGui
class MainWindow(QMainWindow, TeraGui.Ui_MainWindow):
path = ""
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.actionSelect.triggered.connect(self.Select)
def Select(self):
dialog = QDialog()
dialog.ui = TeraGui.Ui_SelectFiles()
dialog.ui.setupUi(dialog)
dialog.setAttribute(Qt.WA_DeleteOnClose)
dialog.exec_()
def ChooseDirectory():
global path
path = str(QFileDialog.getExistingDirectory(self, "Select Directory"))
self.ShowPath.setText(path)
app = QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()
I'm not able to let the ChooseDirectory method be executed when the pushbutton "ChooseDirButton" is clicked. I tried to connect them, but I do not understand the right syntax. Moreover there could be something wrong in the ChooseDirectory method also.
I created the GUI with Qt Designer and import it with the "import TeraGui" command.

It looks like you need to create a subclass for your dialog, just as you did for the main window.
I can't actually test it without your ui modules, but something like this should work:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import TeraGui
class MainWindow(QMainWindow, TeraGui.Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.actionSelect.triggered.connect(self.Select)
def Select(self):
dialog = Dialog(self)
dialog.exec_()
self.ShowPath.setText(dialog.path)
class Dialog(QDialog, TeraGui.Ui_SelectFiles):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.setAttribute(Qt.WA_DeleteOnClose)
self.setupUi(self)
self.ChooseDirButton.clicked.connect(self.ChooseDirectory)
self.path = ''
def ChooseDirectory(self):
self.path = str(QFileDialog.getExistingDirectory(
self, "Select Directory"))
app = QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()

Related

Access data from the parent window in a child window in PyQt

I have two windows (App.py and ChildApp.py) and .ui files for both with same name.
App.py:
import sys
from PyQt4 import QtCore, QtGui, uic
from ChildApp import ChildApp
qtCreatorFile = "App.ui" # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class App(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.message = None
self.child_window = ChildApp()
self.pushButton.clicked.connect(self.sendMessage)
def sendMessage(self):
self.message = self.lineEdit.text()
self.child_window.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = App()
window.show()
sys.exit(app.exec_())
ChildApp.py:
import sys
from PyQt4 import QtCore, QtGui, uic
qtCreatorFile = "ChildApp.ui" # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class ChildApp(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.pushButton.clicked.connect(self.alertmessage)
def alertmessage(self):
message = "test"
self.label.setText("Message : "+message)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = ChildApp()
window.show()
sys.exit(app.exec_())
In Main.py file I have a variable self.message.
When I click on the button "Do something with text", text in the textbox is assigned to self.message and the child window is opened.
Now in the child window, when I click on button "Show message", the method alertmessage() is called, where it sets message = "text".
This variable message must be assigned to value of self.message from MainApp.py.
Please help
Thank you
Call the child that way:
self.child_window = ChildApp(parent=self)
Define the child app this way:
class ChildApp(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent):
self.parent = parent
you can use the parent variables through self.parent.whatever
It must work, but I wouldn't advise this because you are not supposed to know the fields of the parent form the child.
I don't think you can get local data from the parent. I would do the following:
Use a signal to update the child when the text is changed in the lineEdit:
self.lineEdit.textChanged.connect(self.updateChild)
Add this function in the main window:
def updateChild(self):
self.child_window.setMessage(self.lineEdit.text())
and keep the variable self._message updated in the child window:
def setMessage(self, message):
self._message=message
so that whenever you need this variable, it is up to date

How to show the stackwidget?

I'm trying to use the stackWidget to show different widgets .
However when I pressed the item on the listWdget , stackWidget below will not be displayed.
Here is my code,and I don't know where is wrong.
#!/usr/bin/python
# music_1.py
import sys
from PyQt4 import QtGui, QtCore
from music_ui import Ui_Form
class music(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.ui.listWidget.insertItem(0,("Warm"))
self.ui.listWidget.insertItem(1,("Funny"))
self.ui.listWidget.insertItem(2,("Terror"))
self.ui.stackedWidget=QtGui.QStackedWidget()
warm=Warm()
funny=Funny()
terror=Terror()
self.ui.stackedWidget.addWidget(warm)
self.ui.stackedWidget.addWidget(funny)
self.ui.stackedWidget.addWidget(terror)
self.connect(self.ui.listWidget,QtCore.SIGNAL("currentRowChanged(int)"),self.ui.stackedWidget,QtCore.SLOT("setCurrentIndex(int)"))
class Warm(QtGui.QWidget):
def __init__(self,parent=None):
super(Warm,self).__init__(parent)
w1=QtGui.QPushButton("w1")
w2=QtGui.QPushButton("w2")
buttonLayout=QtGui.QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(w1)
buttonLayout.addWidget(w2)
class Funny(QtGui.QWidget):
def __init__(self,parent=None):
super(Funny,self).__init__(parent)
f1=QtGui.QPushButton("f1")
f2=QtGui.QPushButton("f2")
f3=QtGui.QPushButton("f3")
buttonLayout=QtGui.QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(f1)
buttonLayout.addWidget(f2)
buttonLayout.addWidget(f3)
class Terror(QtGui.QWidget):
def __init__(self,parent=None):
super(Terror,self).__init__(parent)
t1=QtGui.QPushButton("t1")
t2=QtGui.QPushButton("t2")
buttonLayout=QtGui.QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(t1)
buttonLayout.addWidget(t2)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = music()
myapp.show()
sys.exit(app.exec_())
I never worked with UI Files but this is my guess:
self.ui.stackedWidget=QtGui.QStackedWidget()
here you create a QStackedWidget which gets assigned to the class. The problem is that it is not added to the UI that is getting displayed but just to the instance of the Ui_Form. What you have to do is either:
Add the QStackedWidget in the UI Designer and erase the line above
or
Add the QStackedWidget to one of your layouts
which can be done like this:
self.ui.mySuperCoolLayout.addWidget(self.ui.stackedWidget)

Working with PyQt and Qt designer ui files

I'm new to PyQt and I'm trying to work with ui files directly from within my PyQt script. I have two ui files, mainwindow.ui and landing.ui. Clicking on a button 'pushButton' on the main window should open the landing window. However, clicking on the button does not work as I expected. Here is the code(I'm just trying to work stuff out so the code is pretty rough):
from PyQt4 import QtCore, uic
from PyQt4 import QtGui
import os
CURR = os.path.abspath(os.path.dirname('__file__'))
form_class = uic.loadUiType(os.path.join(CURR, "mainwindow.ui"))[0]
landing_class = uic.loadUiType(os.path.join(CURR, "landing.ui"))[0]
def loadUiWidget(uifilename, parent=None):
uifile = QtCore.QFile(uifilename)
uifile.open(QtCore.QFile.ReadOnly)
ui = uic.loadUi(uifilename)
uifile.close()
return ui
#QtCore.pyqtSlot()
def clicked_slot():
"""this is called when login button is clicked"""
LandingPage = loadUiWidget(os.path.join(CURR, "landing.ui"))
center(LandingPage)
icon(LandingPage)
LandingPage.show()
class MyWindow(QtGui.QMainWindow, form_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.pushButton.clicked.connect(clicked_slot)
class LandingPage(QtGui.QMainWindow, landing_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
def center(self):
""" Function to center the application
"""
qRect = self.frameGeometry()
centerPoint = QtGui.QDesktopWidget().availableGeometry().center()
qRect.moveCenter(centerPoint)
self.move(qRect.topLeft())
def icon(self):
""" Function to set window icon
"""
appIcon = QtGui.QIcon("icon.png")
self.setWindowIcon(appIcon)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
pixmap = QtGui.QPixmap(os.path.join(CURR, "splash.png"))
splash = QtGui.QSplashScreen(pixmap)
splash.show()
app.processEvents()
MainWindow = MyWindow(None)
center(MainWindow)
icon(MainWindow)
MainWindow.show()
splash.finish(MainWindow)
sys.exit(app.exec_())
What mistake I'm I making??
There are two main problems with your script: firstly, you are not constructing the path to the ui files correctly; and secondly, you are not keeping a reference to the landing-page window (and so it will get garbage-collected immediately after it is shown).
Here is how the part of the script that loads the ui files should be structured:
import os
from PyQt4 import QtCore, QtGui, uic
# get the directory of this script
path = os.path.dirname(os.path.abspath(__file__))
MainWindowUI, MainWindowBase = uic.loadUiType(
os.path.join(path, 'mainwindow.ui'))
LandingPageUI, LandingPageBase = uic.loadUiType(
os.path.join(path, 'landing.ui'))
class MainWindow(MainWindowBase, MainWindowUI):
def __init__(self, parent=None):
MainWindowBase.__init__(self, parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.handleButton)
def handleButton(self):
# keep a reference to the landing page
self.landing = LandingPage()
self.landing.show()
class LandingPage(LandingPageBase, LandingPageUI):
def __init__(self, parent=None):
LandingPageBase.__init__(self, parent)
self.setupUi(self)

Load other windows when button clicked. PyQt

I am trying to call another window from a button click in python 2.7 using PyQt4. The code below opens the AddBooking dialog but immediately closes it. Im new to Gui programming, can somebody please tell me what is wrong with my code?
from PyQt4 import QtGui
from HomeScreen import Ui_HomeScreen
from AddBooking import Ui_AddBooking
import sys
class HomeScreen(QtGui.QWidget, Ui_HomeScreen):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.show()
self.Add_Booking_Button.clicked.connect(self.handleButton)
def handleButton(self):
AddBooking2()
class AddBooking2(QtGui.QWidget, Ui_AddBooking):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = HomeScreen()
window.show()
sys.exit(app.exec_())
Don't use multi-inheritance and neither call show function inside class initializer. The problem is that the object you are creating with AddBooking2() is a temporal and it's destroyed automatically when the function ends. So you need use some variable to reference that object something like:
addbooking = AddBooking2()
addbooking.show()
Also, since you are working with QtDesigner and pyuic4 tools you can make connections a little bit easier. Said that, your code can be modified:
from PyQt4 import QtGui
from PyQt4.QtCore import pyqtSlot
from HomeScreen import Ui_HomeScreen
from AddBooking import Ui_AddBooking
import sys
class HomeScreen(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_HomeScreen()
self.ui.setupUi(self)
#pyqtSlot("")
def on_Add_Booking_Button_clicked(self): # The connection is carried by the Ui_* classes generated by pyuic4
addbooking = AddBooking2()
addbooking.show()
class AddBooking2(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_AddBooking()
self.ui.setupUi(self)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = HomeScreen()
window.show()
sys.exit(app.exec_())
The dialog closes immediately because you are not keeping a reference to it, and so it will get garbage-collected as soon as it goes out of scope.
The simplest way to fix it would be to do something like this:
def handleButton(self):
self.dialog = AddBooking2()
self.dialog.show()
and you can also remove the self.show() lines from AddBooking2.__init__ and HomeScreen.__init__, which are redundant. Other than that, your code looks fine.

Quiting the print dialog-pyqt

I defined a print function using QPrinter and QDialog. However, when I launch the printer dialog and then press cancel, the entire mainwindow goes into not responding mode. I have tried to do QtGui.QPrintDialog.close() but does not work.
Code:
import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
class QButton(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.button = QtGui.QPushButton('Button', self)
self.name='me'
self.button.clicked.connect(self.calluser)
def calluser(self):
Appli=QtGui.QApplication(sys.argv)
printer= QtGui.QPrinter()
doc=QtGui.QTextDocument("Set local variables in this printing slot." )
dialog = QtGui.QPrintDialog(printer)
dialog.setModal(True)
dialog.setWindowTitle("Print Document" )
if dialog.exec_() == True:
doc.print_(printer)
# dialog.addEnabledOption(QAbstractPrintDialog.PrintSelection)
def demo_QButton():
app = QtGui.QApplication(sys.argv)
tb = QButton()
tb.show()
app.exec_()
if __name__=='__main__':
demo_QButton()
You created a new application in the calluser method. Delete or comment the line:
Appli=QtGui.QApplication(sys.argv)
and try again. I think this time your main window will remain responsive.

Categories