如何创建抽屉实例并将其附加到 MainWindow
How to create a Drawer instance and attach it to MainWindow
我正在努力向我的应用程序添加侧边菜单。
我有一个 QMainWindow
实例,我希望向其添加一个 QDrawer
对象并实现类似于 this sample.
的效果
不幸的是,PySide2
似乎只提供 QMenu
、QTooltip
和 QDialog
小部件,它们继承自 Popup
class, QDrawer
无处可寻。但是,在 QML 文件中使用 Drawer
标签效果很好。难道还不能以编程方式创建 QDrawer
的实例吗?
作为另一次尝试,我尝试从 QML 文件加载一个 Drawer
实例并将其附加到我的 QMainWindow
。不幸的是,我不太明白我应该指定什么作为父级,我应该将它包装在什么中,我应该使用什么参数等等 - 任何建议将不胜感激(尽管我更愿意以编程方式创建和配置它)。
我的目标是创建一个 QMainWindow
,带有工具栏、中央小部件和 QDrawer
实例作为侧面导航菜单(例如 this 示例)。您能否分享一些示例或解释该怎么做?
一个可能的解决方案是使用 Qt Widgets 实现抽屉,主要功能是使用 QXAnimation 为宽度的变化设置动画,另一个任务是设置锚点,使其占据必要的高度。一个简单的示例如下面的代码所示:
import os
from PySide2 import QtCore, QtGui, QtWidgets
class Drawer(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setFixedWidth(0)
self.setContentsMargins(0, 0, 0, 0)
# self.setFixedWidth(0)
self._maximum_width = 0
self._animation = QtCore.QPropertyAnimation(self, b"width")
self._animation.setStartValue(0)
self._animation.setDuration(1000)
self._animation.valueChanged.connect(self.setFixedWidth)
self.hide()
@property
def maximum_width(self):
return self._maximum_width
@maximum_width.setter
def maximum_width(self, w):
self._maximum_width = w
self._animation.setEndValue(self.maximum_width)
def open(self):
self._animation.setDirection(QtCore.QAbstractAnimation.Forward)
self._animation.start()
self.show()
def close(self):
self._animation.setDirection(QtCore.QAbstractAnimation.Backward)
self._animation.start()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
self.tool_button = QtWidgets.QToolButton(
checkable=True, iconSize=QtCore.QSize(36, 36)
)
content_widget = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
content_widget.setText("Content")
content_widget.setStyleSheet("background-color: green")
lay = QtWidgets.QVBoxLayout(central_widget)
lay.setSpacing(0)
lay.setContentsMargins(0, 0, 0, 0)
lay.addWidget(self.tool_button)
lay.addWidget(content_widget)
self.resize(640, 480)
self.drawer = Drawer(self)
self.drawer.move(0, self.tool_button.sizeHint().height())
self.drawer.maximum_width = 200
self.drawer.raise_()
content_lay = QtWidgets.QVBoxLayout()
content_lay.setContentsMargins(0, 0, 0, 0)
label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
label.setText("Content\nDrawer")
label.setStyleSheet("background-color: red")
content_lay.addWidget(label)
self.drawer.setLayout(content_lay)
self.tool_button.toggled.connect(self.onToggled)
self.onToggled(self.tool_button.isChecked())
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.onCustomContextMenuRequested)
@QtCore.Slot()
def onCustomContextMenuRequested(self):
menu = QtWidgets.QMenu()
quit_action = menu.addAction(self.tr("Close"))
action = menu.exec_(QtGui.QCursor.pos())
if action == quit_action:
self.close()
@QtCore.Slot(bool)
def onToggled(self, checked):
if checked:
self.tool_button.setIcon(
self.style().standardIcon(QtWidgets.QStyle.SP_MediaStop)
)
self.drawer.open()
else:
self.tool_button.setIcon(
self.style().standardIcon(QtWidgets.QStyle.SP_MediaPlay)
)
self.drawer.close()
def resizeEvent(self, event):
self.drawer.setFixedHeight(self.height() - self.drawer.pos().y())
super().resizeEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
我正在努力向我的应用程序添加侧边菜单。
我有一个 QMainWindow
实例,我希望向其添加一个 QDrawer
对象并实现类似于 this sample.
不幸的是,PySide2
似乎只提供 QMenu
、QTooltip
和 QDialog
小部件,它们继承自 Popup
class, QDrawer
无处可寻。但是,在 QML 文件中使用 Drawer
标签效果很好。难道还不能以编程方式创建 QDrawer
的实例吗?
作为另一次尝试,我尝试从 QML 文件加载一个 Drawer
实例并将其附加到我的 QMainWindow
。不幸的是,我不太明白我应该指定什么作为父级,我应该将它包装在什么中,我应该使用什么参数等等 - 任何建议将不胜感激(尽管我更愿意以编程方式创建和配置它)。
我的目标是创建一个 QMainWindow
,带有工具栏、中央小部件和 QDrawer
实例作为侧面导航菜单(例如 this 示例)。您能否分享一些示例或解释该怎么做?
一个可能的解决方案是使用 Qt Widgets 实现抽屉,主要功能是使用 QXAnimation 为宽度的变化设置动画,另一个任务是设置锚点,使其占据必要的高度。一个简单的示例如下面的代码所示:
import os
from PySide2 import QtCore, QtGui, QtWidgets
class Drawer(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setFixedWidth(0)
self.setContentsMargins(0, 0, 0, 0)
# self.setFixedWidth(0)
self._maximum_width = 0
self._animation = QtCore.QPropertyAnimation(self, b"width")
self._animation.setStartValue(0)
self._animation.setDuration(1000)
self._animation.valueChanged.connect(self.setFixedWidth)
self.hide()
@property
def maximum_width(self):
return self._maximum_width
@maximum_width.setter
def maximum_width(self, w):
self._maximum_width = w
self._animation.setEndValue(self.maximum_width)
def open(self):
self._animation.setDirection(QtCore.QAbstractAnimation.Forward)
self._animation.start()
self.show()
def close(self):
self._animation.setDirection(QtCore.QAbstractAnimation.Backward)
self._animation.start()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
self.tool_button = QtWidgets.QToolButton(
checkable=True, iconSize=QtCore.QSize(36, 36)
)
content_widget = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
content_widget.setText("Content")
content_widget.setStyleSheet("background-color: green")
lay = QtWidgets.QVBoxLayout(central_widget)
lay.setSpacing(0)
lay.setContentsMargins(0, 0, 0, 0)
lay.addWidget(self.tool_button)
lay.addWidget(content_widget)
self.resize(640, 480)
self.drawer = Drawer(self)
self.drawer.move(0, self.tool_button.sizeHint().height())
self.drawer.maximum_width = 200
self.drawer.raise_()
content_lay = QtWidgets.QVBoxLayout()
content_lay.setContentsMargins(0, 0, 0, 0)
label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
label.setText("Content\nDrawer")
label.setStyleSheet("background-color: red")
content_lay.addWidget(label)
self.drawer.setLayout(content_lay)
self.tool_button.toggled.connect(self.onToggled)
self.onToggled(self.tool_button.isChecked())
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.onCustomContextMenuRequested)
@QtCore.Slot()
def onCustomContextMenuRequested(self):
menu = QtWidgets.QMenu()
quit_action = menu.addAction(self.tr("Close"))
action = menu.exec_(QtGui.QCursor.pos())
if action == quit_action:
self.close()
@QtCore.Slot(bool)
def onToggled(self, checked):
if checked:
self.tool_button.setIcon(
self.style().standardIcon(QtWidgets.QStyle.SP_MediaStop)
)
self.drawer.open()
else:
self.tool_button.setIcon(
self.style().standardIcon(QtWidgets.QStyle.SP_MediaPlay)
)
self.drawer.close()
def resizeEvent(self, event):
self.drawer.setFixedHeight(self.height() - self.drawer.pos().y())
super().resizeEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())