Кастомный Title Bar, с помощью PyQt5 в Qt Designer
state_window.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'state_window.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QWidget
class Ui_MainWindow(QtWidgets.QMainWindow):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1440, 950)
MainWindow.setStyleSheet("*{\n"
" font: 19pt \"Arial\";\n"
" color: #fff;\n"
"}\n"
"\n"
"QWidget{\n"
" background-color: #9B9B9A;\n"
" border-radius: 10px;\n"
"}\n"
"\n"
"#practical_btn,\n"
"#settings_btn,\n"
"#achiev_btn{\n"
" background-color: #E88327;\n"
" border-radius: 10px;\n"
"}\n"
"\n"
"#state_btn{\n"
" background-color: #FFAA5C;\n"
" border-radius: 10px;\n"
"}\n"
"\n"
"#achiev_btn:hover,\n"
"#practical_btn:hover,\n"
"#settings_btn:hover,\n"
"#state_btn:hover{\n"
" background-color: #FFAA5C;\n"
"}\n"
"\n"
"#edit_students,\n"
"#edit_streams\n"
"{\n"
" image: url(:/image/pen.png);\n"
" border: none;\n"
"}\n"
"\n"
"#table,\n"
"#streams\n"
"{\n"
" background-color: #E88327;\n"
" border-radius: 10px;\n"
"}\n"
"\n"
"#btn_close:hover,\n"
"#btn_min:hover,\n"
"#btn_max:hover\n"
"{\n"
" background-color:#ccc;\n"
" border-radius: 0px;\n"
"}")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setStyleSheet("")
self.centralwidget.setObjectName("centralwidget")
self.streams = QtWidgets.QListWidget(self.centralwidget)
self.streams.setGeometry(QtCore.QRect(30, 170, 256, 681))
self.streams.setStyleSheet("")
self.streams.setObjectName("streams")
self.edit_streams = QtWidgets.QPushButton(self.centralwidget)
self.edit_streams.setGeometry(QtCore.QRect(195, 137, 18, 18))
self.edit_streams.setCursor(
QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.edit_streams.setStyleSheet("")
self.edit_streams.setText("")
self.edit_streams.setObjectName("edit_streams")
self.table = QtWidgets.QTableWidget(self.centralwidget)
self.table.setGeometry(QtCore.QRect(300, 170, 1111, 681))
self.table.setStyleSheet("")
self.table.setObjectName("table")
self.table.setColumnCount(0)
self.table.setRowCount(0)
self.edit_students = QtWidgets.QPushButton(self.centralwidget)
self.edit_students.setGeometry(QtCore.QRect(945, 142, 18, 18))
self.edit_students.setCursor(
QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.edit_students.setStyleSheet("")
self.edit_students.setText("")
self.edit_students.setObjectName("edit_students")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(830, 135, 111, 31))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(110, 135, 81, 21))
self.label_2.setObjectName("label_2")
self.achiev_btn = QtWidgets.QPushButton(self.centralwidget)
self.achiev_btn.setEnabled(True)
self.achiev_btn.setGeometry(QtCore.QRect(470, 50, 221, 50))
self.achiev_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.achiev_btn.setStyleSheet("")
self.achiev_btn.setObjectName("achiev_btn")
self.state_btn = QtWidgets.QPushButton(self.centralwidget)
self.state_btn.setGeometry(QtCore.QRect(160, 50, 221, 50))
self.state_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.state_btn.setObjectName("state_btn")
self.practical_btn = QtWidgets.QPushButton(self.centralwidget)
self.practical_btn.setGeometry(QtCore.QRect(780, 50, 221, 50))
self.practical_btn.setCursor(
QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.practical_btn.setObjectName("practical_btn")
self.settings_btn = QtWidgets.QPushButton(self.centralwidget)
self.settings_btn.setGeometry(QtCore.QRect(1090, 50, 221, 50))
self.settings_btn.setCursor(
QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.settings_btn.setObjectName("settings_btn")
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(0, 0, 1441, 41))
self.widget.setObjectName("widget")
self.btn_close = QtWidgets.QPushButton(self.widget)
self.btn_close.setGeometry(QtCore.QRect(1310, 10, 75, 23))
self.btn_close.setObjectName("btn_close")
self.btn_max = QtWidgets.QPushButton(self.widget)
self.btn_max.setGeometry(QtCore.QRect(1200, 10, 75, 23))
self.btn_max.setObjectName("btn_max")
self.btn_min = QtWidgets.QPushButton(self.widget)
self.btn_min.setGeometry(QtCore.QRect(1090, 10, 75, 23))
self.btn_min.setObjectName("btn_min")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1440, 34))
self.menubar.setStyleSheet("")
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setStyleSheet("")
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "студенты"))
self.label_2.setText(_translate("MainWindow", "потоки"))
self.achiev_btn.setText(_translate("MainWindow", "достижения"))
self.state_btn.setText(_translate("MainWindow", "ведомость"))
self.practical_btn.setText(_translate("MainWindow", "практические"))
self.settings_btn.setText(_translate("MainWindow", "настройки"))
self.btn_close.setText(_translate("MainWindow", "3"))
self.btn_max.setText(_translate("MainWindow", "2"))
self.btn_min.setText(_translate("MainWindow", "1"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
FramelessWindow.py (все точь-в-точь как из 1 скинутого вами вопроса)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt, pyqtSignal, QPoint
from PyQt5.QtGui import QFont, QEnterEvent, QPainter, QColor, QPen
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QSpacerItem, QSizePolicy, QPushButton)
class TitleBar(QWidget):
# Сигнал минимизации окна
windowMinimumed = pyqtSignal()
# увеличить максимальный сигнал окна
windowMaximumed = pyqtSignal()
# сигнал восстановления окна
windowNormaled = pyqtSignal()
# сигнал закрытия окна
windowClosed = pyqtSignal()
# Окно мобильных
windowMoved = pyqtSignal(QPoint)
# Сигнал Своя Кнопка +++
signalButtonMy = pyqtSignal()
def __init__(self, *args, **kwargs):
super(TitleBar, self).__init__(*args, **kwargs)
# Поддержка настройки фона qss
self.setAttribute(Qt.WA_StyledBackground, True)
self.mPos = None
self.iconSize = 20 # Размер значка по умолчанию
# Установите цвет фона по умолчанию, иначе он будет прозрачным из-за влияния родительского окна
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(palette.Window, QColor(240, 240, 240))
self.setPalette(palette)
# макет
layout = QHBoxLayout(self, spacing=0)
layout.setContentsMargins(0, 0, 0, 0)
# значок окна
self.iconLabel = QLabel(self)
# self.iconLabel.setScaledContents(True)
layout.addWidget(self.iconLabel)
# название окна
self.titleLabel = QLabel(self)
self.titleLabel.setMargin(2)
layout.addWidget(self.titleLabel)
# Средний телескопический бар
layout.addSpacerItem(QSpacerItem(
40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
# Использовать шрифты Webdings для отображения значков
font = self.font() or QFont()
font.setFamily('Webdings')
# Своя Кнопка ++++++++++++++++++++++++++
self.buttonMy = QPushButton(
'@', self, clicked=self.showButtonMy, font=font, objectName='buttonMy')
layout.addWidget(self.buttonMy)
# Свернуть кнопку
self.buttonMinimum = QPushButton(
'0', self, clicked=self.windowMinimumed.emit, font=font, objectName='buttonMinimum')
layout.addWidget(self.buttonMinimum)
# Кнопка Max / restore
self.buttonMaximum = QPushButton(
'1', self, clicked=self.showMaximized, font=font, objectName='buttonMaximum')
layout.addWidget(self.buttonMaximum)
# Кнопка закрытия
self.buttonClose = QPushButton(
'r', self, clicked=self.windowClosed.emit, font=font, objectName='buttonClose')
layout.addWidget(self.buttonClose)
# начальная высота
self.setHeight()
# +++ Вызывается по нажатию кнопки buttonMy
def showButtonMy(self):
print("Своя Кнопка ")
self.signalButtonMy.emit()
def showMaximized(self):
if self.buttonMaximum.text() == '1':
# Максимизировать
self.buttonMaximum.setText('2')
self.windowMaximumed.emit()
else: # Восстановить
self.buttonMaximum.setText('1')
self.windowNormaled.emit()
def setHeight(self, height=38):
""" Установка высоты строки заголовка """
self.setMinimumHeight(height)
self.setMaximumHeight(height)
# Задайте размер правой кнопки ?
self.buttonMinimum.setMinimumSize(height, height)
self.buttonMinimum.setMaximumSize(height, height)
self.buttonMaximum.setMinimumSize(height, height)
self.buttonMaximum.setMaximumSize(height, height)
self.buttonClose.setMinimumSize(height, height)
self.buttonClose.setMaximumSize(height, height)
self.buttonMy.setMinimumSize(height, height)
self.buttonMy.setMaximumSize(height, height)
def setTitle(self, title):
""" Установить заголовок """
self.titleLabel.setText(title)
def setIcon(self, icon):
""" настройки значокa """
self.iconLabel.setPixmap(icon.pixmap(self.iconSize, self.iconSize))
def setIconSize(self, size):
""" Установить размер значка """
self.iconSize = size
def enterEvent(self, event):
self.setCursor(Qt.ArrowCursor)
super(TitleBar, self).enterEvent(event)
def mouseDoubleClickEvent(self, event):
super(TitleBar, self).mouseDoubleClickEvent(event)
self.showMaximized()
def mousePressEvent(self, event):
""" Событие клика мыши """
if event.button() == Qt.LeftButton:
self.mPos = event.pos()
event.accept()
def mouseReleaseEvent(self, event):
''' Событие отказов мыши '''
self.mPos = None
event.accept()
def mouseMoveEvent(self, event):
if event.buttons() == Qt.LeftButton and self.mPos:
self.windowMoved.emit(self.mapToGlobal(event.pos() - self.mPos))
event.accept()
# Перечислить верхнюю левую, нижнюю правую и четыре неподвижные точки
Left, Top, Right, Bottom, LeftTop, RightTop, LeftBottom, RightBottom = range(8)
class FramelessWindow(QWidget):
# Четыре периметра
Margins = 5
def __init__(self, *args, **kwargs):
super(FramelessWindow, self).__init__(*args, **kwargs)
self._pressed = False
self.Direction = None
# Фон прозрачный
self.setAttribute(Qt.WA_TranslucentBackground, True)
# Нет границы
self.setWindowFlag(Qt.FramelessWindowHint)
# Отслеживание мыши
self.setMouseTracking(True)
# макет
layout = QVBoxLayout(self, spacing=0)
# Зарезервировать границы для изменения размера окна без полей
layout.setContentsMargins(
self.Margins, self.Margins, self.Margins, self.Margins)
# Панель заголовка
self.titleBar = TitleBar(self)
layout.addWidget(self.titleBar)
# слот сигнала
self.titleBar.windowMinimumed.connect(self.showMinimized)
self.titleBar.windowMaximumed.connect(self.showMaximized)
self.titleBar.windowNormaled.connect(self.showNormal)
self.titleBar.windowClosed.connect(self.close)
self.titleBar.windowMoved.connect(self.move)
self.windowTitleChanged.connect(self.titleBar.setTitle)
self.windowIconChanged.connect(self.titleBar.setIcon)
def setTitleBarHeight(self, height=38):
""" Установка высоты строки заголовка """
self.titleBar.setHeight(height)
def setIconSize(self, size):
""" Установка размера значка """
self.titleBar.setIconSize(size)
def setWidget(self, widget):
""" Настройте свои собственные элементы управления """
if hasattr(self, '_widget'):
return
self._widget = widget
# Установите цвет фона по умолчанию, иначе он будет прозрачным из-за влияния родительского окна
self._widget.setAutoFillBackground(True)
palette = self._widget.palette()
palette.setColor(palette.Window, QColor(240, 240, 240))
self._widget.setPalette(palette)
self._widget.installEventFilter(self)
self.layout().addWidget(self._widget)
def move(self, pos):
if self.windowState() == Qt.WindowMaximized or self.windowState() == Qt.WindowFullScreen:
# Максимизировать или полноэкранный режим не допускается
return
super(FramelessWindow, self).move(pos)
def showMaximized(self):
""" Чтобы максимизировать, удалите верхнюю, нижнюю, левую и правую границы.
Если вы не удалите его, в пограничной области будут пробелы. """
super(FramelessWindow, self).showMaximized()
self.layout().setContentsMargins(0, 0, 0, 0)
def showNormal(self):
""" Восстановить, сохранить верхнюю и нижнюю левую и правую границы,
иначе нет границы, которую нельзя отрегулировать """
super(FramelessWindow, self).showNormal()
self.layout().setContentsMargins(
self.Margins, self.Margins, self.Margins, self.Margins)
def eventFilter(self, obj, event):
""" Фильтр событий, используемый для решения мыши в других элементах
управления и восстановления стандартного стиля мыши """
if isinstance(event, QEnterEvent):
self.setCursor(Qt.ArrowCursor)
return super(FramelessWindow, self).eventFilter(obj, event)
def paintEvent(self, event):
""" Поскольку это полностью прозрачное фоновое окно, жесткая для поиска
граница с прозрачностью 1 рисуется в событии перерисовывания, чтобы отрегулировать размер окна. """
super(FramelessWindow, self).paintEvent(event)
painter = QPainter(self)
painter.setPen(QPen(QColor(255, 255, 255, 1), 2 * self.Margins))
painter.drawRect(self.rect())
def mousePressEvent(self, event):
""" Событие клика мыши """
super(FramelessWindow, self).mousePressEvent(event)
if event.button() == Qt.LeftButton:
self._mpos = event.pos()
self._pressed = True
def mouseReleaseEvent(self, event):
''' Событие отказов мыши '''
super(FramelessWindow, self).mouseReleaseEvent(event)
self._pressed = False
self.Direction = None
def mouseMoveEvent(self, event):
""" Событие перемещения мыши """
super(FramelessWindow, self).mouseMoveEvent(event)
pos = event.pos()
xPos, yPos = pos.x(), pos.y()
wm, hm = self.width() - self.Margins, self.height() - self.Margins
if self.isMaximized() or self.isFullScreen():
self.Direction = None
self.setCursor(Qt.ArrowCursor)
return
if event.buttons() == Qt.LeftButton and self._pressed:
self._resizeWidget(pos)
return
if xPos <= self.Margins and yPos <= self.Margins:
# Верхний левый угол
self.Direction = LeftTop
self.setCursor(Qt.SizeFDiagCursor)
elif wm <= xPos <= self.width() and hm <= yPos <= self.height():
# Нижний правый угол
self.Direction = RightBottom
self.setCursor(Qt.SizeFDiagCursor)
elif wm <= xPos and yPos <= self.Margins:
# верхний правый угол
self.Direction = RightTop
self.setCursor(Qt.SizeBDiagCursor)
elif xPos <= self.Margins and hm <= yPos:
# Нижний левый угол
self.Direction = LeftBottom
self.setCursor(Qt.SizeBDiagCursor)
elif 0 <= xPos <= self.Margins and self.Margins <= yPos <= hm:
# Влево
self.Direction = Left
self.setCursor(Qt.SizeHorCursor)
elif wm <= xPos <= self.width() and self.Margins <= yPos <= hm:
# Право
self.Direction = Right
self.setCursor(Qt.SizeHorCursor)
elif self.Margins <= xPos <= wm and 0 <= yPos <= self.Margins:
# выше
self.Direction = Top
self.setCursor(Qt.SizeVerCursor)
elif self.Margins <= xPos <= wm and hm <= yPos <= self.height():
# ниже
self.Direction = Bottom
self.setCursor(Qt.SizeVerCursor)
def _resizeWidget(self, pos):
""" Отрегулируйте размер окна """
if self.Direction == None:
return
mpos = pos - self._mpos
xPos, yPos = mpos.x(), mpos.y()
geometry = self.geometry()
x, y, w, h = geometry.x(), geometry.y(), geometry.width(), geometry.height()
if self.Direction == LeftTop: # Верхний левый угол
if w - xPos > self.minimumWidth():
x += xPos
w -= xPos
if h - yPos > self.minimumHeight():
y += yPos
h -= yPos
elif self.Direction == RightBottom: # Нижний правый угол
if w + xPos > self.minimumWidth():
w += xPos
self._mpos = pos
if h + yPos > self.minimumHeight():
h += yPos
self._mpos = pos
elif self.Direction == RightTop: # верхний правый угол
if h - yPos > self.minimumHeight():
y += yPos
h -= yPos
if w + xPos > self.minimumWidth():
w += xPos
self._mpos.setX(pos.x())
elif self.Direction == LeftBottom: # Нижний левый угол
if w - xPos > self.minimumWidth():
x += xPos
w -= xPos
if h + yPos > self.minimumHeight():
h += yPos
self._mpos.setY(pos.y())
elif self.Direction == Left: # Влево
if w - xPos > self.minimumWidth():
x += xPos
w -= xPos
else:
return
elif self.Direction == Right: # Право
if w + xPos > self.minimumWidth():
w += xPos
self._mpos = pos
else:
return
elif self.Direction == Top: # выше
if h - yPos > self.minimumHeight():
y += yPos
h -= yPos
else:
return
elif self.Direction == Bottom: # ниже
if h + yPos > self.minimumHeight():
h += yPos
self._mpos = pos
else:
return
self.setGeometry(x, y, w, h)
main.py
from app import *
from FramelessWindow import FramelessWindow
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
application = StateWindow()
application.show()
MainWindow = QtWidgets.QMainWindow()
w = FramelessWindow()
w.setWindowTitle('Тестовая строка заголовка')
w.setWindowIcon(QIcon('Qt.ico'))
w.setWidget(StateWindow(w)) # Добавить свое окно
w.show()
ui = Ui_MainWindow()
sys.exit(app.exec_())
app.py
import sys
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from state_window import Ui_MainWindow
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QTextEdit
from PyQt5.QtCore import pyqtSignal
from FramelessWindow import FramelessWindow
class StateWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(StateWindow, self).__init__(*args, **kwargs)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setMinimumSize(1440, 950)
Подскажите, пожалуйста, как сделать кастомный Title Bar?
Уже сутки ищу ответ на этот вопрос, что на русских форумах, что на зарубежных. Пока ничего не нашел.
Ответы (1 шт):
Вы выбрали самый продвинутый пример и мне показалось, что для вас это еще рановато.
Пример, который я привожу, будет попроще.
Некоторые вам советы:
НИКОГДА НЕ ИЗМЕНЯЙТЕ код, сгенерированный
Qt Designer. Создайте другой класс, который наследуется от соответствующего виджета, и используйте созданный класс для его заполнения.Изучите как расположить виджеты используя менеджеры компоновки. Класс
QLayout- это базовый класс менеджеров геометрии, начните с него https://doc.qt.io/qt-5/qlayout.html .
Я немного оживил ваш пример (q1252882.py), запустите его, для начала отдельно:
python q1252882.py
Затем запустите q1252882-222.py куда я его вставил.
python q1252882-222.py
Да и измените путь к вашему изображению для кнопки.
q1252882.py
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *
#import resorses_rc
#class Ui_MainWindow(QtWidgets.QMainWindow): # ???
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1000, 600)
MainWindow.setStyleSheet("*{\n"
" font: 19pt \"Arial\";\n"
" color: #fff;\n"
"}\n"
"\n"
"QWidget{\n"
" background-color: #9B9B9A;\n"
" border-radius: 0px;\n"
"}\n"
"\n"
"#practical_btn,\n"
"#settings_btn,\n"
"#achiev_btn{\n"
" background-color: #E88327;\n"
" border-radius: 10px;\n"
"}\n"
"\n"
"#state_btn{\n"
" background-color: #FFAA5C;\n"
" border-radius: 10px;\n"
"}\n"
"\n"
"#achiev_btn:hover,\n"
"#practical_btn:hover,\n"
"#settings_btn:hover,\n"
"#state_btn:hover{\n"
" background-color: #FFAA5C;\n"
"}\n"
"\n"
"#edit_students,\n"
"#edit_streams\n"
"{\n"
" image: url(images/okV.png);\n"
" border: none;\n"
"}\n"
"\n"
"#table,\n"
"#streams\n"
"{\n"
" background-color: #E88327;\n"
" border-radius: 10px;\n"
"}\n"
"\n"
"#btn_close:hover,\n"
"#btn_min:hover,\n"
"#btn_max:hover\n"
"{\n"
" background-color:#ccc;\n"
" border-radius: 0px;\n"
"}")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setStyleSheet("")
self.centralwidget.setObjectName("centralwidget")
self.streams = QtWidgets.QListWidget(self.centralwidget)
self.streams.setGeometry(QtCore.QRect(30, 170, 256, 681))
self.streams.setStyleSheet("")
self.streams.setObjectName("streams")
self.edit_streams = QtWidgets.QPushButton(self.centralwidget)
self.edit_streams.setGeometry(QtCore.QRect(195, 137, 18, 18))
self.edit_streams.setCursor(
QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.edit_streams.setStyleSheet("")
self.edit_streams.setText("")
self.edit_streams.setObjectName("edit_streams")
self.table = QtWidgets.QTableWidget(self.centralwidget)
self.table.setGeometry(QtCore.QRect(300, 170, 1111, 681))
self.table.setStyleSheet("")
self.table.setObjectName("table")
self.table.setColumnCount(0)
self.table.setRowCount(0)
self.edit_students = QtWidgets.QPushButton(self.centralwidget)
self.edit_students.setGeometry(QtCore.QRect(945, 142, 18, 18))
self.edit_students.setCursor(
QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.edit_students.setStyleSheet("")
self.edit_students.setText("")
self.edit_students.setObjectName("edit_students")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(830, 135, 111, 31))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(110, 135, 81, 21))
self.label_2.setObjectName("label_2")
self.achiev_btn = QtWidgets.QPushButton(self.centralwidget)
self.achiev_btn.setEnabled(True)
self.achiev_btn.setGeometry(QtCore.QRect(470, 50, 221, 50))
self.achiev_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.achiev_btn.setStyleSheet("")
self.achiev_btn.setObjectName("achiev_btn")
self.state_btn = QtWidgets.QPushButton(self.centralwidget)
self.state_btn.setGeometry(QtCore.QRect(160, 50, 221, 50))
self.state_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.state_btn.setObjectName("state_btn")
self.practical_btn = QtWidgets.QPushButton(self.centralwidget)
self.practical_btn.setGeometry(QtCore.QRect(780, 50, 221, 50))
self.practical_btn.setCursor(
QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.practical_btn.setObjectName("practical_btn")
self.settings_btn = QtWidgets.QPushButton(self.centralwidget)
self.settings_btn.setGeometry(QtCore.QRect(1090, 50, 221, 50))
self.settings_btn.setCursor(
QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.settings_btn.setObjectName("settings_btn")
'''
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(0, 0, 1441, 41))
self.widget.setObjectName("widget")
self.btn_close = QtWidgets.QPushButton(self.widget)
self.btn_close.setGeometry(QtCore.QRect(1310, 10, 75, 23))
self.btn_close.setObjectName("btn_close")
self.btn_max = QtWidgets.QPushButton(self.widget)
self.btn_max.setGeometry(QtCore.QRect(1200, 10, 75, 23))
self.btn_max.setObjectName("btn_max")
self.btn_min = QtWidgets.QPushButton(self.widget)
self.btn_min.setGeometry(QtCore.QRect(1090, 10, 75, 23))
self.btn_min.setObjectName("btn_min")
'''
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1440, 34))
self.menubar.setStyleSheet("")
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setStyleSheet("")
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "студенты"))
self.label_2.setText(_translate("MainWindow", "потоки"))
self.achiev_btn.setText(_translate("MainWindow", "достижения"))
self.state_btn.setText(_translate("MainWindow", "ведомость"))
self.practical_btn.setText(_translate("MainWindow", "практические"))
self.settings_btn.setText(_translate("MainWindow", "настройки"))
# self.btn_close.setText(_translate("MainWindow", "3"))
# self.btn_max.setText(_translate("MainWindow", "2"))
# self.btn_min.setText(_translate("MainWindow", "1"))
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
layout_maim = QVBoxLayout(self.centralwidget)
lay_h = QHBoxLayout()
lay_h.addWidget(self.state_btn)
lay_h.addWidget(self.achiev_btn)
lay_h.addWidget(self.practical_btn)
lay_h.addWidget(self.settings_btn)
layout_maim.addLayout(lay_h)
lay_h = QHBoxLayout()
lay_h.addStretch(0)
lay_h.addWidget(self.label)
lay_h.addWidget(self.edit_streams)
lay_h.addStretch(2)
lay_h.addWidget(self.label_2)
lay_h.addWidget(self.edit_students)
lay_h.addStretch(2)
layout_maim.addLayout(lay_h)
lay_h = QHBoxLayout()
lay_h.addWidget(self.streams, 2)
lay_h.addWidget(self.table, 3)
layout_maim.addLayout(lay_h)
labels = ("Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7")
self.streams.addItems(labels)
self.table.setRowCount(7)
self.table.setColumnCount(5)
self.table.setHorizontalHeaderLabels(['V1','V2','V3','V4','V5'])
self.table.verticalHeader().hide()
header = self.table.horizontalHeader()
for i in range(7):
for j in range(5):
item = QtWidgets.QTableWidgetItem("Item {}-{}".format(i, j))
item.setTextAlignment(QtCore.Qt.AlignHCenter)
self.table.setItem(i, j, item)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
q1252882-222.py
from PyQt5.QtCore import Qt, QPointF
from PyQt5.QtGui import QWindowStateChangeEvent, QFont, QMouseEvent
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QSpacerItem, QSizePolicy, \
QLabel, QPushButton, QApplication, QVBoxLayout, QDialog
from PyQt5 import QtCore, QtGui, QtWidgets
from q1252882 import MainWindow # Импорт вашнго приложения !!!
class CTitleBar(QWidget):
Radius = 38
def __init__(self, *args, title='заглавие, название', **kwargs):
super(CTitleBar, self).__init__(*args, **kwargs)
self.setupUi()
# Поддержка настройки фона
self.setAttribute(Qt.WA_StyledBackground, True)
self.mPos = None
# Найти родительский элемент управления self.parent() (или self)
self._root = self.window()
self.labelTitle.setText(title)
# Вам нужно скрыть кнопку свернуть или развернуть
self.showMinimizeButton(self.isMinimizeable())
self.showNormalButton(False)
self.showMaximizeButton(self.isMaximizeable())
# Связывающий сигнал
# windowTitleChanged сигнал испускается при изменении заголовка окна
# с новым заголовком в качестве аргумента.
self._root.windowTitleChanged.connect(self.setWindowTitle)
self.buttonMinimum.clicked.connect(self.showMinimized)
self.buttonMaximum.clicked.connect(self.showMaximized)
self.buttonNormal.clicked.connect(self.showNormal)
self.buttonClose.clicked.connect(self._root.close)
# Установите фильтр событий на родительский элемент управления (или на себя)
self._root.installEventFilter(self)
def showMinimized(self):
self._root.showMinimized()
QApplication.sendEvent(self.buttonMinimum, QMouseEvent(
QMouseEvent.Leave, QPointF(), Qt.LeftButton, Qt.NoButton, Qt.NoModifier))
def showNormal(self):
''' Восстанавливает виджет после того, как он был развернут или свернут. '''
self._root.showNormal()
QApplication.sendEvent(self.buttonMaximum, QMouseEvent(
QMouseEvent.Leave, QPointF(), Qt.LeftButton, Qt.NoButton, Qt.NoModifier))
def showMaximized(self):
self._root.showMaximized()
QApplication.sendEvent(self.buttonNormal, QMouseEvent(
QMouseEvent.Leave, QPointF(), Qt.LeftButton, Qt.NoButton, Qt.NoModifier))
def isMinimizeable(self):
return self.testWindowFlags(Qt.WindowMinimizeButtonHint)
def isMaximizeable(self):
return self.testWindowFlags(Qt.WindowMaximizeButtonHint)
def isResizable(self):
return self._root.minimumSize() != self._root.maximumSize()
def showMinimizeButton(self, show=True):
""" Показать скрытую кнопку сворачивания """
self.buttonMinimum.setVisible(show)
self.widgetMinimum.setVisible(show)
def showMaximizeButton(self, show=True):
""" Показать скрытую кнопку максимизации """
self.buttonMaximum.setVisible(show)
self.widgetMaximum.setVisible(show)
def showNormalButton(self, show=True):
""" Показать скрытую кнопку восстановления """
self.buttonNormal.setVisible(show)
self.widgetNormal.setVisible(show)
def showEvent(self, event):
super(CTitleBar, self).showEvent(event)
if not self.isResizable():
self.showMaximizeButton(False)
self.showNormalButton(False)
else:
self.showMaximizeButton(
self.isMaximizeable() and not self._root.isMaximized())
self.showNormalButton(self.isMaximizeable()
and self._root.isMaximized())
def eventFilter(self, target, event):
if isinstance(event, QWindowStateChangeEvent):
if self._root.isVisible() and not self._root.isMinimized() and \
self.testWindowFlags(Qt.WindowMinMaxButtonsHint):
maximized = self._root.isMaximized()
self.showMaximizeButton(not maximized)
self.showNormalButton(maximized)
if maximized:
self._oldMargins = self._root.layout().getContentsMargins()
self._root.layout().setContentsMargins(0, 0, 0, 0)
else:
if hasattr(self, '_oldMargins'):
self._root.layout().setContentsMargins(*self._oldMargins)
return super(CTitleBar, self).eventFilter(target, event)
def mouseDoubleClickEvent(self, event):
""" Дважды щелкните строку заголовка
:param event:
"""
if not self.isMaximizeable() or not self.isResizable():
return
if self._root.isMaximized():
self._root.showNormal()
else:
self._root.showMaximized()
def mousePressEvent(self, event):
""" Координаты записи нажатия мышью
:param event:
"""
if event.button() == Qt.LeftButton:
self.mPos = event.pos()
def mouseReleaseEvent(self, event):
""" Мышь отпущена, удалить координаты
:param event:
"""
self.mPos = None
def mouseMoveEvent(self, event):
""" Мышь двигает окно
:param event:
"""
if self._root.isMaximized():
# Не двигается при максимизации
return
if event.buttons() == Qt.LeftButton and self.mPos:
pos = event.pos() - self.mPos
self._root.move(self._root.pos() + pos)
def testWindowFlags(self, windowFlags):
""" Определите, есть ли у текущего окна флаги
:param windowFlags:
"""
return bool(self._root.windowFlags() & windowFlags)
def setWindowTitle(self, title):
""" Установка заголовка
:param title:
"""
self.labelTitle.setText(title)
def setupUi(self):
""" Создать пользовательский интерфейс """
self.setMinimumSize(0, self.Radius)
self.setMaximumSize(0xFFFFFF, self.Radius)
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
for name in ('widgetMinimum', 'widgetMaximum', 'widgetNormal', 'widgetClose'):
widget = QWidget(self)
widget.setMinimumSize(self.Radius, self.Radius)
widget.setMaximumSize(self.Radius, self.Radius)
widget.setObjectName('CTitleBar_%s' % name)
setattr(self, name, widget)
layout.addWidget(widget)
layout.addItem(QSpacerItem(
40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
# Название
self.labelTitle = QLabel(self, alignment=Qt.AlignCenter)
self.labelTitle.setObjectName('CTitleBar_labelTitle')
layout.addWidget(self.labelTitle)
layout.addItem(QSpacerItem(
40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
# Свернуть, развернуть, восстановить, кнопкa закрыть
for name, text in (('buttonMinimum', '0'), ('buttonMaximum', '1'),
('buttonNormal', '2'), ('buttonClose', 'r')):
button = QPushButton(text, self, font=QFont('Webdings'))
button.setMinimumSize(self.Radius, self.Radius)
button.setMaximumSize(self.Radius, self.Radius)
button.setObjectName('CTitleBar_%s' % name)
setattr(self, name, button)
layout.addWidget(button)
class TestCTitleBarBase:
def __init__(self, *args, **kwargs):
super(TestCTitleBarBase, self).__init__(*args, **kwargs)
self.resize(1000, 600)
# Установите прозрачность фона
self.setAttribute(Qt.WA_TranslucentBackground, True)
# Установите без границ
self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
layout = QVBoxLayout(self)
layout.setSpacing(0)
# Добавить пользовательскую строку заголовка
layout.addWidget(CTitleBar(self, title='Custom TitleBar.'))
# нижний Widget
self.widget = QWidget(self, objectName='bottomWidget')
layout.addWidget(self.widget)
# это ваш код :)
self.mainWindow = MainWindow() # +++ вот ваше приложение !!!
box = QHBoxLayout(self.widget)
box.setContentsMargins(0, 0, 0, 0)
box.addWidget(self.mainWindow) # +++ вот ваше приложение !!!
class TestCTitleBarWidget(QWidget, TestCTitleBarBase):
pass
# стиль строки заголовка
Style = """
/* Цвет строки заголовка */
CTitleBar {
background: rgb(65, 148, 216);
}
/* Окно заголовка закруглено */
CTitleBar {
border-top-right-radius: 10px;
border-top-left-radius: 10px;
}
#CTitleBar_buttonClose {
/* Вам нужно принять во внимание (закруглить) кнопку закрытия на правой стороне */
border-top-right-radius: 10px;
}
/* Нижние закругленные углы и фон */
#bottomWidget {
background: white;
border-bottom-right-radius: 10px;
border-bottom-left-radius: 10px;
}
/* Свернуть, развернуть, кнопка восстановления */
CTitleBar > QPushButton {
background: transparent;
}
CTitleBar > QPushButton:hover {
background: rgba(0, 0, 0, 30);
}
CTitleBar > QPushButton:pressed {
background: rgba(0, 0, 0, 60);
}
/* Кнопка закрытия */
#CTitleBar_buttonClose:hover {
color: white;
background: rgb(232, 17, 35);
}
#CTitleBar_buttonClose:pressed {
color: white;
background: rgb(165, 69, 106);
}
"""
if __name__ == '__main__':
import sys
import cgitb
sys.excepthook = cgitb.enable(1, None, 5, '')
app = QApplication(sys.argv)
app.setStyleSheet(Style)
w = TestCTitleBarWidget()
w.setWindowTitle('Главное окно')
w.show()
sys.exit(app.exec_())
