I am trying to create a PyQt application that has both status bar and a menu bar with other Widgets in the window. Below is the code which I managed to get it run with class QtGui.QMainWindow method. But as I intend to add further features, I realise I must use QtGui.QWidget instead.
Here is the code:
import sys
from PyQt4 import QtGui, QtCore
### How can I use QtGui.QWidget here??? ###
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> Window widget')
exitAction = QtGui.QAction(QtGui.QIcon('exit-icon-2.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit/Terminate application')
exitAction.triggered.connect(QtGui.qApp.quit)
self.statusBar()
menubar = self.menuBar()
menubar.setToolTip('This is a <b>QWidget</b> for MenuBar')
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
toolbar = self.addToolBar('Exit')
toolbar.addAction(exitAction)
qbtn = QtGui.QPushButton('Quit', self)
qbtn.setToolTip('This is a <b>QPushButton</b> widget')
qbtn.clicked.connect(self.launchAAA)
qbtn.resize(qbtn.sizeHint())
qbtn.move(170, 190)
self.setGeometry(500, 180, 400, 400)
self.setWindowTitle('Quit button with Message')
self.show()
def launchAAA(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
QtGui.QApplication.quit()
else:
pass
def main():
app = QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I am under the impression that menu bar and title bars can be created using QWidget method, but here it doesn't work. I intend to add an LCD function to the application using QtGui.QLCDNumber.
Any suggestions on how to fix the above problem. Thanks
You could just move your buttons/labels/etc. to a QWidget, and add this widget to the main window. Here is how it could look like (I changed the imports so that it is a bit more readable).
Your content widget class :
class ExampleContent(QWidget):
def __init__(self, parent):
QWidget.__init__(self, parent)
self.initUI()
def initUI(self):
qbtn = QPushButton('Quit', self)
qbtn.setToolTip('This is a <b>QPushButton</b> widget')
qbtn.clicked.connect(self.launchAAA)
qbtn.resize(qbtn.sizeHint())
qbtn.move(170, 190)
def launchAAA(self):
reply = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
QApplication.quit()
else:
pass
Add it to the main window :
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QToolTip.setFont(QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> Window widget')
exitAction = QAction(QIcon('exit-icon-2.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit/Terminate application')
exitAction.triggered.connect(qApp.quit)
self.statusBar()
menubar = self.menuBar()
menubar.setToolTip('This is a <b>QWidget</b> for MenuBar')
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
toolbar = self.addToolBar('Exit')
toolbar.addAction(exitAction)
# create the widget here
content = ExampleContent(self)
self.setCentralWidget(content)
self.setGeometry(500, 180, 400, 400)
self.setWindowTitle('Quit button with Message')
self.show()
And everything just works as before, except that you new have a QWidget in the middle, instead of a QMainWindow. Hope that helped !
Here is a working solution using your code. I added a centralWidget and a centralLayout to the QMainWindow which now holds your qbtn:
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> Window widget')
exitAction = QtGui.QAction(QtGui.QIcon('exit-icon-2.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit/Terminate application')
exitAction.triggered.connect(QtGui.qApp.quit)
self.statusBar()
menubar = self.menuBar()
menubar.setToolTip('This is a <b>QWidget</b> for MenuBar')
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
toolbar = self.addToolBar('Exit')
toolbar.addAction(exitAction)
# Create a central Widgets
centralWidget = QtGui.QWidget()
# Create a Layout for the central Widget
centralLayout = QtGui.QHBoxLayout()
qbtn = QtGui.QPushButton('Quit', self)
qbtn.setToolTip('This is a <b>QPushButton</b> widget')
qbtn.clicked.connect(self.launchAAA)
qbtn.resize(qbtn.sizeHint())
qbtn.move(170, 190)
# Add the Button to the Layout
centralLayout.addWidget(qbtn)
# Set the Layout
centralWidget.setLayout(centralLayout)
# Set the Widget
self.setCentralWidget(centralWidget)
self.setGeometry(500, 180, 400, 400)
self.setWindowTitle('Quit button with Message')
self.show()
def launchAAA(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
QtGui.QApplication.quit()
else:
pass
def main():
app = QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You can also use a combination of QMainWindow and QWidget.
I have found this useful in some cases. You can add statusbar and menubar to the MainWindow section and the widgets to the QWidget area.
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.win_widget = WinWidget(self)
widget = QtGui.QWidget()
layout = QtGui.QVBoxLayout(widget)
layout.addWidget(self.win_widget)
self.setCentralWidget(widget)
self.statusBar().showMessage('Ready')
self.setGeometry(300, 300, 450, 250)
self.setWindowTitle('Test')
self.setWindowIcon (QtGui.QIcon('logo.png'))
self.show()
self.win_widget = WinWidget (self)
class WinWidget (QtGui.QWidget) :
def __init__(self, parent):
super (WinWidget , self).__init__(parent)
self.__controls()
#self.__layout()
def __controls(self):
self.qbtn = QtGui.QPushButton('Quit', self)
self.qbtn. clicked.connect(QtCore.QCoreApplication.instance().quit)
self.qbtn.setFixedSize (100,25)
self.qbtn.move(50, 50)
def main():
app = QtGui.QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Related
So I'm new to PyQt and I can't seem to quite work out all the kinks. For some reason, whenever I click the "play game" button, the image just doesn't appear. However, it does run the InitUI. Can someone tell me what Im doing wrong? (when It just loaded up the image initially, the image appeared.
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 image - pythonspot.com'
self.initUI()
def initUI(self):
central_widget = QWidget()
self.chess = ChessWidget(central_widget)
self.setCentralWidget(central_widget)
self.setWindowIcon(QIcon('web.png'))
self.resize(900,900)
self.center()
self.setFixedSize(self.size())
self.show()
def toggleMenu(self, state):
if state:
self.statusbar.show()
else:
self.statusbar.hide()
# def closeEvent(self, event):
#
# reply = QMessageBox.question(self, 'Message',
# """Are you sure you want to quit?""", QMessageBox.Yes |
# QMessageBox.No, QMessageBox.No)
#
# if reply == QMessageBox.Yes:
# event.accept()
# else:
# event.ignore()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
class ChessWidget(QFrame):
def __init__(self, parent):
super().__init__(parent)
qbtn = QPushButton('Play Game', self)
qbtn.clicked.connect(lambda: qbtn.close())
qbtn.clicked.connect(lambda: self.initUI())
qbtn.resize(qbtn.sizeHint())
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(qbtn)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
def initUI(self):
print("hi")
pixmap = QPixmap("ChessBoard.jpg")
lbl = QLabel(self)
pixmap2 = pixmap.scaledToWidth(900)
hbox = QHBoxLayout(self)
hbox.addStretch(1)
hbox.addWidget(lbl)
lbl.setPixmap(pixmap2) ` if __name__ == '__main__':
app = QApplication([])
ex = Example()
sys.exit(app.exec_()) `
You should be getting a useful warning from Qt; if not, check that your test environment has a console active. The warning is:
QLayout: Attempting to add QLayout "" to ChessWidget "", which already has a layout
This happens when you create the QHBoxLayout in ChessWidget.initUI and try to parent it to the ChessWidget. You have already set a QVBoxLayout on that widget.
A quick solution is to retain the name of your layout (vbox -> self.vbox), then in a click event remove the QPushButton from the layout and add the ChessWidget.
I understand you're just making small tests for learning purposes, but this design pattern with the QPushButton being permanently replaced might not be what you want. If you want the QPushButton and ChessWidget to occupy the same space, look at QStackedWidget. This will allow you to switch from one widget to the other as often as you like. This could be a useful approach if you want to hide the ChessWidget later when no game is active, for example.
Note that when you create your QPushButton and QLabel, it's unnecessary to parent them to the ChessWidget as they will be reparented to the layout when added.
Try it:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
central_widget = QWidget()
self.chess = ChessWidget(central_widget)
self.setCentralWidget(central_widget)
self.layV = QVBoxLayout(central_widget) # +++
self.layV.addWidget(self.chess) # +++
self.setWindowIcon(QIcon('D:/_Qt/img/py-qt.png')) # web.png
self.resize(440,440) #(900,900)
class ChessWidget(QFrame):
def __init__(self, parent=None):
super().__init__(parent)
qbtn = QPushButton('Play Game', self)
qbtn.clicked.connect(lambda: qbtn.close())
qbtn.clicked.connect(lambda: self.initUI())
self.hbox = QHBoxLayout()
self.hbox.addWidget(qbtn)
self.vbox = QVBoxLayout()
self.vbox.addStretch(1)
self.vbox.addLayout(self.hbox)
self.setLayout(self.vbox)
def initUI(self):
print("hi")
pixmap = QPixmap("D:/_Qt/img/pyqt.jpg") # ChessBoard.jpg
lbl = QLabel(self)
self.vbox.addWidget(lbl)
lbl.setPixmap(pixmap.scaled(400, 400, Qt.KeepAspectRatio)) # +++
if __name__ == '__main__':
app = QApplication([])
ex = Example()
ex.setWindowTitle('PyQt5 image - pythonspot.com')
ex.show()
sys.exit(app.exec_())
I'm new to python and pyqt. I'm trying to open a new window after the first screen. My second window opens but without the options I specified, label and pushbutton.
from PyQt5 import QtWidgets
import sys
class secondwindow(QtWidgets.QMainWindow):
def __init__(self):
super(secondwindow, self).__init__()
self.label1 = QtWidgets.QLabel("Second Window");
self.button1 = QtWidgets.QPushButton("Click Me");
hbox = QtWidgets.QHBoxLayout()
hbox.addWidget(self.label1)
hbox.addWidget(self.button1)
self.setLayout(hbox)
class Window(QtWidgets.QWidget):
def btnclicked(self):
sender = self.sender()
if sender.text() == "OK":
self.secwin.show()
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.button1 = QtWidgets.QPushButton("OK");
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(self.button1)
self.setLayout(vbox)
self.button1.clicked.connect(self.btnclicked)
self.secwin = secondwindow()
self.show()
def main():
app = QtWidgets.QApplication(sys.argv)
main = Window()
main.show
sys.exit(app.exec())
if __name__ == '__main__':
main()
QMainWindow is a special widget because it has a defined structure, http://doc.qt.io/qt-5/qmainwindow.html#qt-main-window-framework:
As shown in the image there is already an area destined to place the widgets called Central Widget, in it you must place the widgets that you want to be displayed for it, you use setCentralWidget().
In your case the solution is:
class secondwindow(QtWidgets.QMainWindow):
def __init__(self):
super(secondwindow, self).__init__()
central_widget = QtWidgets.QWidget()
self.label1 = QtWidgets.QLabel("Second Window")
self.button1 = QtWidgets.QPushButton("Click Me")
hbox = QtWidgets.QHBoxLayout(central_widget)
hbox.addWidget(self.label1)
hbox.addWidget(self.button1)
self.setCentralWidget(central_widget)
I am trying to generate a visualizer where each time you press a button the image in a window change. The image have to be in the same window where the button is and it has to replace the previous image.
So for I am able to show the button and the first image. But I cannot connect the click button with the image updating process.
This is my code so far:
author__ = 'lpp'
#!/usr/bin/python
import os,sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('Test', 10))
self.setToolTip('This is a <b>QWidget</b> widget')
# Show image
pic = QtGui.QLabel(self)
pic.setGeometry(10, 10, 800, 800)
pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/Image1.png"))
# Show button
btn = QtGui.QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.clicked.connect(self.fun)
btn.move(50, 50)
self.setGeometry(300, 300, 2000, 1500)
self.setWindowTitle('Tooltips')
self.show()
# Connect button to image updating
def fun(self):
#print("Test!!!")
pic = QtGui.QLabel(self)
pic.setGeometry(100, 10, 800, 800)
pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/image2.png"))
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
All but the "def fun" works.
I also tried these functions but it did not work:
def fun(self):
pic = QtGui.QLabel(self)
pic.setGeometry(100, 10, 800, 800)
pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/image2.png"))
return (pic)
def fun(self):
#print("Test!!!")
pic = QtGui.QLabel(self)
pic.setGeometry(100, 10, 800, 800)
pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/image2.png"))
return self.show()
If you want the previous image you should not create a new QLabel, but just update the QPixmap.
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('Test', 10))
self.setToolTip('This is a <b>QWidget</b> widget')
# Show image
self.pic = QtGui.QLabel(self)
self.pic.setGeometry(10, 10, 800, 800)
self.pic.setPixmap(QtGui.QPixmap("/home/lpp/Desktop/image1.png"))
# Show button
btn = QtGui.QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.clicked.connect(self.fun)
btn.move(50, 50)
self.setGeometry(300, 300, 2000, 1500)
self.setWindowTitle('Tooltips')
self.show()
# Connect button to image updating
def fun(self):
self.pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/image2.png"))
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I am trying to get buttons and a menu bar inside a GUI application. When I run my code the GUI is seen with the menu bar but the button is not seen. Here is my sample code. And the code compiles without any error.
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class guiwindow(QMainWindow):
def __init__(self):
super(guiwindow,self).__init__()
self.menubar()
def menubar(self):
textEdit = QWidget()
self.setCentralWidget(textEdit)
exitAction = QAction('Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.close)
self.statusBar()
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
self.setGeometry(400, 100, 1200, 800)
self.setWindowTitle("Menubar + Buttons")
button = QPushButton("Test")
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(button)
self.setLayout(hbox)
self.show()
def main():
app = QApplication(sys.argv)
ex = guiwindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Generally, in GUI programming you'll have to be faimliar with the concept of parent and child widgets. If you want your button to be inside your window, then the later should be a child of the former.
So use:
button = QPushButton("Test", parent=self)
Instead of:
button = QPushButton("Test")
Hope this helps!
I just started with programming, started using Python and PyQt4. And got this error:
QCoreApplication::exec: The event loop is already running
Basically i wanted to write a function which, when you press a button, opens a new gui window(while the previous one wouldnt exist at that point) with completely new layout.
Is there a way how to fix the script or write it in another way to get the outcome?
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50 , 1280, 720)
self.setWindowTitle("Main")
self.setWindowIcon(QtGui.QIcon("smili.png"))
extractAction = QtGui.QAction("Exit", self)
extractAction.setShortcut("Ctrl+Q")
extractAction.setStatusTip("Press to leave the app.")
extractAction.triggered.connect(self.close_appllication)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("Menu")
fileMenu.addAction(extractAction)
self.home()
def home(self):
btn = QtGui.QPushButton("Quit", self)
btn.clicked.connect(QtCore.QCoreApplication.instance() .quit)
btn.resize(250,50)
btn.move(100,600)
btn.setStyleSheet('QPushButton{background-color:#8A0808;color:#000000;font-size:25px;border:5px}')
btn = QtGui.QPushButton("Start", self)
btn.clicked.connect(self.redirect_window)
btn.resize(250,50)
btn.move(100,200)
btn.setStyleSheet('QPushButton{background-color:#8A0808;color:#000000;font-size:25px;border:5px}')
extractAction = QtGui.QAction(QtGui.QIcon("exitb.png"), "Exit the application.", self)
extractAction.triggered.connect(self.close_appllication)
self.toolBar = self.addToolBar("ToolBar")
self.toolBar.addAction(extractAction)
checkBox = QtGui.QCheckBox("Enlarge Window", self)
checkBox.move(100, 25)
checkBox.stateChanged.connect(self.enlarge_window)
self.show()
def redirect_window(self):
class startWindow(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50 , 1280, 720)
self.setWindowTitle("Main/Start")
self.setWindowIcon(QtGui.QIcon("smili.png"))
extractAction = QtGui.QAction("Exit", self)
extractAction.setShortcut("Ctrl+Q")
extractAction.setStatusTip("Press to leave the app.")
extractAction.triggered.connect(self.close_appllication)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("Menu")
fileMenu.addAction(extractAction)
self.home()
main()
def enlarge_window(self, state):
if state == QtCore.Qt.Checked:
self.setGeometry(50,50,1920,1080)
else:
self.setGeometry(50,50,1280,720)
def close_appllication(self):
print("Shutting down!")
sys.exit()
def main():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
main()