I have written the code below:
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtGui.QStackedWidget()
self.setCentralWidget(self.central_widget)
Login_Widget = LoginPage(self)
self.central_widget.addWidget(Login_Widget)
self.central_widget.setCurrentWidget(Login_Widget)
self.setStyleSheet("background-color:#FFDA00;")
class LoginPage(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginPage, self).__init__(parent)
self.Username = QtGui.QLineEdit(self)
self.Password = QtGui.QLineEdit(self)
self.Password.setEchoMode(QtGui.QLineEdit.Password)
self.buttonLogin = QtGui.QPushButton('Login', self)
self.cancelButton = QtGui.QPushButton('Cancel', self)
loginLayout = QtGui.QFormLayout()
loginLayout.addRow("Username", self.Username)
loginLayout.addRow("Password", self.Password)
horizontallayout = QtGui.QHBoxLayout()
horizontallayout.addWidget(self.buttonLogin)
horizontallayout.addWidget(self.cancelButton)
layout = QtGui.QVBoxLayout(self)
layout.addLayout(loginLayout)
layout.addLayout(horizontallayout)
self.setLayout(layout)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
With the code above, When I run the code, it sets everything orange. I wanted to set the background orange, the lineedit white and the buttons silvery-grey. How would I set different colors for individual widget items?? Also is there any way that I could set a colour for the Window bar (the bar containing the window-title, exit button, minimize button, and re-size button)
Any help will be much appreciated!
You can set different style properties for individual widgets.
Have a look at this link Qt Style Sheets Examples as it cover how to set different style properties for most of the widgets.
You can also save the stylesheeet as .qss file and save it externally.
css = '''
QMainWindow
{
background:orange;
}
QLineEdit
{
background:white;
}
QPushButton
{
background:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #FAFFFA, stop: 0.4 #F5F7F5,
stop: 0.5 #F0F2F0, stop: 1.0 #EDEDED);
}
'''
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtGui.QStackedWidget()
self.setCentralWidget(self.central_widget)
Login_Widget = LoginPage(self)
self.central_widget.addWidget(Login_Widget)
self.central_widget.setCurrentWidget(Login_Widget)
class LoginPage(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginPage, self).__init__(parent)
self.Username = QtGui.QLineEdit(self)
self.Password = QtGui.QLineEdit(self)
self.Password.setEchoMode(QtGui.QLineEdit.Password)
self.buttonLogin = QtGui.QPushButton('Login', self)
self.cancelButton = QtGui.QPushButton('Cancel', self)
loginLayout = QtGui.QFormLayout()
loginLayout.addRow("Username", self.Username)
loginLayout.addRow("Password", self.Password)
horizontallayout = QtGui.QHBoxLayout()
horizontallayout.addWidget(self.buttonLogin)
horizontallayout.addWidget(self.cancelButton)
layout = QtGui.QVBoxLayout(self)
layout.addLayout(loginLayout)
layout.addLayout(horizontallayout)
self.setLayout(layout)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
app.setStyleSheet(css)#<------------set your stylesheet
window = MainWindow()
window.show()
app.exec_()
As for the window title bar, it is not possible to set color or any properties. Your best bet is to hide it and implement your own window title bar.
Related
I have build a small application using PyQt and as far as I know QStackedWidget is used for making multipage applications. The issue is that it is opening multiple pages and also I'm unable to redirect to class Xyz using button in class Abc.
main.py
from PyQt4 import QtGui, QtCore
import sys
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.stacked_widget = QtGui.QStackedWidget()
layout = QtGui.QVBoxLayout()
layout.setContentsMargins(0,0,0,0)
layout.addWidget(self.stacked_widget)
widget = QtGui.QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
widget_1 = Abc(self.stacked_widget)
widget_2 = Xyz(self.stacked_widget)
self.stacked_widget.addWidget(widget_1)
self.stacked_widget.addWidget(widget_2)
self.showMaximized()
class Abc(QtGui.QWidget):
def __init__(self, stacked_widget, parent=None):
super(Abc, self).__init__(parent)
self.stacked_widget = stacked_widget
self.frame = QtGui.QFrame()
self.frame_layout = QtGui.QVBoxLayout()
self.button = QtGui.QPushButton('Click me!')
self.button.clicked.connect(self.click)
self.frame_layout.addWidget(self.button)
self.frame.setLayout(self.frame_layout)
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.frame)
self.setLayout(self.layout)
self.showMaximized()
def click(self):
print("You clicked me!")
self.stacked_widget.setCurrentIndex(1)
class Xyz(QtGui.QWidget):
def __init__(self, parent=None):
super(Xyz, self).__init__(parent)
self.frame_layout = QtGui.QStackedLayout()
self.page1 = Page("Page 1", self.frame_layout)
self.page2 = Page("Page 2", self.frame_layout)
self.frame_layout.addWidget(self.page1)
self.frame_layout.addWidget(self.page2)
class Page(QtGui.QWidget):
def __init__(self, text, frame_layout, parent=None):
super(Page, self).__init__(parent)
print(self.width(), self.height())
self.frame_layout = frame_layout
self.frame = QtGui.QFrame()
self.frame_layout = QtGui.QVBoxLayout()
self.frame.setStyleSheet("background-color: rgb(191, 191, 191)")
self.label = QtGui.QLabel()
self.label.setText(text)
self.frame_layout.addWidget(self.label, alignment=QtCore.Qt.AlignCenter)
self.frame.setLayout(self.frame_layout)
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.frame)
self.layout.setContentsMargins(0,0,0,0)
self.setLayout(self.layout)
self.showMaximized()
print(self.width(), self.height())
if __name__ == "__main__":
app = QtGui.QApplication([])
window = Window()
window.show()
sys.exit(app.exec_())
The main problem is that you are not setting the QStackedLayout for the Xyz widget, the result is that all pages will actually appear as top level windows.
When a widget is added to a layout, it takes ownership of it; if the layout is already set to a widget, then the widget that was added to the layout becomes reparented to the other. The same happens if you set the layout afterwards.
Why does it show the first page as a separate window? And why doesn't it show the second?
When a new widget is created without a parent, it becomes a top level window; when a widget is added to a new stacked layout, Qt automatically tries to show it; you didn't set the layout to anything (which would reparent it as explained before), and the result is that the first page is shown as a standalone window.
Now, since the first "screen" is going to be shown only the first time, you can set that widget as the central widget, and then set a Xyz instance (which is actually a QStackedWidget subclass) as a new central widget.
Note that you don't need to use QWidget to add a QFrame if that's the only parent widget shown: you can just subclass QFrame.
This is a much simpler and cleaner version of your code:
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.startPage = Abc()
self.setCentralWidget(self.startPage)
self.startPage.startRequest.connect(self.buildPages)
def buildPages(self):
self.pages = Xyz()
self.setCentralWidget(self.pages)
class Abc(QtGui.QFrame):
startRequest = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(Abc, self).__init__(parent)
layout = QtGui.QVBoxLayout(self)
self.button = QtGui.QPushButton('Click me!')
self.button.clicked.connect(self.startRequest)
layout.addWidget(self.button)
class Xyz(QtGui.QStackedWidget):
def __init__(self, parent=None):
super(Xyz, self).__init__(parent)
self.page1 = Page("Page 1")
self.page2 = Page("Page 2")
self.addWidget(self.page1)
self.addWidget(self.page2)
self.page1.switchRequest.connect(lambda: self.setCurrentIndex(1))
self.page2.switchRequest.connect(lambda: self.setCurrentIndex(0))
class Page(QtGui.QFrame):
switchRequest = QtCore.pyqtSignal()
def __init__(self, text, parent=None):
super(Page, self).__init__(parent)
layout = QtGui.QVBoxLayout(self)
# set the background only for QFrame subclasses (which also includes
# QLabel), this prevents setting the background for other classes,
# such as the push button
self.setStyleSheet('''
QFrame {
background-color: rgb(191, 191, 191)
}
''')
# when adding a widget to a layout, the layout tries to automatically
# make it as big as possible (based on the widget's sizeHint); so you
# should not use the alignment argument for layout.addWidget(), but for
# the label instead
self.label = QtGui.QLabel(text, alignment=QtCore.Qt.AlignCenter)
layout.addWidget(self.label)
self.switchButton = QtGui.QPushButton('Switch')
layout.addWidget(self.switchButton)
self.switchButton.clicked.connect(self.switchRequest)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
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 create a dialog with three tabs using PyQt. However, I am annoyed because although the dialog is displayed, the embedded widgets are not displayed!. I suppose this is a very simple problem with a correspondingly very simple solution, but I am struck! Can anyone give a hint? Thanks in advance!
Here is my code so far:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class TabbedDialog(QDialog):
def __init__(self, parent = None):
super(TabbedDialog, self).__init__(parent)
self.tabWidget = QTabWidget()
self.tabWidget.tab1 = QWidget()
self.tabWidget.tab2 = QWidget()
self.tabWidget.tab3 = QWidget()
self.tabWidget.addTab(self.tabWidget.tab1,"Tab 1")
self.tabWidget.addTab(self.tabWidget.tab2,"Tab 2")
self.tabWidget.addTab(self.tabWidget.tab3,"Tab 3")
self.tab1UI()
self.tab2UI()
self.tab3UI()
self.setWindowTitle("tab demo")
def tab1UI(self):
layout = QFormLayout()
layout.addRow("Name",QLineEdit())
layout.addRow("Address",QLineEdit())
self.tabWidget.setTabText(0,"Contact Details")
self.tabWidget.tab1.setLayout(layout)
def tab2UI(self):
layout = QFormLayout()
sex = QHBoxLayout()
sex.addWidget(QRadioButton("Male"))
sex.addWidget(QRadioButton("Female"))
layout.addRow(QLabel("Sex"),sex)
layout.addRow("Date of Birth",QLineEdit())
self.tabWidget.setTabText(1,"Personal Details")
self.tabWidget.tab2.setLayout(layout)
def tab3UI(self):
layout = QHBoxLayout()
layout.addWidget(QLabel("subjects"))
layout.addWidget(QCheckBox("Physics"))
layout.addWidget(QCheckBox("Maths"))
self.tabWidget.setTabText(2,"Education Details")
self.tabWidget.tab3.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
form = TabbedDialog()
retval = form.exec_()
here is my solution to the problem
On the init method, I declared a layout, then added the 'tabWidget' widget to that layout and set that layout as the layout of your QDialog.
def __init__(self, parent = None):
super(TabbedDialog, self).__init__(parent)
self.tabWidget = QTabWidget()
self.tabWidget.tab1 = QWidget()
self.tabWidget.tab2 = QWidget()
self.tabWidget.tab3 = QWidget()
self.tabWidget.addTab(self.tabWidget.tab1,"Tab 1")
self.tabWidget.addTab(self.tabWidget.tab2,"Tab 2")
self.tabWidget.addTab(self.tabWidget.tab3,"Tab 3")
self.tab1UI()
self.tab2UI()
self.tab3UI()
self.setWindowTitle("tab demo")
# Here is the addition to the code.
mainLayout = QVBoxLayout()
mainLayout.addWidget(self.tabWidget)
self.setLayout(mainLayout)
I've created a class, which creates the GUI. I would like to add a menubar to it, but I don't really know, how should I add it to the window, if I work with a class. I can't make the menu bar appaer.
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
Main = QtGui.QMainWindow()
self.tab1 = QtGui.QWidget()
self.tab2 = QtGui.QWidget()
self.figure = plt.figure()
self.canvas = FigureCanvas(self.figure)
self.tempLabel=QtGui.QLabel("NC",self)
self.tempLabel.move(350,20)
self.tempLabel.setStyleSheet('color: black; font-size: 12pt;font: bold')
#menu bar
self.menu=QtGui.QMenu("Port", self)
self.menu.addAction('&ttyUSB0',)
self.menu.addAction('&ttyUSB1',)
self.menu.addAction('&ttyUSB2',)
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.canvas)
self.layout.addWidget(self.tempLabel)
self.tab1.setLayout(self.layout)
self.tabs = QtGui.QTabWidget()
self.tabs.addTab(self.tab1, "Database")
self.tabs.addTab(self.tab2, "Current")
self.tabs.show()
The menu bar is usually accessed from the main window, using the menuBar function.
I have edited your example code to show how to add menus, and also fixed a few other minor issues:
from PyQt4 import QtCore, QtGui
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
menubar = self.menuBar()
menu = menubar.addMenu('Port')
menu.addAction('&ttyUSB0')
menu.addAction('&ttyUSB1')
menu.addAction('&ttyUSB2')
self.tab1 = QtGui.QWidget()
self.tab2 = QtGui.QWidget()
self.figure = plt.figure()
self.canvas = FigureCanvas(self.figure)
self.tempLabel = QtGui.QLabel('NC', self)
self.tempLabel.move(350, 20)
self.tempLabel.setStyleSheet(
'color: black; font-size: 12pt;font: bold')
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.canvas)
self.layout.addWidget(self.tempLabel)
self.tab1.setLayout(self.layout)
self.tabs = QtGui.QTabWidget()
self.tabs.addTab(self.tab1, 'Database')
self.tabs.addTab(self.tab2, 'Current')
self.setCentralWidget(self.tabs)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())