Details
-
Bug
-
Resolution: Out of scope
-
Not Evaluated
-
None
-
6.0.3
-
None
Description
Я пишу программу на Pyside6 и использую свой собственный titlebar. При запуске с pyside6 у меня возникает эта проблема. При запуске с помощью Pyside6 результат на первом скриншоте. (Проблема в том что между тайтлбаром и окном существует разрыв(прозрачное пространство))
Используя PyQt5, все в порядке (2 скриншот)
Какие отличия в работе этих фреймворков могут вызвать эту проблему и что следует использовать для ее устранения. Код в обоих фреймворках одинаковый, но результат разный, я не могу понять, почему это происходит.
TextEditorQt.py
from PySide6 import QtGui from TextEditorUI import * from PySide6.QtWidgets import QApplication from TextEditorUI import Ui_MainWindow, QMainWindow # импорт нашего сгенерированного файла from PySide6.QtCore import QSettings, QPoint, QSize, QFile from Titlebar import FramelessWindow class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowIcon(QtGui.QIcon('icon.ico')) self.setupUi(self) self.curFile = '' self.setCurrentFile('') self.createStatusBar() self.textEdit.document().contentsChanged.connect(self.documentWasModified) self.setCurrentFile('') self.settings = QSettings('Matewriter', 'Matewriter') self.exit_action.triggered.connect(QApplication.quit) self.save_action.triggered.connect(self.save) self.open_action.triggered.connect(self.open) self.newfile_action.triggered.connect(self.newFile) self.saveas_action.triggered.connect(self.saveAs) self.open_action.setShortcut('Ctrl+O') self.newfile_action.setShortcut('Ctrl+N') self.save_action.setShortcut('Ctrl+S') # Конфиги окна windowScreenGeometry = self.settings.value("windowScreenGeometry") windowScreenState = self.settings.value("windowScreenState") if windowScreenGeometry: self.restoreGeometry(windowScreenGeometry) else: self.resize(600) if windowScreenState: self.restoreState(windowScreenState) def closeEvent(self, event): self.settings.setValue("windowScreenGeometry", self.saveGeometry()) self.settings.setValue("windowScreenState", self.saveState()) if self.maybeSave(): self.writeSettings() event.accept() else: event.ignore() def newFile(self): if self.maybeSave(): self.textEdit.clear() self.setCurrentFile('') def open(self): if self.maybeSave(): fileName, _ = QFileDialog.getOpenFileName(self) if fileName: self.loadFile(fileName) def save(self): if self.curFile: return self.saveFile(self.curFile) return self.saveAs() def saveAs(self): fileName, _ = QFileDialog.getSaveFileName(self) if fileName: return self.saveFile(fileName) return False def documentWasModified(self): self.setWindowModified(self.textEdit.document().isModified()) def createStatusBar(self): self.statusBar().showMessage("Ready") def readSettings(self): settings = QSettings("MateWriter") pos = settings.value("pos", QPoint(200, 200)) size = settings.value("size", QSize(400, 400)) self.resize(size) self.move(pos) def writeSettings(self): settings = QSettings("MateWriter") settings.setValue("pos", self.pos()) settings.setValue("size", self.size()) def maybeSave(self): if self.textEdit.document().isModified(): ret = QMessageBox.warning(self, "MateWriter", "The document has been modified.\nDo you want to save " "your changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if ret == QMessageBox.Save: return self.save() if ret == QMessageBox.Cancel: return False return True def loadFile(self, fileName): file = QFile(fileName) if not file.open(QFile.ReadOnly | QFile.Text): QMessageBox.warning(self, "MateWriter", "Cannot read file %s:\n%s." % (fileName, file.errorString())) return inf = QTextStream(file) QApplication.setOverrideCursor(Qt.WaitCursor) self.textEdit.setPlainText(inf.readAll()) QApplication.restoreOverrideCursor() self.setCurrentFile(fileName) self.statusBar().showMessage("File loaded", 2000) def saveFile(self, fileName): file = QFile(fileName) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning(self, "MateWriter", "Cannot write file %s:\n%s." % (fileName, file.errorString())) return False outf = QTextStream(file) QApplication.setOverrideCursor(Qt.WaitCursor) outf << self.textEdit.toPlainText() QApplication.restoreOverrideCursor() self.setCurrentFile(fileName) self.statusBar().showMessage("File saved", 2000) return True def setCurrentFile(self, fileName): self.curFile = fileName self.textEdit.document().setModified(False) self.setWindowModified(False) if self.curFile: shownName = self.strippedName(self.curFile) else: shownName = 'untitled.txt' self.setWindowTitle(" %s[*] - MateWriter" % shownName) def strippedName(self, fullFileName): return QFileInfo(fullFileName).fileName() if __name__ == '__main__': import sys app = QApplication(sys.argv) app.setStyle('windowsvista') w = FramelessWindow() w.setWindowTitle('MateWriter') w.setWindowIcon(QIcon('icon-white.ico')) # w.setWidget(MainWindow(MainWindow)) # Добавить свое окно w.setWidget(MainWindow()) # !!! w.show() sys.exit(app.exec_())
Titlebar.py
from PySide6.QtCore import Qt, Signal, QPoint, QFileInfo from PySide6.QtGui import QFont, QEnterEvent, QPainter, QColor, QPen, QIcon from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QSpacerItem, QSizePolicy, QPushButton) class TitleBar(QWidget): # Сигнал минимизации окна windowMinimumed = Signal() # увеличить максимальный сигнал окна windowMaximumed = Signal() # сигнал восстановления окна windowNormaled = Signal() # сигнал закрытия окна windowClosed = Signal() # Окно мобильных windowMoved = Signal(QPoint) # Сигнал Своя Кнопка +++ signalButtonMy = Signal() 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) # Подключение стиля self.setStyleSheet('Titlebar.qss') self.setStyleSheet(open("Titlebar.qss", "r").read()) # макет layout = QHBoxLayout(self, spacing=0) layout.setContentsMargins(0, 0, 0, 0) # значок окна self.iconLabel = QLabel(self) self.iconLabel.setMargin(10) # self.iconLabel.setScaledContents(True) layout.addWidget(self.iconLabel) # название окна self.titleLabel = QLabel(self) self.titleLabel.setMargin(2) layout.addWidget(self.titleLabel) # Средний телескопический бар layout.addSpacerItem(QSpacerItem( 40, 100, QSizePolicy.Expanding, QSizePolicy.Minimum)) # Использовать шрифты Webdings для отображения значков font = self.font() or QFont() font.setFamily('Webdings') # Своя Кнопка self.buttonMy = QPushButton(self, clicked=self.showButtonMy, objectName='buttonMy') self.buttonMy.setIcon(QIcon('icon-white.ico')) 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.resize(762, 580) # Фон прозрачный 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)
Attachments
Issue Links
- relates to
-
PYSIDE-1305 Unknown keyword args on constructors silently ignored
- Closed