Pra*_*ore 1 python qt window pyqt pyqt5
我正在为Windows / Linux开发开放源代码降价支持的最小笔记应用程序。我正在尝试删除标题栏并添加自己的按钮。我想要一个标题栏,只有两个自定义按钮,如图所示
目前我有这个:
我试过修改窗口标志:
self.setWindowFlags(QtCore.Qt.FramelessWindowHint),窗口没有边界,但是无法移动或调整窗口大小self.setWindowFlags(QtCore.Qt.CustomizeWindowHint),窗口可以调整大小,但不能移动,也不能摆脱窗口顶部的白色部分。任何帮助表示赞赏。您可以在Github上找到该项目在这里。
谢谢..
这是我的python代码:
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets, uic
import sys
import os
import markdown2 # https://github.com/trentm/python-markdown2
from PyQt5.QtCore import QRect
from PyQt5.QtGui import QFont
simpleUiForm = uic.loadUiType("Simple.ui")[0]
class SimpleWindow(QtWidgets.QMainWindow, simpleUiForm):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.markdown = markdown2.Markdown()
self.css = open(os.path.join("css", "default.css")).read()
self.editNote.setPlainText("")
#self.noteView = QtWebEngineWidgets.QWebEngineView(self)
self.installEventFilter(self)
self.displayNote.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
#self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
def eventFilter(self, object, event):
if event.type() == QtCore.QEvent.WindowActivate:
print("widget window has gained focus")
self.editNote.show()
self.displayNote.hide()
elif event.type() == QtCore.QEvent.WindowDeactivate:
print("widget window has lost focus")
note = self.editNote.toPlainText()
htmlNote = self.getStyledPage(note)
# print(note)
self.editNote.hide()
self.displayNote.show()
# print(htmlNote)
self.displayNote.setHtml(htmlNote)
elif event.type() == QtCore.QEvent.FocusIn:
print("widget has gained keyboard focus")
elif event.type() == QtCore.QEvent.FocusOut:
print("widget has lost keyboard focus")
return False
Run Code Online (Sandbox Code Playgroud)
UI文件按以下层次结构创建
以下是您必须遵循的步骤:
这是一个带有移动和按钮实现的小示例。您仍然必须使用相同的逻辑来实现调整大小。
import sys
from PyQt5.QtCore import QPoint
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QWidget
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.layout = QVBoxLayout()
self.layout.addWidget(MyBar(self))
self.setLayout(self.layout)
self.layout.setContentsMargins(0,0,0,0)
self.layout.addStretch(-1)
self.setMinimumSize(800,400)
self.setWindowFlags(Qt.FramelessWindowHint)
self.pressing = False
class MyBar(QWidget):
def __init__(self, parent):
super(MyBar, self).__init__()
self.parent = parent
print(self.parent.width())
self.layout = QHBoxLayout()
self.layout.setContentsMargins(0,0,0,0)
self.title = QLabel("My Own Bar")
btn_size = 35
self.btn_close = QPushButton("x")
self.btn_close.clicked.connect(self.btn_close_clicked)
self.btn_close.setFixedSize(btn_size,btn_size)
self.btn_close.setStyleSheet("background-color: red;")
self.btn_min = QPushButton("-")
self.btn_min.clicked.connect(self.btn_min_clicked)
self.btn_min.setFixedSize(btn_size, btn_size)
self.btn_min.setStyleSheet("background-color: gray;")
self.btn_max = QPushButton("+")
self.btn_max.clicked.connect(self.btn_max_clicked)
self.btn_max.setFixedSize(btn_size, btn_size)
self.btn_max.setStyleSheet("background-color: gray;")
self.title.setFixedHeight(35)
self.title.setAlignment(Qt.AlignCenter)
self.layout.addWidget(self.title)
self.layout.addWidget(self.btn_min)
self.layout.addWidget(self.btn_max)
self.layout.addWidget(self.btn_close)
self.title.setStyleSheet("""
background-color: black;
color: white;
""")
self.setLayout(self.layout)
self.start = QPoint(0, 0)
self.pressing = False
def resizeEvent(self, QResizeEvent):
super(MyBar, self).resizeEvent(QResizeEvent)
self.title.setFixedWidth(self.parent.width())
def mousePressEvent(self, event):
self.start = self.mapToGlobal(event.pos())
self.pressing = True
def mouseMoveEvent(self, event):
if self.pressing:
self.end = self.mapToGlobal(event.pos())
self.movement = self.end-self.start
self.parent.setGeometry(self.mapToGlobal(self.movement).x(),
self.mapToGlobal(self.movement).y(),
self.parent.width(),
self.parent.height())
self.start = self.end
def mouseReleaseEvent(self, QMouseEvent):
self.pressing = False
def btn_close_clicked(self):
self.parent.close()
def btn_max_clicked(self):
self.parent.showMaximized()
def btn_min_clicked(self):
self.parent.showMinimized()
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)
选项1:
选项2:
不用QGridLayout,您可以通过click pos来检测要单击的位置。
验证点击的x是否小于移动的pos的x,以了解它是向左还是向右移动以及被点击的位置。
计算方法与Option1相同
选项3:
提示:
好运:D
虽然接受的答案可以被认为是有效的,但它存在一些问题。
setGeometry()不合适(并且使用它的原因是错误的),因为它没有考虑样式设置的可能的帧边距;我修改了代码为主窗口提供更好的基础,简化了移动代码,并添加了其他功能,例如 QtwindowTitle()属性支持、按钮的标准 QStyle 图标(而不是文本)以及适当的最大化/正常按钮图标。请注意,标题标签未添加到布局中。
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
self.titleBar = MyBar(self)
self.setContentsMargins(0, self.titleBar.height(), 0, 0)
self.resize(640, self.titleBar.height() + 480)
def changeEvent(self, event):
if event.type() == event.WindowStateChange:
self.titleBar.windowStateChanged(self.windowState())
def resizeEvent(self, event):
self.titleBar.resize(self.width(), self.titleBar.height())
class MyBar(QWidget):
clickPos = None
def __init__(self, parent):
super(MyBar, self).__init__(parent)
self.setAutoFillBackground(True)
self.setBackgroundRole(QPalette.Shadow)
# alternatively:
# palette = self.palette()
# palette.setColor(palette.Window, Qt.black)
# palette.setColor(palette.WindowText, Qt.white)
# self.setPalette(palette)
layout = QHBoxLayout(self)
layout.setContentsMargins(1, 1, 1, 1)
layout.addStretch()
self.title = QLabel("My Own Bar", self, alignment=Qt.AlignCenter)
# if setPalette() was used above, this is not required
self.title.setForegroundRole(QPalette.Light)
style = self.style()
ref_size = self.fontMetrics().height()
ref_size += style.pixelMetric(style.PM_ButtonMargin) * 2
self.setMaximumHeight(ref_size + 2)
btn_size = QSize(ref_size, ref_size)
for target in ('min', 'normal', 'max', 'close'):
btn = QToolButton(self, focusPolicy=Qt.NoFocus)
layout.addWidget(btn)
btn.setFixedSize(btn_size)
iconType = getattr(style,
'SP_TitleBar{}Button'.format(target.capitalize()))
btn.setIcon(style.standardIcon(iconType))
if target == 'close':
colorNormal = 'red'
colorHover = 'orangered'
else:
colorNormal = 'palette(mid)'
colorHover = 'palette(light)'
btn.setStyleSheet('''
QToolButton {{
background-color: {};
}}
QToolButton:hover {{
background-color: {}
}}
'''.format(colorNormal, colorHover))
signal = getattr(self, target + 'Clicked')
btn.clicked.connect(signal)
setattr(self, target + 'Button', btn)
self.normalButton.hide()
self.updateTitle(parent.windowTitle())
parent.windowTitleChanged.connect(self.updateTitle)
def updateTitle(self, title=None):
if title is None:
title = self.window().windowTitle()
width = self.title.width()
width -= self.style().pixelMetric(QStyle.PM_LayoutHorizontalSpacing) * 2
self.title.setText(self.fontMetrics().elidedText(
title, Qt.ElideRight, width))
def windowStateChanged(self, state):
self.normalButton.setVisible(state == Qt.WindowMaximized)
self.maxButton.setVisible(state != Qt.WindowMaximized)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.clickPos = event.windowPos().toPoint()
def mouseMoveEvent(self, event):
if self.clickPos is not None:
self.window().move(event.globalPos() - self.clickPos)
def mouseReleaseEvent(self, QMouseEvent):
self.clickPos = None
def closeClicked(self):
self.window().close()
def maxClicked(self):
self.window().showMaximized()
def normalClicked(self):
self.window().showNormal()
def minClicked(self):
self.window().showMinimized()
def resizeEvent(self, event):
self.title.resize(self.minButton.x(), self.height())
self.updateTitle()
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWindow()
layout = QVBoxLayout(mw)
widget = QTextEdit()
layout.addWidget(widget)
mw.show()
mw.setWindowTitle('My custom window with a very, very long title')
sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)