How to create a Stylesheet for Mulitiple QLabels or Multiple Qwidgets in PyQt5 ?
For example, In my programme, I use 8 QLabels, Out of Which 4 QLabels belong to one family/group and another 4 have a another family/group. Now I want to create a separate style sheet for both families. First family (all 4 QLabels) have to set the same property ( Background color, foreground color, Alignment, and font) and the second family also have to set different properties.
import sys
from PyQt5.QtWidgets import QWidget,QApplication,QLabel,QFormLayout
class Stylesheet_001(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Style Sheet Example_001")
self.setMinimumSize(600,800)
self.setMaximumSize(600,800)
self.mydesign()
def mydesign(self):
lbl_normal = QLabel("Total Available Items :")
lbl_starts = QLabel("Item Starts With :")
lbl_contains = QLabel("Items Contains Anywhere :")
lbl_end = QLabel("Items Ends With :")
lbl_normal_count = QLabel("500")
lbl_starts_count = QLabel('50,000')
lbl_contains_count = QLabel('5')
lbl_ends_count = QLabel('0')
mylayout = QFormLayout()
mylayout.addRow(lbl_normal ,lbl_normal_count)
mylayout.addRow(lbl_starts ,lbl_starts_count)
mylayout.addRow(lbl_contains,lbl_contains_count)
mylayout.addRow(lbl_end ,lbl_ends_count)
self.setLayout(mylayout)
def main():
myapp = QApplication(sys.argv)
mywindow = Stylesheet_001()
mywindow.show()
sys.exit(myapp.exec_())
if __name__ == "__main__":
main()
1) lbl_normal, 2) lbl_strats, 3) lbl_contains , 4) lbl_ends belong to one group (First) and another 4 Labels belong to another group (second group).
First group have to set same, fore-ground color:Red,font : Caliber,10,Bold and Alignment to Right.
Second group have to set same, fore-ground colour:Green,font:system default and Alignment to Left.
Try it:
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QFormLayout,\
QFrame, QVBoxLayout
from PyQt5.QtCore import Qt
class Stylesheet_001(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Style Sheet Example_001")
self.setMinimumSize(600,800)
self.setMaximumSize(600,800)
self.mydesign()
def mydesign(self):
# Red, same font : Caliber, 10, Bold, and Alignment to Right
lbl_normal = QLabel("Total Available Items :", alignment=Qt.AlignRight | Qt.AlignVCenter)
lbl_normal.setMinimumWidth(180)
lbl_starts = QLabel("Item Starts With :", minimumWidth=180, alignment=Qt.AlignRight | Qt.AlignVCenter)
lbl_contains = QLabel("Items Contains Anywhere :", minimumWidth=180, alignment=Qt.AlignRight | Qt.AlignVCenter)
lbl_end = QLabel("Items Ends With :", minimumWidth=180, alignment=Qt.AlignRight | Qt.AlignVCenter)
lbl_normal_count = QLabel("500")
lbl_starts_count = QLabel('50,000')
lbl_contains_count = QLabel('5')
lbl_ends_count = QLabel('0')
mylayout = QFormLayout(self)
mylayout.addRow(lbl_normal , lbl_normal_count)
mylayout.addRow(lbl_starts , lbl_starts_count)
mylayout.addRow(lbl_contains, lbl_contains_count)
mylayout.addRow(lbl_end , lbl_ends_count)
QSS = """
QWidget > QLabel[text="Total Available Items :"],
QWidget > QLabel[text="Item Starts With :"],
QWidget > QLabel[text="Items Contains Anywhere :"],
QWidget > QLabel[text="Items Ends With :"] {
background-color: red;
color: white;
font: bold 10pt \"Caliber\";
}
QWidget > QLabel {
background-color: green;
color: yellow;
font: 10pt \"Caliber\";
}
"""
def main():
myapp = QApplication(sys.argv)
myapp.setStyle('Fusion')
myapp.setStyleSheet(QSS)
mywindow = Stylesheet_001()
mywindow.show()
sys.exit(myapp.exec_())
if __name__ == "__main__":
main()
Try it :
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Stylesheet_001(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Style Sheet Example_001")
self.setMinimumSize(600,800)
# self.setMaximumSize(600,800)
self.mydesign()
def mydesign(self):
lbl_normal = QLabel("Total Available Items :")
lbl_starts = QLabel("Item Starts With :")
lbl_contains = QLabel("Items Contains Anywhere :")
lbl_end = QLabel("Items Ends With :")
lbl_normal.setStyleSheet(self.stylesheet_family_1())
lbl_starts.setStyleSheet(self.stylesheet_family_1())
lbl_contains.setStyleSheet(self.stylesheet_family_1())
lbl_end.setStyleSheet(self.stylesheet_family_1())
lbl_normal_count = QLabel("500")
lbl_starts_count = QLabel('50,000')
lbl_contains_count = QLabel('5')
lbl_ends_count = QLabel('0')
lbl_normal_count.setStyleSheet(self.stylesheet_family_2())
lbl_starts_count.setStyleSheet(self.stylesheet_family_2())
lbl_contains_count.setStyleSheet(self.stylesheet_family_2())
lbl_ends_count.setStyleSheet(self.stylesheet_family_2())
self.mylayout = QFormLayout()
self.mylayout.setSpacing(0)
self.mylayout.addRow(lbl_normal ,lbl_normal_count)
self.mylayout.addRow(lbl_starts ,lbl_starts_count)
self.mylayout.addRow(lbl_contains,lbl_contains_count)
self.mylayout.addRow(lbl_end ,lbl_ends_count)
self.myframe = QFrame()
self.mainlayout = QVBoxLayout()
self.myframe.setFixedSize(400,300)
self.myframe.setLayout(self.mylayout)
self.mainlayout.addWidget(self.myframe)
self.mainlayout.addStretch()
self.setLayout(self.mainlayout)
def stylesheet_family_1(self):
return"""
QLabel{
background-color:'red';
font-family: Caliber;
font-style: normal;
font-size:10pt;
font-weight:normal;
border-width:1px;
border-color:black;
border-top-color:black;
border-style:outset;
color:white;
padding:6px;
min-width:220px;
qproperty-alignment:'AlignRight';
}
"""
def stylesheet_family_2(self):
return"""
QLabel{
background-color:'green';
font-family: Caliber;
font-style: normal;
font-size:10pt;
font-weight:bold;
border-width:1px;
border-color:black;
border-top-color:black;
border-style:outset;
color:white;
padding:1px;
min-width:20px;
qproperty-alignment:'AlignCenter|AlignRight';
}
"""
def main():
myapp = QApplication(sys.argv)
mywindow = Stylesheet_001()
mywindow.show()
sys.exit(myapp.exec_())
if __name__ == "__main__":
main()
Related
Good Evening,
I am working on one of my first Python programs utilizing the MVC framework. I have looked at several tutorials and examples of MVC and I followed a youTube series of creating a calulator using MVC from Life in Code. https://www.youtube.com/channel/UCb__or4F5GkZLGYBhvfa5hg/featured
I am running into an issue with my program and I can't figure out why, I believe I have narrowed the issue down to the "View" class doesn't not see the "Controller" class to pass the function. I just don't know why. I am doing what I believe to be the same thing as Life in Code is doing with his example.
atdsController.py
import sys
from atdsCreatorUi import displayUi
#from atdsModel import atdsModel
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow
class atdsController:
def __init__(self):
#self.model = atdsModel()
self.view = displayUi(self)
def on_button_click(self, btnTxt):
print("I'm back in controller")
#file = self.model.openFile()
def main():
atdsFileCreator = QApplication(sys.argv)
atdsFileCreator.setStyle('Fusion')
#Show GUI
view = displayUi(QMainWindow)
view.show()
sys.exit(atdsFileCreator.exec_())
if __name__ == "__main__":
main()
atdsCreatorUi.
from PyQt5.QtCore import QCoreApplication, QDateTime, QTimer, QMetaObject
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import (
QMainWindow,
QFrame,
QWidget,
QHBoxLayout,
QVBoxLayout,
QGridLayout,
QGroupBox,
QLabel,
QPushButton,
QLineEdit,
QFileDialog,
QTableWidget,
QHeaderView,
QMenuBar,
QProgressBar,
QStatusBar,
QAction,
QWidgetAction,
QToolBar,
QPlainTextEdit)
__version__ = "1.0"
__author__ = "Daniel DeWitte"
ERROR_MSG = 'ERROR'
class VLine(QFrame):
def __init__(self):
super(VLine, self).__init__()
self.setFrameShape(self.VLine|self.Sunken)
class displayUi(QMainWindow):
def _createLeftLayout(self):
leftLayout = QVBoxLayout()
# Create Buttons
loadFile = QPushButton("Load File")
#btnTxt = loadFile.text()
loadFile.clicked.connect(lambda checked, btnTxt = loadFile.text():
self.controller.on_button_click(btnTxt))
loadFile.setFont(QFont('Times', 16))
leftLayout.addWidget(loadFile)
# Create Header Information
header = QGroupBox("Imported File Information:")
header.setObjectName("Header")
header.setStyleSheet("""QGroupBox#Header {border: 1px solid gray;
border-radius: 5px; margin-top: 0.5em;
font-size: 18px; font-weight: bold;}
QGroupBox:title {subcontrol-origin: margin;
subcontrol-position: top center; padding: 0px 0px;}""")
headerInfo = QGridLayout()
# Create QLineEdits()
empNum = QLineEdit()
empNum.setPlaceholderText("Employee Number")
empNum.setReadOnly(True)
empNum.setFixedWidth(200)
file = QLineEdit()
file.setPlaceholderText("File selected for conversion")
file.setReadOnly(True)
file.setFixedWidth(200)
testType = QLineEdit()
testType.setPlaceholderText("Test to be converted")
testType.setReadOnly(True)
testType.setFixedWidth(200)
partNum = QLineEdit()
partNum.setPlaceholderText("Part Number of UUT")
partNum.setReadOnly(True)
partNum.setFixedWidth(200)
serialNum = QLineEdit()
serialNum.setPlaceholderText("Serial Number of UUT")
serialNum.setReadOnly(True)
serialNum.setFixedWidth(200)
testStand = QLineEdit()
testStand.setPlaceholderText("Test stand test was performed on")
testStand.setReadOnly(True)
testStand.setFixedWidth(200)
standCal = QLineEdit()
standCal.setPlaceholderText("Calibration date of Test Stand")
standCal.setReadOnly(True)
standCal.setFixedWidth(200)
swBuildName = QLineEdit()
swBuildName.setPlaceholderText("OFP SW Version")
swBuildName.setReadOnly(True)
swBuildName.setFixedWidth(200)
buildName = QLineEdit()
buildName.setPlaceholderText("Relay Emulator Tools SW Version")
buildName.setReadOnly(True)
buildName.setFixedWidth(200)
buildToolsName = QLineEdit()
buildToolsName.setPlaceholderText("OM Build Tools SW Version")
buildToolsName.setReadOnly(True)
buildToolsName.setFixedWidth(200)
supportBuildName = QLineEdit()
supportBuildName.setPlaceholderText("Support Tools SW Version")
supportBuildName.setReadOnly(True)
supportBuildName.setFixedWidth(200)
numFilesGen = QLineEdit()
numFilesGen.setPlaceholderText("Number of ATDS files to be generated")
numFilesGen.setReadOnly(True)
numFilesGen.setFixedWidth(200)
# Create Layout
headerInfo.addWidget(loadFile, 0, 0, 1, 2)
headerInfo.addWidget(QLabel("Employee Number:"), 1, 0)
headerInfo.addWidget(empNum, 1, 1)
headerInfo.addWidget(QLabel("TDR File:"), 2, 0)
headerInfo.addWidget(tdrFile, 2, 1)
headerInfo.addWidget(QLabel("Test Name:"), 3, 0)
headerInfo.addWidget(testType, 3, 1)
headerInfo.addWidget(QLabel("Part Number:"), 4, 0)
headerInfo.addWidget(partNum, 4, 1)
headerInfo.addWidget(QLabel("Serial Number:"), 5, 0)
headerInfo.addWidget(serialNum, 5, 1)
headerInfo.addWidget(QLabel("Test Stand:"), 6, 0)
headerInfo.addWidget(testStand, 6, 1)
headerInfo.addWidget(QLabel("Test Stand Calibration Date:"), 7, 0)
headerInfo.addWidget(standCal, 7, 1)
headerInfo.addWidget(QLabel("OFP SW Version:"), 8, 0)
headerInfo.addWidget(ofpBuildName, 8, 1)
headerInfo.addWidget(QLabel("Relay Emulator Tools SW Version:"), 9, 0)
headerInfo.addWidget(reBuildName, 9, 1)
headerInfo.addWidget(QLabel("OM Build Tools SW Version:"), 10, 0)
headerInfo.addWidget(omBuildToolsName, 10, 1)
headerInfo.addWidget(QLabel("Support Tools SW Version:"), 11, 0)
headerInfo.addWidget(supportBuildName, 11, 1)
headerInfo.addWidget(QLabel("Number of ATDS Files to be Created:"), 12, 0)
headerInfo.addWidget(numFilesGen, 12, 1)
#headerInfo.setRowStretch(13, 1)
# Add Header to Frame
header.setLayout(headerInfo)
leftLayout.addWidget(header)
convertFile = QPushButton("Convert file to ATDS Format")
#convertFiles.clicked.connect(self.convertFile)
convertFile.setFont(QFont('Times', 16))
leftLayout.addWidget(convertFile)
# Add left layout to Main Layout
self.mainLayout.addLayout(leftLayout, 1)
def _createRightLayout(self):
rightLayout = QVBoxLayout()
#Create ATDS File Table
rightLayout.convTable = QTableWidget()
rightLayout.convTable.setRowCount(12)
rightLayout.convTable.setColumnCount(5)
# Table to fit the screen horizontally
rightLayout.convTable.horizontalHeader().setStretchLastSection(True)
rightLayout.convTable.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
rightLayout.convTable.horizontalHeader().setMinimumSectionSize(115)
# Set Column Names
rightLayout.convTable.setHorizontalHeaderLabels(["ATDS File Name:", "ATDS File Desc:", "Conversion Status:",
"Test Section:","Pass / Fail:"])
rightLayout.addWidget(rightLayout.convTable)
# Detailed information of selected files
#Create ATDS File Table
rightLayout.detailedInfoTable = QTableWidget()
rightLayout.detailedInfoTable.setRowCount(10)
rightLayout.detailedInfoTable.setColumnCount(7)
# Table to fit the screen horizontally
rightLayout.detailedInfoTable.horizontalHeader().setStretchLastSection(True)
rightLayout.detailedInfoTable.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
rightLayout.detailedInfoTable.horizontalHeader().setMinimumSectionSize(115)
# Set Column Names
rightLayout.detailedInfoTable.setHorizontalHeaderLabels(["Test Section:", "Test Description:", "Units:",
"Lower Limit:", "Upper Limit:", "Value:", "Pass / Fail:"])
rightLayout.addWidget(rightLayout.detailedInfoTable)
# Add right layout to Main Layout
self.mainLayout.addLayout(rightLayout, 3)
def findFile(self):
doc = QFileDialog.getOpenFileName(self,
"Load TDR File",
r'S:\\EDE\\adv_sys_mfg',
"Excel Files (*.xls*);; LibreOffice Files (*.ods)")
def _createMenu(self):
menu = QMenuBar(self)
# Create Menus
fileMenu = menu.addMenu("&File")
fileMenu.addAction(self.loadAction)
fileMenu.addSeparator()
fileMenu.addAction(self.quit)
aboutMenu = menu.addMenu("&Help")
self.setMenuBar(menu)
def _createActions(self):
self.loadAction = QAction("&Load New File", self)
self.loadAction.setShortcut("Ctrl+N")
self.loadAction.triggered.connect(self.findFile)
self.quit = QAction("Quit", self)
self.quit.setShortcut("Ctrl+Q")
self.quit.triggered.connect(QCoreApplication.instance().quit)
def _createStatusBar(self):
statusBar = QStatusBar()
# Create Status Bar
statusMsg = "Click Load File or Ctrl + N to begin"
statusBar.showMessage(statusMsg)
statusBar.addPermanentWidget(VLine())
# Create Progress Bar
progressBar = QProgressBar()
statusBar.addPermanentWidget(progressBar)
progressBar.setValue(50)
statusBar.addPermanentWidget(VLine())
# Add Date Time Widget to status bar
self.display = QLabel()
statusBar.addPermanentWidget(self.display)
current = QDateTime.currentDateTime()
self.display.setText(current.toString("yyyy-MMM-dd h:mm:ss AP"))
# Create date and time widget
timer = QTimer()
timer.timeout.connect(self.displayTime)
timer.start(1000)
self.displayTime()
self.setStatusBar(statusBar)
def displayTime(self):
current = QDateTime.currentDateTime()
self.display.setText(current.toString("yyyy-MMM-dd h:mm:ss AP"))
def __init__(self, atdsController):
# View Initializer
super().__init__()
# Connect atdsController
self.controller = atdsController()
# Set Window Properties
self.setWindowTitle("TDR File Conversion to ATDS")
self.setMinimumSize(1250, 600)
# Set Central Widget and general layout
self.mainLayout = QHBoxLayout()
self._centralWidget = QWidget(self)
self.setCentralWidget(self._centralWidget)
self._centralWidget.setLayout(self.mainLayout)
# Create a display and buttons
self._createActions()
self._createLeftLayout()
self._createRightLayout()
self._createMenu()
self._createStatusBar()
When I run this code, I get the following error:
"runfile('H:/C4ISR S2 NPI/Projects/Voice of the Process/ATDS TDR Importer - Python/ATDS File Creator/atdsController.py', wdir='H:/C4ISR S2 NPI/Projects/Voice of the Process/ATDS TDR Importer - Python/ATDS File Creator')
Reloaded modules: atdsCreatorUi
Traceback (most recent call last):
File "H:\C4ISR S2 NPI/Projects/Voice of the Process/ATDS TDR Importer - Python/ATDS File Creator\atdsCreatorUi.py", line 51, in
loadFile.clicked.connect(lambda checked, btnTxt = loadFile.text(): self.controller.on_button_click(btnTxt))
AttributeError: 'QMainWindow' object has no attribute on_button_click'
"
From what it looks like is that atdsCreatorUi is not seeing the atdsController but I don't know why.
Any help will be appreciated,
~Dan
I've a stacklayout in a qt5-python program with 3 pages.
I change the page by clicking on three icons and it works perfectly.
import sys
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtWidgets import (
QAction,
QApplication,
QHBoxLayout,
QLabel,
QMainWindow,
QPushButton,
QStackedLayout,
QVBoxLayout,
QWidget,
QStatusBar,
QToolBar,
)
### TESTING CLASS ###
from PyQt5.QtGui import QColor, QPalette
from PyQt5.QtWidgets import QWidget
class Color(QWidget):
def __init__(self, color):
super().__init__()
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
### TESTING CLASS ###
I_INDEX_PAGE_DISC = 0
I_INDEX_PAGE_SONG = 1
I_INDEX_PAGE_INSTRUMENT = 2
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Studio Diary")
self.setWindowIcon(QIcon("img/icon/icone_main_window.png"))
### IMPOSTA DIMENSIONE INTERFACCIA ###
self.resize(900, 300)
### CREA LA BARRA DEGLI STRUMENTI ###
tbMainToolBar = QToolBar("Studio Diary Toolbar")
tbMainToolBar.setIconSize(QSize(64, 64))
tbMainToolBar.setMovable(False)
self.addToolBar(tbMainToolBar)
lstButtonIcon = []
### CREA ICONA DISCO ###
icoDisc = QIcon()
icoDisc.addPixmap(QPixmap("img/icon/toolbar/icon_disc_on.png"))
icoDisc.addPixmap(QPixmap("img/icon/toolbar/icon_disc_sel.png"), QIcon.Disabled)
### CREA BOTTONE DISCO ###
bticDisc = QAction(icoDisc, "Dischi", self)
bticDisc.setStatusTip("Gestisci i dischi")
lstButtonIcon.append(bticDisc)
### CREA ICONA CANZONE ###
icoSong= QIcon()
icoSong.addPixmap(QPixmap("img/icon/toolbar/icon_song_on.png"))
icoSong.addPixmap(QPixmap("img/icon/toolbar/icon_song_sel.png"), QIcon.Disabled)
### CREA BOTTONE DISCO ###
bticSong = QAction(icoSong, "Canzoni", self)
bticSong.setStatusTip("Gestisci le canzoni")
lstButtonIcon.append(bticSong)
### CREA ICONA STRUMENTO ###
icoInstrument = QIcon()
icoInstrument.addPixmap(QPixmap("img/icon/toolbar/icon_instrument_on.png"))
icoInstrument.addPixmap(QPixmap("img/icon/toolbar/icon_instrument_sel.png"), QIcon.Disabled)
### CREA BOTTONE STRUMENTO ###
bticInstrument = QAction(icoInstrument, "Strumenti", self)
bticInstrument.setStatusTip("Gestisci gli strumenthi")
lstButtonIcon.append(bticInstrument)
### AGGIUNGI BOTTONE DISCO ###
bticDisc.triggered.connect(lambda lam_pageDisc: self.activateDiscPage(lstButtonIcon))
tbMainToolBar.addAction(bticDisc)
### AGGIUNGI BOTTONE CANZONE ###
bticSong.triggered.connect(lambda lam_pageSong: self.activateSongPage(lstButtonIcon))
tbMainToolBar.addAction(bticSong)
### AGGIUNGI BOTTONE CANZONE ###
bticInstrument.triggered.connect(lambda lam_pageInstrument: self.activateInstrumentPage(lstButtonIcon))
tbMainToolBar.addAction(bticInstrument)
### CREA IL LAYOUT GENERALE ###
bvloMainPageLayout = QVBoxLayout()
self.stacklayout = QStackedLayout()
bvloMainPageLayout.addLayout(self.stacklayout)
self.stacklayout.addWidget(Color("red"))
self.stacklayout.addWidget(Color("green"))
self.stacklayout.addWidget(Color("yellow"))
wgtBodyApp = QWidget()
wgtBodyApp.setLayout(bvloMainPageLayout)
self.setCentralWidget(wgtBodyApp)
self.setStatusBar(QStatusBar(self))
def buildDiscPage(self, strColor="red"):
bhloDiscPage = QVBoxLayout()
tvAlbumSong = TreeView()
bhloDiscPage.addWidget(tvAlbumSong)
bhloDiscPage.addWidget(QLabel("Song"))
def buildSongPage(self):
bhloSongPage = QHBoxLayout()
self.stacklayout.addWidget(QLabel("cyan"))
def buildInstrumentPage(self):
bhloSongPage = QHBoxLayout()
self.stacklayout.addWidget(QLabel("yellow"))
def activateDiscPage(self,mLstButtonIcon):
### IMPEDISCI CHE LA PAGINA VENGA RICHIAMATA SE E' GIA' STATA SELEZIONATA ###
bticCurrentButton = mLstButtonIcon[I_INDEX_PAGE_DISC]
blnIsEnabled = bticCurrentButton.isEnabled()
if blnIsEnabled == True:
self.buildDiscPage("green")
self.stacklayout.setCurrentIndex(I_INDEX_PAGE_DISC)
bticCurrentButton.setDisabled(True)
self.resetIconButtonActivationStatus(mLstButtonIcon,I_INDEX_PAGE_DISC)
def activateSongPage(self,mLstButtonIcon):
### IMPEDISCI CHE LA PAGINA VENGA RICHIAMATA SE E' GIA' STATA SELEZIONATA ###
bticCurrentButton = mLstButtonIcon[I_INDEX_PAGE_SONG]
blnIsEnabled = bticCurrentButton.isEnabled()
if blnIsEnabled == True:
self.buildSongPage()
self.stacklayout.setCurrentIndex(I_INDEX_PAGE_SONG)
bticCurrentButton.setDisabled(True)
self.resetIconButtonActivationStatus(mLstButtonIcon,I_INDEX_PAGE_SONG)
def activateInstrumentPage(self,mLstButtonIcon):
### IMPEDISCI CHE LA PAGINA VENGA RICHIAMATA SE E' GIA' STATA SELEZIONATA ###
bticCurrentButton = mLstButtonIcon[I_INDEX_PAGE_INSTRUMENT]
blnIsEnabled = bticCurrentButton.isEnabled()
if blnIsEnabled == True:
self.buildInstrumentPage()
self.stacklayout.setCurrentIndex(I_INDEX_PAGE_INSTRUMENT)
mLstButtonIcon[I_INDEX_PAGE_INSTRUMENT].setDisabled(True)
self.resetIconButtonActivationStatus(mLstButtonIcon,I_INDEX_PAGE_INSTRUMENT)
### RESETTA LO STATUS DI ATTIVAZIONE DEI BOTTONI
# === riattiva tutti i bottoni tranne quello corrente ===
def resetIconButtonActivationStatus(self,mLstButtonIcon,mIntCurrent):
for iButton in range (len(mLstButtonIcon)):
btIcSingleButton = mLstButtonIcon [iButton]
if iButton != mIntCurrent:
btIcSingleButton.setEnabled(True)
appMain = QApplication(sys.argv)
winMain = MainWindow()
winMain.show()
appMain.exec_()
When I click on the icon I will open the relative page, using the method activatePage() that recall buildPage()
I would that the page content will be update.
For example: In a page I will query the database or in another one I will pass some parameters to the buildPage() function to change some elements or style in the page.
How should I modify these functions?
[edit]
0
This code works perfectly but I would like to know another thing about it.
I've a layout like the one in the screenshoot.
The treeview is created by a class that builds the tree by querying a database.
I would like to update it when I add a new album. Can I update only the treeview and not all the page (maybe separating in two layouts)? I need to do it in other page of the application so I would learn how to do it.
Everytime I click on the icon/button on the toolbar should I query the database to update the view? In other pages I could add some infos.
(see the image in the answers)
QStackedLayout works with "pages" which are reusable, just like a "tabbed" interface does (in fact, QTabWidget uses a private QStackedWidget, which is based on QStackedLayout).
Considering the fact that pages are reusable, your issue is that you're not actually switching to the pages, but you're continuously adding a new page every time.
While dynamic creation of pages is obviously possible, even for optimization purposes, in your case you don't need that since you only have 3 pages.
Since those 3 pages will probably have their own "static" layout, a better solution is to create separate subclasses for each page, which allows creating specific function to update the data whenever required. This is a far better approach than creating single functions that do almost the same thing when creating/switching pages, and you can have a single interface to access/set the data from and to each page.
This is a possible implementation:
from PyQt5 import QtCore, QtWidgets
class Disco(QtWidgets.QFrame):
def __init__(self):
super().__init__()
self.artista = QtWidgets.QLineEdit()
self.titolo = QtWidgets.QLineEdit()
layout = QtWidgets.QFormLayout(self)
layout.addRow('Artista', self.artista)
layout.addRow('Titolo', self.titolo)
def setData(self, data):
self.artista.setText(data.get('artista', ''))
self.titolo.setText(data.get('titolo', ''))
def getData(self):
return {'artista': self.artista.text(), 'titolo': self.titolo.text()}
class Canzoni(QtWidgets.QFrame):
def __init__(self):
super().__init__()
layout = QtWidgets.QVBoxLayout(self)
self.table = QtWidgets.QTableWidget(0, 2)
self.table.setHorizontalHeaderLabels(('Titolo', 'Durata'))
layout.addWidget(self.table)
self.addButton = QtWidgets.QPushButton('Aggiungi')
layout.addWidget(self.addButton)
self.addButton.clicked.connect(lambda:
self.table.insertRow(self.table.rowCount()))
def setData(self, data):
self.table.clearContents()
canzoni = data.get('canzoni', [])
self.table.setRowCount(len(canzoni))
for row, (titolo, durata) in enumerate(canzoni):
self.table.setItem(row, 0, QtWidgets.QTableWidgetItem(titolo))
durataItem = QtWidgets.QTableWidgetItem()
durataItem.setData(QtCore.Qt.DisplayRole, int(durata))
self.table.setItem(row, 1, durataItem)
def getData(self):
canzoni = []
for row in range(self.table.rowCount()):
canzoni.append([
self.table.item(row, 0).text(),
self.table.item(row, 1).data(QtCore.Qt.DisplayRole),
])
return {'canzoni': canzoni}
class Strumenti(QtWidgets.QFrame):
def __init__(self):
super().__init__()
layout = QtWidgets.QVBoxLayout(self)
self.table = QtWidgets.QTableWidget(0, 2)
layout.addWidget(self.table)
self.table.setHorizontalHeaderLabels(('Artista', 'Strumenti'))
self.table.verticalHeader().hide()
self.addButton = QtWidgets.QPushButton('Aggiungi')
layout.addWidget(self.addButton)
self.addButton.clicked.connect(lambda:
self.table.insertRow(self.table.rowCount()))
def setData(self, data):
self.table.clearContents()
strumenti = data.get('strumenti', [])
self.table.setRowCount(len(strumenti))
for row, (artista, strumento) in enumerate(strumenti):
self.table.setItem(row, 0, QtWidgets.QTableWidgetItem(artista))
self.table.setItem(row, 1, QtWidgets.QTableWidgetItem(strumento))
def getData(self):
strumenti = []
for row in range(self.table.rowCount()):
strumenti.append([
self.table.item(row, 0).text(),
self.table.item(row, 1).text(),
])
return {'strumenti': strumenti}
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.stackWidget = QtWidgets.QStackedWidget()
self.setCentralWidget(self.stackWidget)
self.disco = Disco()
self.stackWidget.addWidget(self.disco)
self.canzoni = Canzoni()
self.stackWidget.addWidget(self.canzoni)
self.strumenti = Strumenti()
self.stackWidget.addWidget(self.strumenti)
self.pages = self.disco, self.canzoni, self.strumenti
self.loadAction = self.menuBar().addAction('Load')
self.loadAction.triggered.connect(self.loadData)
self.saveAction = self.menuBar().addAction('Save')
self.saveAction.triggered.connect(self.saveData)
for i, actionName in enumerate(('Disco', 'Canzoni', 'Strumenti')):
action = self.menuBar().addAction(actionName)
action.setData(i)
self.menuBar().triggered.connect(self.switchPageAction)
self.setStyleSheet('''
Disco {
background: red;
}
Canzoni {
background: green;
}
Strumenti {
background: yellow;
}
''')
self.switchPage(0)
def loadData(self):
data = {
'artista': 'Elio e le Storie Tese',
'titolo': 'Elio Samaga Hukapan Kariyana Turu',
'canzoni': [
['John Holmes', 206],
['Nubi di ieri sul nostro domani odierno', 253],
],
'strumenti': [
['Elio', 'Voci'],
['Rocco', 'Tastiere'],
]
}
for page in self.pages:
page.setData(data)
def saveData(self):
data = {}
for page in self.pages:
data.update(page.getData())
print(data)
def switchPageAction(self, action):
index = action.data()
if index is not None:
self.switchPage(index)
def switchPage(self, index):
self.stackWidget.setCurrentIndex(index)
for action in self.menuBar().actions():
action.setEnabled(action.data() != index)
Note that newly created rows in QTableWidget always return None for item() if no value has been set yet, so the saveFunction() above may throw exceptions, I obviously didn't add all required checkings; it's up to you to add proper data type checking.
Also consider that setting the palette on a parent widget propagates the palette to all its children too, including subchildren, that's why I used stylesheets instead, which allows using a proper selector for the class that requires specific properties; also note that I chose to use QFrame to simplify things, as QWidget doesn't directly support stylesheet drawing. Alternatively, you can use self.setAttribute(QtCore.Qt.WA_StyledBackground).
So, i want to display both the text and the ICON as a menubar item.
I have used the below statement as:
self.helpMenu = menubar1.addMenu(QtGui.QIcon("home.png"),"&TEXT")
But this displays only the icon and not the text.
So need help to fix it
Premise
It seems that, despite Qt provides an addMenu() function to create a menu that has both an icon and text, it is not fully supported.
There is a related and very old bug report on the matter, which has been flagged as closed and "Out of scope". I cannot test it right now, but I'm going to suppose that it's due to the native menubar support, which is mostly intended for macOS and Linux distros that support that feature.
That said, a workaround is possible, and that's done through a QProxyStyle.
It's a bit complex, but it works seamlessly given that:
it's enabled only when the native menubar feature is not used (whether it's available or just disabled);
it uses the 'fusion' style or the default style on Windows;
The trick is to ensure that the proxy returns a correct size for sizeFromContents() that includes both the text and the icon if both exist, and to use the default implementations as much as possible in drawControl() and drawItemText() (which is called from more standard styles).
class MenuProxy(QtWidgets.QProxyStyle):
menuHack = False
alertShown = False
def useMenuHack(self, element, opt, widget):
if (element in (self.CT_MenuBarItem, self.CE_MenuBarItem) and
isinstance(widget, QtWidgets.QMenuBar) and
opt.icon and not opt.icon.isNull() and opt.text):
if not self.alertShown:
if widget.isNativeMenuBar():
# this will probably not be shown...
print('WARNING: menubar items with icons and text not supported for native menu bars')
styleName = self.baseStyle().objectName()
if not 'windows' in styleName and styleName != 'fusion':
print('WARNING: menubar items with icons and text not supported for "{}" style'.format(
styleName))
self.alertShown = True
return True
return False
def sizeFromContents(self, content, opt, size, widget=None):
if self.useMenuHack(content, opt, widget):
# return a valid size that includes both the icon and the text
alignment = (QtCore.Qt.AlignCenter | QtCore.Qt.TextShowMnemonic |
QtCore.Qt.TextDontClip | QtCore.Qt.TextSingleLine)
if not self.proxy().styleHint(self.SH_UnderlineShortcut, opt, widget):
alignment |= QtCore.Qt.TextHideMnemonic
width = (opt.fontMetrics.size(alignment, opt.text).width() +
self.pixelMetric(self.PM_SmallIconSize) +
self.pixelMetric(self.PM_LayoutLeftMargin) * 2)
textOpt = QtWidgets.QStyleOptionMenuItem(opt)
textOpt.icon = QtGui.QIcon()
height = super().sizeFromContents(content, textOpt, size, widget).height()
return QtCore.QSize(width, height)
return super().sizeFromContents(content, opt, size, widget)
def drawControl(self, ctl, opt, qp, widget=None):
if self.useMenuHack(ctl, opt, widget):
# create a new option with no icon to draw a menubar item; setting
# the menuHack allows us to ensure that the icon size is taken into
# account from the drawItemText function
textOpt = QtWidgets.QStyleOptionMenuItem(opt)
textOpt.icon = QtGui.QIcon()
self.menuHack = True
self.drawControl(ctl, textOpt, qp, widget)
self.menuHack = False
# compute the rectangle for the icon and call the default
# implementation to draw it
iconExtent = self.pixelMetric(self.PM_SmallIconSize)
margin = self.pixelMetric(self.PM_LayoutLeftMargin) / 2
top = opt.rect.y() + (opt.rect.height() - iconExtent) / 2
iconRect = QtCore.QRect(opt.rect.x() + margin, top, iconExtent, iconExtent)
pm = opt.icon.pixmap(widget.window().windowHandle(),
QtCore.QSize(iconExtent, iconExtent),
QtGui.QIcon.Normal if opt.state & self.State_Enabled else QtGui.QIcon.Disabled)
self.drawItemPixmap(qp, iconRect, QtCore.Qt.AlignCenter, pm)
return
super().drawControl(ctl, opt, qp, widget)
def drawItemText(self, qp, rect, alignment, palette, enabled, text, role=QtGui.QPalette.NoRole):
if self.menuHack:
margin = (self.pixelMetric(self.PM_SmallIconSize) +
self.pixelMetric(self.PM_LayoutLeftMargin))
rect = rect.adjusted(margin, 0, 0, 0)
super().drawItemText(qp, rect, alignment, palette, enabled, text, role)
class Test(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
menu = self.menuBar().addMenu(QtGui.QIcon.fromTheme('document-new'), 'File')
menu.addAction(QtGui.QIcon.fromTheme('application-exit'), 'Quit')
self.menuBar().addMenu(QtGui.QIcon.fromTheme('edit-cut'), 'Edit')
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle(MenuProxy(QtWidgets.QStyleFactory.create('fusion')))
# or, for windows systems:
# app.setStyle(MenuProxy())
test = Test()
test.show()
sys.exit(app.exec_())
I have the same story with Windows 7 and PyQt 5.12.2 and tried to solve it like this:
import sys
from PyQt5.Qt import *
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.centralWidget = QLabel("Hello, World")
self.centralWidget.setAlignment(Qt.AlignCenter)
self.setCentralWidget(self.centralWidget)
menuBar = QMenuBar(self)
self.setMenuBar(menuBar)
self.helpContentAction = QAction(QIcon("img/readMe.png"), "&Help Content", self)
self.aboutAction = QAction("&About", self)
# helpMenu = menuBar.addMenu(QIcon("img/qtlogo.png"), "&Help")
helpMenu = menuBar.addMenu(" &Help") # +++
# ^^^^^^^^^^^^
helpMenu.addAction(self.helpContentAction)
helpMenu.addAction(self.aboutAction)
qss = """
QMenuBar {
background-color: qlineargradient(
x1:0, y1:0, x2:0, y2:1,
stop:0 lightgray, stop:1 darkgray
);
}
QMenuBar::item {
background-color: darkgray;
padding: 1px 5px 1px -25px; /* +++ */
background: transparent;
image: url(img/qtlogo.png); /* +++ * /
}
QMenuBar::item:selected {
background-color: lightgray;
}
QMenuBar::item:pressed {
background: lightgray;
}
"""
if __name__ == "__main__":
app = QApplication(sys.argv)
# app.setStyle('Fusion')
app.setStyleSheet(qss) # +++
app.setFont(QFont("Times", 10, QFont.Bold))
win = Window()
win.setWindowTitle("Python Menus")
win.resize(600, 350)
win.show()
sys.exit(app.exec_())
The code:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import*
from PyQt5.QtGui import*
from PyQt5 import QtGui
from PyQt5.QtPrintSupport import *
class Pencere(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(100,50,1080,1080)
self.setWindowIcon(QtGui.QIcon("note.png"))
self.setWindowTitle("M Content Re-Writer")
self.widget = QWidget(self)
self.widget.setObjectName("widget")
self.texteditor()
vbox2 = QVBoxLayout(self.widget)
vbox2.addWidget(self.button, alignment=Qt.AlignLeft)
vbox2.addWidget(self.editor, alignment=Qt.AlignLeft | Qt.AlignTop)
vbox = QVBoxLayout(self)
vbox.setContentsMargins(0, 0, 0, 0)
vbox.addWidget(self.widget)
def texteditor(self):
self.editor = QTextEdit()
self.editor.resize(500, 500)
self.editor.move(5,40)
self.button = QPushButton("re-write")
self.button.setFont(QFont('Segoe Script', 11))
self.button.setStyleSheet("border : 2px lemonchiffon; border-style : solid")
self.button.clicked.connect(self.function)
def function(self):
text = self.editor.toPlainText() # editor'de yazan yaziyi al
# path, _ = QFileDialog.getSaveFileName(self, "Save File", "", "Text documents (*.txt);All files (*.*)")
if not text: # == "":
print("none")
return
# else:
path, _ = QFileDialog.getSaveFileName(
self,
"Save file",
"",
"Text documents (*.txt);All files (*.*)")
if path:
with open(path, 'w') as murti:
murti.write(text)
qss = """
#widget {
border-image: url(2.jpg) 0 0 0 0 stretch stretch;
}
QPushButton {background-color : yellow;}
QPushButton:hover:pressed {background-color: red;}
QPushButton:hover {background-color: #0ff;}
QTextEdit {
background-image: url("hand.jpeg");
min-width: 400px;
min-height: 400px;
border: 2px solid black;
color:white;
font-size:24px;
}
"""
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet(qss)
demo = Pencere()
demo.show()
sys.exit(app.exec_())
Hello, How can I make the background of the title of the GUI window appear transparent instead of white? In addition, I want to ask this: How can I change the color and font style of the M Content Re-Writer text in the title? I also added a screenshot to make it better. Thanks for your help.
Since you are modifying the window title so much, I believe it would be helpful to simply remove it create a custom one.
self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
This code gets rid of the window frame (which removes the title bar.)
Now, we just need to create our own title bar. This will look something like:
self.topMenu = QLabel(self)
self.topMenu.setGeometry(0, 0, 1920, 60)
self.topMenu.setStyleSheet("background-color: rgba(255,255,255, 120);")
This code creates a blank bar for everything to rest on.
From here, you just need to create a label for text, followed by three buttons for closing, minimizing, and full screening the window.
I have to create a custom widget that looks like the following:
custom_widget_sketch
Each custom widget is a representation of one LIPO battery, and displays the battery volatge (V), status text (charging, discharging, etc), serial number of the battery (S/N) and three status LEDs (yellow, green and red)
After I have created the custom widget I need to add 30 of these in a grid of 6*5. My assumption here is that once I have created that custom widget it should be as simple as adding say a QPushButton in a QGridLayout like so:
custom_layput = QGridLayout()
custom_layout.addWidget(custom_widget, 0, 0)
custom_layout.addWidget(custom_widget, 0, 1)
.
.
.
custom_layout.addWidget(custom_widget, 6, 5)
The final screen would look like this:
main_window_sketch
Considering all of these requirements I have the following questions:
Will I able able to create such a complex/rich custom widget using PyQt5? Is it doable?
Is this the correct approach to create the custom widget: first draw a square using QPainter (this is the blue square in the custom_widget_sketch), then add QLineEdits to dispaly the voltage (V) text, serial number (S/N) text and the Status text, add a QLabel for displaying the "V", "S/N" and "STATUS" labels in the custom widget, then draw the three circles: one each for the yellow, green and red LEDs, then use a combination of QVBoxLayout and QHBoxLayout to arrange the QLineEdits, QLabels, the square and the circles (LED indicators)
How do I package this custom widget such that I can simply add it to a layout like I would add a QPushButton or a QLineEdit?
PS: The custom_widget_sketch also contains a line and a square with three lines inside it in the top left corner. This is to depict the connector for the LIPO battery. It may be too complex to implement that right now. So I would be happy even if I am able to implement everything other than these two elements
I have been through a few SO questions but they all refer to one tutorial, which is not my end goal.
I would appreciate any code snippets, general outline of code/steps to follow or links to any articles/tutorials that create custom widgets similar to the one I wish to create.
Python code for the custom widget I ended up creating. The widget looks as follows:
from PyQt5.QtGui import QPainter, QPen,QBrush,QColor
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout,QPushButton, QLineEdit, QLabel, QVBoxLayout, QHBoxLayout, QSizePolicy, QGroupBox
import sys
class BatteryStatusWidget(QWidget):
def __init__(self):
super(BatteryStatusWidget, self).__init__()
#Voltage widgets
self.voltage_text = QLineEdit()
self.voltage_text.setReadOnly(True)
self.voltage_label = QLabel("V")
self.voltage_label.setStyleSheet("QLabel {color : white}")
#Status widgets
self.status_text = QLineEdit()
self.status_text.setReadOnly(True)
self.status_label = QLabel("STATUS")
self.status_label_font = QtGui.QFont()
self.status_label_font.setPointSize(12)
self.status_label.setFont(self.status_label_font)
self.status_label.setAlignment(QtCore.Qt.AlignCenter)
self.status_label.setStyleSheet("QLabel {color : white}")
#Serial number
self.serial_number_text = QLineEdit()
self.serial_number_label = QLabel("S/N")
#LED widgets
self.yellow_led_label = QLabel()
self.yellow_led_label.setStyleSheet("QLabel {background-color : yellow; border-color : black; border-width : 1px; border-style : solid; border-radius : 10px; min-height: 20px; min-width: 20px}")
self.green_led_label = QLabel()
self.green_led_label.setStyleSheet("QLabel {background-color : green; border-color : black; border-width : 1px; border-style : solid; border-radius : 10px; min-height: 20px; min-width: 20px}")
self.red_led_label = QLabel()
self.red_led_label.setStyleSheet("QLabel {background-color : red; border-color : black; border-width : 1px; border-style : solid; border-radius : 10px; min-height: 20px; min-width: 20px}")
#Number Identifier Label
#This label is for tagging the widget with the same label as on the PCB
self.number_label = QLabel("Test")
self.number_label.setAlignment(QtCore.Qt.AlignCenter)
self.number_label_font = QtGui.QFont()
self.number_label_font.setPointSize(12)
self.number_label_font.setBold(True)
self.number_label.setFont(self.number_label_font)
#Layouts
#voltage layout
self.voltage_layout = QHBoxLayout()
self.voltage_layout.addWidget(self.voltage_text)
self.voltage_layout.addWidget(self.voltage_label)
#Serial number layout
self.serial_num_layout = QHBoxLayout()
self.serial_num_layout.addWidget(self.serial_number_label)
self.serial_num_layout.addWidget(self.serial_number_text)
#Voltage and status box layouts
self.blue_container = QWidget()
self.blue_container.setStyleSheet("background-color:rgb(77, 122, 194);")
self.blue_box_layout = QVBoxLayout()
self.blue_box_layout.addLayout(self.voltage_layout)
self.blue_box_layout.addWidget(self.status_text)
self.blue_box_layout.addWidget(self.status_label)
self.blue_container.setLayout(self.blue_box_layout)
#Blue box+ serial num layout
self.non_led_layout = QVBoxLayout()
#self.non_led_layout.addWidget(self.number_label)
self.non_led_layout.addWidget(self.blue_container)
self.non_led_layout.addLayout(self.serial_num_layout)
#LED layout
self.led_layout = QVBoxLayout()
self.led_layout.addWidget(self.yellow_led_label)
self.led_layout.addWidget(self.green_led_label)
self.led_layout.addWidget(self.red_led_label)
self.led_layout.addStretch(1)
#Main Layout
self.main_layout = QHBoxLayout()
self.main_layout.addLayout(self.non_led_layout)
self.main_layout.addLayout(self.led_layout)
#Main group box
self.main_group_box = QGroupBox()
self.main_group_box.setStyleSheet("QGroupBox{font-size: 10px}")
self.main_group_box.setTitle("Chan #")
self.main_group_box.setLayout(self.main_layout)
#Outer main layout to accomodate the group box
self.outer_main_layout = QVBoxLayout()
self.outer_main_layout.addWidget(self.main_group_box)
#Set the main layout
self.setLayout(self.outer_main_layout)
self.setWindowTitle("Battery Widget")
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = BatteryStatusWidget()
main_window.show()
app.exec_()
I was able to easily create 30 instances of the custom widget and add it to a QGridLayout as I posted in my question. The final GUI screen looks as follows:
There's no need to use QPainter for the blue square, as you can use stylesheets for your whole widget, the trick is to use selectors.
I tried to create your widget and used this stylesheet:
Battery {
background-color: white;
}
QFrame#statusFrame {
background-color: rgb(64, 112, 190);
}
QFrame#statusFrame QLabel {
color: white;
font-weight: bold;
font-size: 24pt;
}
QLineEdit {
border: 1px solid black;
font-size: 24pt;
}
#serialLabel {
font-weight: bold;
font-size: 16pt;
}
I created a "container" QWidget, the status rectangle is actually a QFrame with its own layout, which I named statusFrame (you can set it in designer, or by means of setObjectName(str)).
By using object names and child selectors, I was able to set specific fonts for its labels by using the QFrame#statusFrame QLabel selector (which means "apply to each QLabel that is a child of a QFrame"); I also set the serialLabel object name to the s/n label, allowing me to set a different font size.
You can do this from code or using designer, just remember to set the right object names and parent/children hierarchy.
I was able to draw the "connector" part too, which requires to set fixed margins to the main widget:
class Battery(QtWidgets.QWidget):
connPath = QtGui.QPainterPath()
connPath.addRect(30, 10, 40, 28)
connPath.moveTo(30, 16)
connPath.lineTo(45, 16)
connPath.moveTo(30, 24)
connPath.lineTo(45, 24)
connPath.moveTo(30, 32)
connPath.lineTo(45, 32)
cablePen = QtGui.QColor(77, 122, 194)
def __init__(self):
QtWidgets.QWidget.__init__(self)
# the following is only if you create the whole widget from code,
# otherwise ensure to set both widget and layout contentsMargins
# accordingly in designer
self.setContentsMargins(25, 50, 10, 10)
layout = QtWidgets.QGridLayout()
self.setLayout(layout)
layout.setContentsMargins(0, 0, 0, 0)
# ...
def paintEvent(self, event):
qp = QtGui.QPainter(self)
qp.setRenderHints(qp.Antialiasing)
qp.translate(.5, .5)
qp.drawPath(self.connPath)
qp.setPen(self.cablePen)
cablePath = QtGui.QPainterPath()
cablePath.moveTo(30, 24)
top = self.statusFrame.geometry().top()
cablePath.quadTo(0, top + 20, 25, top + 40)
qp.drawPath(cablePath)
As you can see, it's almost the same as yours.