[英]Differences in pyside6 and pyqt5
I am writing a program in Pyside6 and use my own Titlebar.我正在 Pyside6 中编写程序并使用我自己的标题栏。 When running with pyside6, I get this problem.
使用 pyside6 运行时,出现此问题。
I need to remove this space
我需要删除这个空间
Using PyQt5 everything is fine使用 PyQt5 一切正常
What differences in the work of these frameworks can cause this problem and what should be used to fix it.这些框架在工作中的哪些差异会导致这个问题,应该用什么来修复它。 the code on both frameworks is the same, but the result is different, I can't understand why this is happening
两个框架上的代码是一样的,但结果不同,我不明白为什么会这样
My code using PySide6我的代码使用 PySide6
TextEditorQt.py文本编辑器Qt.py
from PySide6 import QtGui
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from PySide6.QtWidgets import QApplication
from TextEditorUI import Ui_MainWindow, QMainWindow # импорт нашего сгенерированного файла
from PySide6.QtCore import QSettings, QPoint, QSize
from Titlebar import FramelessWindow
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(762, 580)
MainWindow.setStyleSheet(u"")
self.open_action = QAction(MainWindow)
self.open_action.setObjectName(u"open_action")
self.newfile_action = QAction(MainWindow)
self.newfile_action.setObjectName(u"newfile_action")
self.save_action = QAction(MainWindow)
self.save_action.setObjectName(u"save_action")
self.saveas_action = QAction(MainWindow)
self.saveas_action.setObjectName(u"saveas_action")
self.exit_action = QAction(MainWindow)
self.exit_action.setObjectName(u"exit_action")
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.gridLayout = QGridLayout(self.centralwidget)
self.gridLayout.setObjectName(u"gridLayout")
self.textEdit = QTextEdit(self.centralwidget)
self.textEdit.setObjectName(u"textEdit")
self.textEdit.setStyleSheet(u"alternate-background-color: rgb(85, 0, 255);\n"
"background-color: rgb(255, 255, 255);")
self.gridLayout.addWidget(self.textEdit, 1, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 762, 22))
self.menu = QMenu(self.menubar)
self.menu.setObjectName(u"menu")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar")
MainWindow.setStatusBar(self.statusbar)
self.menubar.addAction(self.menu.menuAction())
self.menu.addAction(self.open_action)
self.menu.addAction(self.newfile_action)
self.menu.addAction(self.save_action)
self.menu.addAction(self.saveas_action)
self.menu.addSeparator()
self.menu.addAction(self.exit_action)
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Matewriter", None))
self.open_action.setText(
QCoreApplication.translate("MainWindow", u"\u041e\u0442\u043a\u0440\u044b\u0442\u044c", None))
self.newfile_action.setText(QCoreApplication.translate("MainWindow", u"\u041d\u043e\u0432\u044b\u0439", None))
self.save_action.setText(
QCoreApplication.translate("MainWindow", u"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c", None))
self.saveas_action.setText(QCoreApplication.translate("MainWindow",
u"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a...",
None))
self.exit_action.setText(QCoreApplication.translate("MainWindow", u"\u0412\u044b\u0445\u043e\u0434", None))
# if QT_CONFIG(tooltip)
self.textEdit.setToolTip(
QCoreApplication.translate("MainWindow", u"<html><head/><body><p><br/></p></body></html>", None))
# endif // QT_CONFIG(tooltip)
self.menu.setTitle(QCoreApplication.translate("MainWindow", u"\u0424\u0430\u0439\u043b", None))
# retranslateUi
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)
self.resize(600, 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('Fusion')
w = FramelessWindow()
w.setWindowTitle('Тестовая строка заголовка')
w.setWindowIcon(QIcon('Qt.ico'))
# w.setWidget(MainWindow(MainWindow)) # Добавить свое окно
w.setWidget(MainWindow()) # !!!
w.show()
sys.exit(app.exec_())
Titlebar.py标题栏.py
from PySide6.QtCore import Qt, Signal, QPoint, QFileInfo
from PySide6.QtGui import QFont, QEnterEvent, QPainter, QColor, QPen
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)
# макет
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, 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.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)
The reason is that the named arguments to QVBoxLayout are not supported原因是不支持 QVBoxLayout 的命名参数
layout = QVBoxLayout(self, spacing=0)
The property needs to be set by calling the setter.该属性需要通过调用 setter 来设置。
layout = QVBoxLayout(self)
layout.setSpacing(0)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.