I trying to make the ui with rounded corners on a QMainWindow with Qt Designer by also adding a custom title bar.
I'm using python and pyside 6: when i use no .ui file it works fine.
Whenever i load the ui file and try to apply the custom titlebar plus the rounded corners effect everything breaks.
Also what is the difference between loading a ui file and writing by code all the element?
Thank you all!
from PySide6.QtWidgets import (
QApplication,
QWidget,
QHBoxLayout,
QLabel,
QVBoxLayout,
QTextEdit,
QToolButton,
QStyle,
QPushButton,
QMainWindow,
)
import sys, os
from PySide6.QtCore import Qt, QSize, QEvent, QRect
from PySide6.QtGui import QPalette
from PySide6 import QtGui, QtCore
from qt_material import apply_stylesheet
from PySide6.QtUiTools import QUiLoader
os.chdir(os.path.dirname(__file__))
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.main = QUiLoader().load("test.ui", self)
self.selected_filter = None
apply_stylesheet(self.main, theme="my_theme.xml")
self.main.setWindowFlags(self.main.windowFlags() | QtCore.Qt.FramelessWindowHint)
self.main.setAttribute(Qt.WA_TranslucentBackground)
self.titleBar = MyBar(self.main)
self.setContentsMargins(0, self.titleBar.height(), 0, 0)
# self.resize(640, self.titleBar.height() + 480)
self.backgroundColor = QtGui.QColor("#020b1a")
self.foregroundColor = QtGui.QColor("#1f2e60")
self.borderRadius = 5
def changeEvent(self, event):
if event.type() == QEvent.WindowStateChange:
self.titleBar.windowStateChanged(self.windowState())
def resizeEvent(self, event):
self.titleBar.resize(self.width(), self.titleBar.height())
def paintEvent(self, event):
# get current window size
s = self.size()
qp = QtGui.QPainter()
qp.begin(self)
qp.setRenderHint(QtGui.QPainter.Antialiasing, True)
qp.setPen(self.foregroundColor)
qp.setBrush(self.backgroundColor)
qp.drawRoundedRect(0, 0, s.width(), s.height(), self.borderRadius, self.borderRadius)
qp.end()
class MyBar(QWidget):
clickPos = None
def __init__(self, parent):
super(MyBar, self).__init__(parent)
self.setAutoFillBackground(True)
# self.setBackgroundRole(QPalette.Shadow)
# alternatively:
palette = self.palette()
palette.setColor(QPalette.Window, Qt.black)
palette.setColor(QPalette.WindowText, Qt.white)
self.setPalette(palette)
layout = QHBoxLayout(self)
layout.setContentsMargins(1, 1, 1, 1)
layout.addStretch()
self.title = QLabel("My Own Bar", self, alignment=Qt.AlignLeft | Qt.AlignVCenter)
# if setPalette() was used above, this is not required
style = self.style()
ref_size = self.fontMetrics().height()
ref_size += style.pixelMetric(QStyle.PM_ButtonMargin) * 2
self.setMaximumHeight(ref_size + 2)
btn_size = QSize(ref_size, ref_size)
for target in ("min", "normal", "max", "close"):
btn = QPushButton(self, focusPolicy=Qt.NoFocus)
layout.addWidget(btn)
btn.setFixedSize(btn_size)
iconType = getattr(QStyle, f"SP_TitleBar{target.capitalize()}Button")
ico = style.standardIcon(iconType)
btn.setIcon(style.standardIcon(iconType))
colorHover = "#ffb900"
colorNormal = "#020b1a"
btn.setStyleSheet(
f"""
QPushButton {{
border-color: #020b1a;
background-color: {colorNormal};
}}
QPushButton:hover {{
background-color: {colorHover}
}}
"""
)
signal = getattr(self, f"{target}Clicked")
btn.clicked.connect(signal)
setattr(self, f"{target}Button", btn)
self.normalButton.hide()
self.maxButton.hide()
self.updateTitle(parent.windowTitle())
parent.windowTitleChanged.connect(self.updateTitle)
def updateTitle(self, title=None):
if title is None:
title = self.window().windowTitle()
width = self.title.width()
width -= self.style().pixelMetric(QStyle.PM_LayoutHorizontalSpacing) * 2
self.title.setText(self.fontMetrics().elidedText(title, Qt.ElideRight, width))
def windowStateChanged(self, state):
self.normalButton.setVisible(state == Qt.WindowMaximized)
self.maxButton.setVisible(state != Qt.WindowMaximized)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.clickPos = event.windowPos().toPoint()
def mouseMoveEvent(self, event):
if self.clickPos is not None:
self.window().move(event.globalPos() - self.clickPos)
def mouseReleaseEvent(self, QMouseEvent):
self.clickPos = None
def closeClicked(self):
self.window().close()
def maxClicked(self):
self.window().showMaximized()
def normalClicked(self):
self.window().showNormal()
def minClicked(self):
self.window().showMinimized()
def resizeEvent(self, event):
self.title.resize(self.minButton.x(), self.height())
self.updateTitle()
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWindow()
mw.main.show()
mw.setWindowTitle("My custom window with a very, very long title")
sys.exit(app.exec())
main.py
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QToolButton" name="toolButton">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>371</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>300</x>
<y>270</y>
<width>104</width>
<height>87</height>
</rect>
</property>
</widget>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
test.ui