Страницы

Поиск по вопросам

пятница, 28 февраля 2020 г.

Как работать с заголовком окна?

#python #pyqt5


Хочу модернизировать заголовок окна. Например цвет заголовка и хочу добавить еще
одну собственную кнопку. Как это реализовать? Чтоб не было вечно такого:


Пример:
Запускающий файл

import sys, os, time, random
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt, pyqtSignal
from MainWindow import Ui_MainWindow

# стиль
StyleSheet = """
/* Панель заголовка */
TitleBar {
    background-color: #2a3440;
}
/* Минимизировать кнопку `Максимальное выключение` Общий фон по умолчанию */
#buttonMinimum,#buttonMaximum,#buttonClose, #buttonMy {
    border: none;
    background-color: #2a3440;
}
/* Зависание */
#buttonMinimum:hover,#buttonMaximum:hover {
    background-color: #2a3440;
}
#buttonClose:hover {
    color: white;
    background-color: #2a3440;
}
#buttonMy:hover {
    color: white;
    background-color: green;   /* rgb(232, 17, 35) */
}
/* Мышь удерживать */
#buttonMinimum:pressed,#buttonMaximum:pressed {
    background-color: #2a3440;
}
#buttonClose:pressed {
    color: white;
    background-color: #2a3440;
}
"""

class Window(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.Window = Ui_MainWindow()
        self.Window.setupUi(self)
        self.show()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    app.setStyleSheet(StyleSheet)
    Win = Window()
    Win.show()
    sys.exit(app.exec_())


Сам файл накиданный в дизайнере

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'MainWindow.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(257, 60)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(160, 20, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(20, 20, 113, 20))
        self.lineEdit.setObjectName("lineEdit")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "PushButton"))

    


Ответы

Ответ 1



Отличный пример демонстрации как это делается: main.py #!/usr/bin/env python # -*- coding: utf-8 -*- from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QTextEdit from PyQt5.QtCore import pyqtSignal from FramelessWindow import FramelessWindow # Created on 2018年4月30日 # author: Irony # site: https://github.com/892768447 # email: 892768447@qq.com # file: Test # description: __Author__ = """By: Irony QQ: 892768447 Email: 892768447@qq.com""" __Copyright__ = 'Copyright (c) 2018 Irony' __Version__ = 1.0 class MainWindow(QWidget): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) objectTitleBar = args[0].titleBar layout = QVBoxLayout(self, spacing=0) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(QPushButton('Кнопка', self)) self.textEdit = QTextEdit(self) layout.addWidget(self.textEdit) objectTitleBar.signalButtonMy.connect(self.onButtonMy) def onButtonMy(self): self.textEdit.append("Нажата `Своя Кнопка`!") # стиль StyleSheet = """ /* Панель заголовка */ TitleBar { background-color: rgb(54, 157, 180); } /* Минимизировать кнопку `Максимальное выключение` Общий фон по умолчанию */ #buttonMinimum,#buttonMaximum,#buttonClose, #buttonMy { border: none; background-color: rgb(54, 157, 180); } /* Зависание */ #buttonMinimum:hover,#buttonMaximum:hover { background-color: rgb(48, 141, 162); } #buttonClose:hover { color: white; background-color: rgb(232, 17, 35); } #buttonMy:hover { color: white; background-color: green; /* rgb(232, 17, 35) */ } /* Мышь удерживать */ #buttonMinimum:pressed,#buttonMaximum:pressed { background-color: rgb(44, 125, 144); } #buttonClose:pressed { color: white; background-color: rgb(161, 73, 92); } """ if __name__ == '__main__': import sys from PyQt5.QtWidgets import QApplication app = QApplication(sys.argv) app.setStyleSheet(StyleSheet) w = FramelessWindow() w.setWindowTitle('Тестовая строка заголовка') w.setWindowIcon(QIcon('Qt.ico')) w.setWidget(MainWindow(w)) # Добавить свое окно w.show() sys.exit(app.exec_()) FramelessWindow.py #!/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) # Created on 2018年4月30日 # author: Irony # site: https://github.com/892768447 # email: 892768447@qq.com # file: FramelessWindow # description: __Author__ = """By: Irony QQ: 892768447 Email: 892768447@qq.com""" __Copyright__ = 'Copyright (c) 2018 Irony' __Version__ = 1.0 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)

Комментариев нет:

Отправить комментарий