diff --git a/examples/demo.py b/examples/demo.py index a75ec55..323b297 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -2,8 +2,8 @@ import sys from PyQt5.QtCore import Qt -from PyQt5.QtGui import QColor, QPixmap -from PyQt5.QtWidgets import QApplication, QLabel +from PyQt5.QtGui import QColor, QPixmap, QIcon +from PyQt5.QtWidgets import QApplication, QLabel, QHBoxLayout from qframelesswindow import FramelessWindow, TitleBar @@ -13,9 +13,23 @@ class CustomTitleBar(TitleBar): def __init__(self, parent): super().__init__(parent) + # add window icon + self.iconLabel = QLabel(self) + self.iconLabel.setFixedSize(20, 20) + self.hBoxLayout.insertSpacing(0, 10) + self.hBoxLayout.insertWidget(1, self.iconLabel, 0, Qt.AlignLeft) + self.window().windowIconChanged.connect(self.setIcon) + # add title label self.titleLabel = QLabel(self) - self.titleLabel.setStyleSheet("QLabel{font: 13px 'Segoe UI'; margin: 9px}") + self.hBoxLayout.insertWidget(2, self.titleLabel, 0, Qt.AlignLeft) + self.titleLabel.setStyleSheet(""" + QLabel{ + background: transparent; + font: 13px 'Segoe UI'; + padding: 0 4px + } + """) self.window().windowTitleChanged.connect(self.setTitle) # customize the style of title bar button @@ -38,6 +52,9 @@ def setTitle(self, title): self.titleLabel.setText(title) self.titleLabel.adjustSize() + def setIcon(self, icon): + self.iconLabel.setPixmap(icon.pixmap(20, 20)) + class Window(FramelessWindow): @@ -49,7 +66,9 @@ def __init__(self, parent=None): self.label = QLabel(self) self.label.setScaledContents(True) self.label.setPixmap(QPixmap("screenshot/shoko.png")) - self.setWindowTitle("PyQt Frameless Window") + + self.setWindowIcon(QIcon("screenshot/logo.png")) + self.setWindowTitle("PyQt-Frameless-Window") self.setStyleSheet("background:white") self.titleBar.raise_() diff --git a/qframelesswindow/titlebar/__init__.py b/qframelesswindow/titlebar/__init__.py index 0065a66..105ccf1 100644 --- a/qframelesswindow/titlebar/__init__.py +++ b/qframelesswindow/titlebar/__init__.py @@ -5,7 +5,8 @@ from PyQt5.QtWidgets import QHBoxLayout, QWidget from ..utils import startSystemMove -from .title_bar_buttons import CloseButton, MaximizeButton, MinimizeButton, SvgTitleBarButton +from .title_bar_buttons import (CloseButton, MaximizeButton, MinimizeButton, + SvgTitleBarButton, TitleBarButton) class TitleBar(QWidget): @@ -25,10 +26,11 @@ def __init__(self, parent): # add buttons to layout self.hBoxLayout.setSpacing(0) self.hBoxLayout.setContentsMargins(0, 0, 0, 0) + self.hBoxLayout.setAlignment(Qt.AlignVCenter | Qt.AlignLeft) + self.hBoxLayout.addStretch(1) self.hBoxLayout.addWidget(self.minBtn, 0, Qt.AlignRight) self.hBoxLayout.addWidget(self.maxBtn, 0, Qt.AlignRight) self.hBoxLayout.addWidget(self.closeBtn, 0, Qt.AlignRight) - self.hBoxLayout.setAlignment(Qt.AlignRight) # connect signal to slot self.minBtn.clicked.connect(self.window().showMinimized) @@ -53,13 +55,13 @@ def mouseDoubleClickEvent(self, event): self.__toggleMaxState() def mouseMoveEvent(self, e): - if sys.platform != "win32" or not self._isDragRegion(e.pos()): + if sys.platform != "win32" or not self.canDrag(e.pos()): return startSystemMove(self.window(), e.globalPos()) def mousePressEvent(self, e): - if sys.platform == "win32" or e.button() != Qt.LeftButton or not self._isDragRegion(e.pos()): + if sys.platform == "win32" or not self.canDrag(e.pos()): return startSystemMove(self.window(), e.globalPos()) @@ -72,8 +74,21 @@ def __toggleMaxState(self): self.window().showMaximized() def _isDragRegion(self, pos): - """ Check whether the pressed point belongs to the area where dragging is allowed """ - return 0 < pos.x() < self.width() - 46 * 3 + """ Check whether the position belongs to the area where dragging is allowed """ + width = 0 + for button in self.findChildren(TitleBarButton): + if button.isVisible(): + width += button.width() + + return 0 < pos.x() < self.width() - width + + def _hasButtonPressed(self): + """ whether any button is pressed """ + return any(btn.isPressed() for btn in self.findChildren(TitleBarButton)) + + def canDrag(self, pos): + """ whether the position is draggable """ + return self._isDragRegion(pos) and not self._hasButtonPressed() def setDoubleClickEnabled(self, isEnabled): """ whether to switch window maximization status when double clicked diff --git a/qframelesswindow/titlebar/title_bar_buttons.py b/qframelesswindow/titlebar/title_bar_buttons.py index 6706a67..f14a0bd 100644 --- a/qframelesswindow/titlebar/title_bar_buttons.py +++ b/qframelesswindow/titlebar/title_bar_buttons.py @@ -1,9 +1,9 @@ # coding:utf-8 from enum import Enum -from PyQt5.QtCore import QFile, QPointF, QRectF, QSize, Qt, pyqtProperty -from PyQt5.QtGui import QColor, QIcon, QPainter, QPainterPath, QPen -from PyQt5.QtWidgets import QToolButton, QAbstractButton +from PyQt5.QtCore import QFile, QPointF, QRectF, Qt, pyqtProperty +from PyQt5.QtGui import QColor, QPainter, QPainterPath, QPen +from PyQt5.QtWidgets import QAbstractButton from PyQt5.QtSvg import QSvgRenderer from PyQt5.QtXml import QDomDocument @@ -48,6 +48,10 @@ def setState(self, state): self._state = state self.update() + def isPressed(self): + """ whether the button is pressed """ + return self._state == TitleBarButtonState.PRESSED + @deprecated def updateStyle(self, style): """ update the style of button """ @@ -304,4 +308,4 @@ def __init__(self, parent=None): self.setHoverColor(Qt.white) self.setPressedColor(Qt.white) self.setHoverBackgroundColor(QColor(232, 17, 35)) - self.setPressedBackgroundColor(QColor(241, 112, 122)) \ No newline at end of file + self.setPressedBackgroundColor(QColor(241, 112, 122)) diff --git a/screenshot/logo.png b/screenshot/logo.png new file mode 100644 index 0000000..14ff4eb Binary files /dev/null and b/screenshot/logo.png differ diff --git a/setup.py b/setup.py index 2b022a5..9a9ec5e 100644 --- a/setup.py +++ b/setup.py @@ -6,10 +6,10 @@ setuptools.setup( name="PyQt5-Frameless-Window", - version="0.1.5", + version="0.1.6", keywords="pyqt frameless", - author="Huang Zhengzhi", - author_email="1319158137@qq.com", + author="zhiyiYo", + author_email="shokokawaii@outlook.com", description="A cross-platform frameless window based on pyqt5, support Win32, X11, Wayland and macOS.", long_description=long_description, long_description_content_type='text/markdown',