Функция изменения размеров модифицированного окна курсором и движение окна по экрану за титульный бар
Есть пример, по которому я пытаюсь изучить функцию изменения размера окна пользователем. Также в этом примере окно перемещается по экрану с зажатым на нём курсором на титульном баре. Если на этом окне зажать ЛКМ на фреймах контента, окно не движется, что мне и нужно.
Путём некоторых корректировок своего кода за счёт примера, я добиваюсь подобного результата, но есть подозрение, что код получается перегруженным и всё можно сделать проще.
Как мне можно реализовать два этих действия буквально в двух функциях? Гуглил, что означают методы из примера в официальной документации, но понимание не всегда приходит.
Мой код:
import sys
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import QColor, QFont, QFontDatabase, QIcon, QImage, QPixmap
from PyQt5.QtWidgets import *
class Window(QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.clicks = 0
self.setStyleSheet("background-color: rgb(35,43,50);")
self.setMinimumSize(800, 500)
self.resize(1200, 700)
# Скрытие стандартной шапки (Без границ)
self.setWindowFlags(Qt.FramelessWindowHint)
# Прозрачность окна (WA_TranslucentBackground - прозрачный фон)
self.setAttribute(Qt.WA_TranslucentBackground)
# Прозрачность
# self.setWindowOpacity(0.9)
# Появление виджета в месте курсора
# self.move(QtGui.QCursor.pos())
self.offset = None
self.top_bar = QFrame()
self.top_bar.setObjectName('top_bar')
self.top_bar.setMaximumHeight(40)
self.top_bar.setFrameShadow(QFrame.Raised)
self.content = QFrame()
self.content.setFrameShadow(QFrame.Raised)
# left_bar
self.left_bar = QFrame()
self.left_bar.setMaximumWidth(50)
self.left_bar.setFrameShadow(QFrame.StyledPanel | QFrame.Raised)
# self.left_bar.setLineWidth(3) # Понятия не имею что это, тени нет в любом случае
# title_bar
self.title_bar = QFrame()
self.title_bar.setStyleSheet("background-color: transparent")
self.title_bar.setMinimumWidth(120)
# min_button
self.min_button = QPushButton()
self.min_button.setIcon(
QIcon(QPixmap('icons/Apagar/cil-minus.png')))
self.min_button.setMinimumHeight(40)
self.min_button.setMaximumWidth(40)
self.min_button.clicked.connect(self.turn_window)
# max_button
self.max_button = QPushButton()
self.max_button.setIcon(
QIcon(QPixmap('icons/Apagar/cil-fullscreen.png')))
self.max_button.setMinimumHeight(40)
self.max_button.setMaximumWidth(40)
self.max_button.clicked.connect(self.expand_window)
# close_button
self.close_button = QPushButton()
self.close_button.setIcon(
QIcon(QPixmap('icons/Apagar/cil-power-standby.png')))
self.close_button.setMinimumHeight(40)
self.close_button.setMaximumWidth(40)
self.close_button.clicked.connect(self.close_window)
# menu_button
self.menu_button = QPushButton()
self.menu_button.setText("")
self.menu_button.setIcon(QIcon(QPixmap('icons/Apagar/cil-menu.png')))
self.menu_button.setMinimumHeight(40)
self.menu_button.clicked.connect(self.toggle)
# page_1_button
self.page_1_button = QPushButton()
self.page_1_button.setText("")
self.page_1_button.setIcon(
QIcon(QPixmap('icons/Apagar/cil-mood-very-good.png')))
self.page_1_button.setMinimumHeight(40)
self.chek_activ_1 = QFrame()
self.chek_activ_1.setMaximumWidth(10)
# self.chek_activ_1.setMinimumWidth(5)
self.chek_activ_1.setFrameShadow(QFrame.Raised)
# page_2_button
self.page_2_button = QPushButton()
self.page_2_button.setText("")
self.page_2_button.setIcon(
QIcon(QPixmap('icons/Apagar/cil-mood-very-bad.png')))
self.page_2_button.setMinimumHeight(40)
self.chek_activ_2 = QFrame()
self.chek_activ_2.setStyleSheet("background-color: transparent")
self.chek_activ_2.setMaximumWidth(0)
# self.chek_activ_2.setMinimumWidth(5)
self.chek_activ_2.setFrameShadow(QFrame.Raised)
self.layout_navigation = QGridLayout(self.top_bar)
self.layout_navigation.addWidget(self.title_bar, 0, 0)
self.layout_navigation.addWidget(self.min_button, 0, 1)
self.layout_navigation.addWidget(self.max_button, 0, 2)
self.layout_navigation.addWidget(self.close_button, 0, 3)
self.layout_navigation.setContentsMargins(0, 0, 0, 0)
self.layout_menu_0 = QHBoxLayout()
self.layout_menu_0.addWidget(self.menu_button)
self.layout_menu_0.setContentsMargins(0, 0, 0, 0)
self.layout_menu_0.setSpacing(0)
self.layout_menu_1 = QHBoxLayout()
self.layout_menu_1.addWidget(self.chek_activ_1)
self.layout_menu_1.addWidget(self.page_1_button)
self.layout_menu_1.setContentsMargins(0, 0, 0, 0)
self.layout_menu_1.setSpacing(0)
self.layout_menu_2 = QHBoxLayout()
self.layout_menu_2.addWidget(self.chek_activ_2)
self.layout_menu_2.addWidget(self.page_2_button)
self.layout_menu_2.setContentsMargins(0, 0, 0, 0)
self.layout_menu_2.setSpacing(0)
self.vbox_1 = QVBoxLayout(self.left_bar)
self.vbox_1.addLayout(self.layout_menu_0)
self.vbox_1.addLayout(self.layout_menu_1)
self.vbox_1.addLayout(self.layout_menu_2)
self.vbox_1.addStretch()
self.vbox_1.setContentsMargins(0, 0, 0, 0)
self.right_bar = QFrame()
self.right_bar.setFrameShadow(QFrame.Raised)
self.vbox_2 = QVBoxLayout(self.right_bar)
self.vbox_2.addWidget(self.top_bar)
self.vbox_2.addWidget(self.content)
self.vbox_2.setContentsMargins(0, 0, 0, 0)
self.vbox_2.setSpacing(0)
self.hbox = QHBoxLayout(self)
self.hbox.setContentsMargins(0, 0, 0, 0)
self.hbox.setSpacing(0)
self.hbox.addWidget(self.left_bar)
self.hbox.addWidget(self.right_bar)
def turn_window(self):
self.showMinimized()
def expand_window(self):
if self.isMaximized():
self.max_button.setIcon(
QIcon("icons/Apagar/cil-fullscreen.png"))
self.showNormal()
else:
self.max_button.setIcon(
QIcon("icons/Apagar/cil-fullscreen-exit.png"))
self.showMaximized()
self.right_bar.setStyleSheet('''''')
def close_window(self):
self.close()
def mousePressEvent(self, event):
""" Координаты записи нажатия мышью
:param event:
"""
if event.button() == QtCore.Qt.LeftButton:
self.offset = event.pos()
else:
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
""" Мышь двигает окно
:param event:
"""
if self.isMaximized():
# Не двигается при максимизации
return
if self.offset is not None and event.buttons() == QtCore.Qt.LeftButton:
self.move(self.pos() + event.pos() - self.offset)
else:
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
""" Мышь отпущена, удалить координаты
:param event:
"""
self.offset = None
super().mouseReleaseEvent(event)
def toggle(self):
self.animation = QPropertyAnimation(self.left_bar, b"minimumWidth")
self.animation.setDuration(900)
if self.left_bar.width() == 50:
self.animation.setStartValue(50)
self.animation.setEndValue(280)
self.page_1_button.setText("Page 1")
self.page_1_button.setIcon(
QIcon(QPixmap('icons/Noimg.png')))
self.page_2_button.setText("Page 2")
self.page_2_button.setIcon(
QIcon(QPixmap('icons/Noimg.png')))
else:
self.animation.setStartValue(280)
self.animation.setEndValue(50)
self.page_1_button.setText("")
self.page_1_button.setIcon(
QIcon(QPixmap('icons/Apagar/cil-mood-very-good.png')))
self.page_2_button.setText("")
self.page_2_button.setIcon(
QIcon(QPixmap('icons/Apagar/cil-mood-very-bad.png')))
self.animation.setEasingCurve(QEasingCurve.OutCubic)
self.animation.start()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
Код взятого мной примера: (хотелось бы понять для чего функции showEvent и eventFilter в классе CTitleBar)
import sys
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import QColor, QFont, QFontDatabase, QIcon, QImage, QMouseEvent, QPixmap, QWindowStateChangeEvent
from PyQt5.QtWidgets import *
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)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
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_())
Ответы (1 шт):
Функция изменения размеров модифицированного окна курсором:
...
sizeGrip = QtWidgets.QSizeGrip(self) # !!! +++
sizeGrip.setStyleSheet("background-color: #CD1818") # <-попробуйте убрать эту строку
self.gridLayout.addWidget( # !!! +++
sizeGrip,
1, 0, 1, 1,
QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight
)
...
Движение окна по экрану за титульный бар:
...
self.offset_title_bar = False
...
self.label_title.installEventFilter(self) # +++ !!!
...
def eventFilter(self, obj, event): # +++ !!!
if self.label_title is obj:
if event.type() == QtCore.QEvent.Enter:
self.offset_title_bar = True
elif event.type() == QtCore.QEvent.Leave:
self.offset_title_bar = False
return super().eventFilter(obj, event)
...
def mouseMoveEvent(self, event):
""" Мышь двигает окно """
if self.isMaximized():
# Не двигается при максимизации
return
# !!! self.offset_title_bar
# if self.offset is not None and event.buttons() == QtCore.Qt.LeftButton:
if self.offset is not None and \
event.buttons() == QtCore.Qt.LeftButton and \
self.offset_title_bar: # +++ offset_title_bar
self.move(self.pos() + event.pos() - self.offset)
else:
super().mouseMoveEvent(event)
...
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *
class Window(QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.clicks = 0
self.setStyleSheet("background-color: rgb(35,43,50);")
self.setMinimumSize(400, 200) # (800, 500)
self.resize(800, 400) # (1200, 700)
# Скрытие стандартной шапки (Без границ)
self.setWindowFlags(Qt.FramelessWindowHint)
# Прозрачность окна (WA_TranslucentBackground - прозрачный фон)
self.setAttribute(Qt.WA_TranslucentBackground)
# Прозрачность
# self.setWindowOpacity(0.9)
# Появление виджета в месте курсора
# self.move(QtGui.QCursor.pos())
self.offset = None
self.offset_title_bar = False # +++ offset_title_bar
self.top_bar = QFrame()
self.top_bar.setObjectName('top_bar')
self.top_bar.setMaximumHeight(40)
self.top_bar.setFrameShadow(QFrame.Raised)
self.content = QFrame()
self.content.setFrameShadow(QFrame.Raised)
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
self.gridLayout = QtWidgets.QGridLayout(self.content)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setSpacing(0)
self.label_content = QLabel('Hello World', self, alignment=Qt.AlignCenter)
self.label_content.setStyleSheet("background-color: #064635")
self.gridLayout.addWidget(self.label_content, 0, 0)
self.gridLayout.setRowStretch(0, 1)
font = self.label_content.font()
font.setPointSize(20)
self.label_content.setFont(font)
sizeGrip = QtWidgets.QSizeGrip(self) # !!! +++
sizeGrip.setStyleSheet("background-color: #CD1818") # <-попробуйте убрать эту строку
self.gridLayout.addWidget( # !!! +++
sizeGrip,
1, 0, 1, 1,
QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight
)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# left_bar
self.left_bar = QFrame()
self.left_bar.setMaximumWidth(50)
self.left_bar.setFrameShadow(QFrame.StyledPanel | QFrame.Raised)
# self.left_bar.setLineWidth(3) # Понятия не имею что это, тени нет в любом случае
# title_bar
self.title_bar = QFrame()
self.title_bar.setStyleSheet("background-color: transparent")
self.title_bar.setMinimumWidth(120)
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
self.gridLayout2 = QtWidgets.QGridLayout(self.title_bar)
self.gridLayout2.setContentsMargins(0, 0, 0, 0)
self.gridLayout2.setSpacing(0)
self.label_title = QLabel('Title_bar', alignment=Qt.AlignCenter)
self.label_title.setObjectName('label_title')
self.label_title.setStyleSheet("background-color: #519259")
font = self.label_title.font()
font.setPointSize(15)
self.label_title.setFont(font)
# !!!
self.label_title.installEventFilter(self) # +++ !!!
self.gridLayout2.addWidget(self.label_title, 0, 0)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# min_button
self.min_button = QPushButton()
self.min_button.setIcon(
QIcon(QPixmap('Ok.png')))
self.min_button.setMinimumHeight(40)
self.min_button.setMaximumWidth(40)
self.min_button.clicked.connect(self.turn_window)
# max_button
self.max_button = QPushButton()
self.max_button.setIcon(
QIcon(QPixmap('Ok.png')))
self.max_button.setMinimumHeight(40)
self.max_button.setMaximumWidth(40)
self.max_button.clicked.connect(self.expand_window)
# close_button
self.close_button = QPushButton()
self.close_button.setIcon(
QIcon(QPixmap('Ok.png')))
self.close_button.setMinimumHeight(40)
self.close_button.setMaximumWidth(40)
self.close_button.clicked.connect(self.close_window)
# menu_button
self.menu_button = QPushButton()
self.menu_button.setText("")
self.menu_button.setIcon(QIcon(QPixmap('Ok.png')))
self.menu_button.setMinimumHeight(40)
self.menu_button.clicked.connect(self.toggle)
# page_1_button
self.page_1_button = QPushButton()
self.page_1_button.setText("")
self.page_1_button.setIcon(
QIcon(QPixmap('Ok.png')))
self.page_1_button.setMinimumHeight(40)
self.chek_activ_1 = QFrame()
self.chek_activ_1.setMaximumWidth(10)
# self.chek_activ_1.setMinimumWidth(5)
self.chek_activ_1.setFrameShadow(QFrame.Raised)
# page_2_button
self.page_2_button = QPushButton()
self.page_2_button.setText("")
self.page_2_button.setIcon(
QIcon(QPixmap('Ok.png')))
self.page_2_button.setMinimumHeight(40)
self.chek_activ_2 = QFrame()
self.chek_activ_2.setStyleSheet("background-color: transparent")
self.chek_activ_2.setMaximumWidth(0)
# self.chek_activ_2.setMinimumWidth(5)
self.chek_activ_2.setFrameShadow(QFrame.Raised)
self.layout_navigation = QGridLayout(self.top_bar)
self.layout_navigation.addWidget(self.title_bar, 0, 0)
self.layout_navigation.addWidget(self.min_button, 0, 1)
self.layout_navigation.addWidget(self.max_button, 0, 2)
self.layout_navigation.addWidget(self.close_button, 0, 3)
self.layout_navigation.setContentsMargins(0, 0, 0, 0)
self.layout_menu_0 = QHBoxLayout()
self.layout_menu_0.addWidget(self.menu_button)
self.layout_menu_0.setContentsMargins(0, 0, 0, 0)
self.layout_menu_0.setSpacing(0)
self.layout_menu_1 = QHBoxLayout()
self.layout_menu_1.addWidget(self.chek_activ_1)
self.layout_menu_1.addWidget(self.page_1_button)
self.layout_menu_1.setContentsMargins(0, 0, 0, 0)
self.layout_menu_1.setSpacing(0)
self.layout_menu_2 = QHBoxLayout()
self.layout_menu_2.addWidget(self.chek_activ_2)
self.layout_menu_2.addWidget(self.page_2_button)
self.layout_menu_2.setContentsMargins(0, 0, 0, 0)
self.layout_menu_2.setSpacing(0)
self.vbox_1 = QVBoxLayout(self.left_bar)
self.vbox_1.addLayout(self.layout_menu_0)
self.vbox_1.addLayout(self.layout_menu_1)
self.vbox_1.addLayout(self.layout_menu_2)
self.vbox_1.addStretch()
self.vbox_1.setContentsMargins(0, 0, 0, 0)
self.right_bar = QFrame()
self.right_bar.setFrameShadow(QFrame.Raised)
self.vbox_2 = QVBoxLayout(self.right_bar)
self.vbox_2.addWidget(self.top_bar)
self.vbox_2.addWidget(self.content)
self.vbox_2.setContentsMargins(0, 0, 0, 0)
self.vbox_2.setSpacing(0)
self.hbox = QHBoxLayout(self)
self.hbox.setContentsMargins(0, 0, 0, 0)
self.hbox.setSpacing(0)
self.hbox.addWidget(self.left_bar)
self.hbox.addWidget(self.right_bar)
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
def eventFilter(self, obj, event): # +++ !!!
if self.label_title is obj:
if event.type() == QtCore.QEvent.Enter:
self.offset_title_bar = True
elif event.type() == QtCore.QEvent.Leave:
self.offset_title_bar = False
return super().eventFilter(obj, event)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
def turn_window(self):
self.showMinimized()
def expand_window(self):
if self.isMaximized():
self.max_button.setIcon(
QIcon("Ok.png"))
self.showNormal()
else:
self.max_button.setIcon(
QIcon("Ok.png"))
self.showMaximized()
self.right_bar.setStyleSheet('''''')
def close_window(self):
self.close()
def mousePressEvent(self, event):
""" Координаты записи нажатия мышью """
if event.button() == QtCore.Qt.LeftButton:
self.offset = event.pos()
else:
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
""" Мышь двигает окно """
if self.isMaximized():
# Не двигается при максимизации
return
# !!! self.offset_title_bar
# if self.offset is not None and event.buttons() == QtCore.Qt.LeftButton:
if self.offset is not None and \
event.buttons() == QtCore.Qt.LeftButton and \
self.offset_title_bar: # +++ offset_title_bar
self.move(self.pos() + event.pos() - self.offset)
else:
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
""" Мышь отпущена, удалить координаты
:param event:
"""
self.offset = None
super().mouseReleaseEvent(event)
def toggle(self):
self.animation = QPropertyAnimation(self.left_bar, b"minimumWidth")
self.animation.setDuration(900)
if self.left_bar.width() == 50:
self.animation.setStartValue(50)
self.animation.setEndValue(280)
self.page_1_button.setText("Page 1")
self.page_1_button.setIcon(
QIcon(QPixmap('Ok.png')))
self.page_2_button.setText("Page 2")
self.page_2_button.setIcon(
QIcon(QPixmap('Ok.png')))
else:
self.animation.setStartValue(280)
self.animation.setEndValue(50)
self.page_1_button.setText("")
self.page_1_button.setIcon(
QIcon(QPixmap('Ok.png')))
self.page_2_button.setText("")
self.page_2_button.setIcon(
QIcon(QPixmap('Ok.png')))
self.animation.setEasingCurve(QEasingCurve.OutCubic)
self.animation.start()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
