自定义标题栏窗口中调整Toolbar显示位置的方法
解决方案
你的问题根源在于使用了QMainWindow.addToolBar()方法,这个方法会让Qt自动将工具栏放置到主窗口的默认工具栏区域,而非你手动添加的垂直布局中。同时TitleBar类中存在冗余的标签页和编辑器相关代码,导致逻辑混乱。
以下是具体修改步骤:
1. 清理TitleBar类中的冗余代码
删除TitleBar.__init__中不属于标题栏职责的代码,这些内容应由MainWindow统一管理:
# 删除以下代码块 self.current_editor = self.parent().create_editor() self.current_editor.setFocus() self.text_editors = [] self.tabs = qtw.QTabWidget() self.tabs.setTabsClosable(True) self.tabs.tabBar().setMovable(True) # 同时删除提前调用父类动作创建的代码 self.parent()._createActions() self.parent()._connectActions()
2. 修改工具栏创建方式
将MainWindow._createToolBars方法改为直接实例化QToolBar,避免使用QMainWindow的默认工具栏管理:
def _createToolBars(self): # 直接创建QToolBar作为普通控件,完全由布局控制位置 self.file_toolbar = qtw.QToolBar("File", self) self.file_toolbar.setIconSize(qtc.QSize(22,22)) self.file_toolbar.addAction(self.new_action) self.file_toolbar.addAction(self.open_action) self.file_toolbar.addAction(self.save_action)
3. 调整MainWindow初始化顺序
将动作创建代码提前到标题栏实例化之前,确保标题栏的菜单栏能正确获取动作:
def __init__(self): super(MainWindow, self).__init__() # ... 其他初始化代码 ... # 先创建动作,再实例化标题栏 self._createActions() self.title_bar = TitleBar(self) # ... 后续代码 ...
修改后的完整代码
import sys from PySide6 import QtWidgets as qtw from PySide6 import QtCore as qtc from PySide6 import QtGui as qtg class TitleBar(qtw.QWidget): height = 35 def __init__(self, parent): super(TitleBar, self).__init__(parent) self.nav_maximize = """ QToolButton[accessibleName="btn_max"] { image: url(./icons/nav_maximize.png); background: #161a21; border: none; padding-right: 3px; } QToolButton[accessibleName="btn_max"]:hover { image: url(./icons/colored_maximize.png); background: #161a21; border: none; } """ self.nav_normal = """ QToolButton[accessibleName="btn_max"]{ image: url(./icons/nav_normal.png); background: #161a21; border: none; } QToolButton[accessibleName="btn_max"]:hover{ image: url(./icons/colored_normal.png); background: #161a21; border: none; } """ ### 窗口移动相关 ### self.prevGeo = self.geometry() self.pressing = False self.maximizedWindow=False ### [ end ] ### self.layout = qtw.QHBoxLayout() self.layout.setContentsMargins(0,0,10,0) self.menubar = qtw.QMenuBar() file_menu = self.menubar.addMenu('File') file_menu.addAction(self.parent().new_action) file_menu.addAction(self.parent().open_action) file_menu.addAction(self.parent().save_action) file_menu.addSeparator() file_menu.addAction(self.parent().exit_action) self.layout.addWidget(self.menubar) self.window_title = qtw.QLabel("Visual Studio Code") # 窗口标题 self.window_title.setAlignment(qtc.Qt.AlignCenter) self.window_title.setAccessibleName("lbl_title") self.window_title.setFixedHeight(self.height) self.layout.addStretch(1) # 让标题标签占据剩余空间 self.layout.addWidget(self.window_title) self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Fixed) self.maximizedWindow=False self.closeButton = qtw.QToolButton() self.closeButton.setAccessibleName("btn_close") self.closeButton.clicked.connect(self.onClickClose) self.maxButton = qtw.QToolButton() self.maxButton.setAccessibleName("btn_max") self.maxButton.setStyleSheet(self.nav_maximize) self.maxButton.clicked.connect(self.showMaxRestore) self.hideButton = qtw.QToolButton() self.hideButton.setAccessibleName("btn_min") self.hideButton.clicked.connect(self.onClickHide) self.layout.addWidget(self.hideButton) self.layout.addWidget(self.maxButton) self.layout.addWidget(self.closeButton) self.setLayout(self.layout) ##################################################### ## 标题栏最小化、最大化、关闭方法 ##################################################### def onClickClose(self): self.parent().close() def onClickHide(self): self.parent().showMinimized() def showMaxRestore(self): if(self.maximizedWindow): self.parent().showNormal() self.maximizedWindow = False self.maxButton.setStyleSheet(self.nav_maximize) else: self.prevGeo = self.parent().geometry() self.parent().showMaximized() self.maximizedWindow = True self.maxButton.setStyleSheet(self.nav_normal) def mouseReleaseEvent(self, event): if event.globalPosition().y() < 10: self.showMaxRestore() def mousePressEvent(self, event): self.prevMousePos = event.scenePosition() self.pressing = True if event.type() == qtc.QEvent.MouseButtonDblClick: self.showMaxRestore() def mouseMoveEvent(self, event): if(self.maximizedWindow): self.parent().showNormal() self.maximizedWindow= False self.maxButton.setStyleSheet(self.nav_maximize) self.prevMousePos = qtc.QPointF((self.prevGeo.width()*.5), (self.prevGeo.height()*.5)) if self.pressing: mousePosition = event.globalPosition() pos = mousePosition-self.prevMousePos x = pos.x() y = pos.y() self.parent().move(int(x), int(y)) ##################################################### ## END ##################################################### class MainWindow(qtw.QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.statusbar = self.statusBar() self.statusbar.showMessage("Ready") self.current_editor = self.create_editor() self.current_editor.setFocus() self.text_editors = [] self.setMinimumSize(400,250) self.resize(700,500) self.setWindowFlags(qtc.Qt.FramelessWindowHint| qtc.Qt.WindowMaximizeButtonHint| qtc.Qt.WindowMinimizeButtonHint | qtc.Qt.WindowStaysOnTopHint ) # 先创建动作,确保标题栏能获取到 self._createActions() self.title_bar = TitleBar(self) self.tabs = qtw.QTabWidget() self.tabs.setTabsClosable(True) self.tabs.tabBar().setMovable(True) self.tabs.tabCloseRequested.connect(self.remove_editor) self.tabs.currentChanged.connect(self.change_text_editor) self._createToolBars() self._connectActions() # 构建中央控件布局 widget = qtw.QWidget() layout = qtw.QVBoxLayout() layout.setContentsMargins(0,0,0,0) layout.addWidget(self.title_bar, 1) layout.addWidget(self.file_toolbar, 2) layout.addWidget(self.tabs, 3) layout.setSpacing(0) widget.setLayout(layout) self.setCentralWidget(widget) self.new_tab() self.closeTab() def create_editor(self): current_editor = qtw.QTextEdit() current_editor.setTabStopDistance(33) return current_editor def change_text_editor(self, index): if index < len(self.text_editors): self.current_editor = self.text_editors[index] def remove_editor(self, index): if self.tabs.count() < 2: return True self.tabs.removeTab(index) if index < len(self.text_editors): del self.text_editors[index] def closeTab(self): close_tab = qtg.QShortcut(qtg.QKeySequence("Ctrl+W"), self) close_tab.activated.connect(lambda:self.remove_editor(self.tabs.currentIndex())) def close(self): qtw.QApplication.quit() def new_tab(self, checked = False, title = "Untitled.txt"): editor_widget = qtw.QWidget() editor_layout = qtw.QVBoxLayout(editor_widget) editor_layout.setContentsMargins(0,0,0,0) self.current_editor = self.create_editor() self.text_editors.append(self.current_editor) editor_layout.addWidget(self.current_editor) tab_index = self.tabs.addTab(editor_widget, title) self.tabs.setCurrentIndex(tab_index) def open_document(self): options = qtw.QFileDialog.Options() self.filename, _ = qtw.QFileDialog.getOpenFileName( self, 'Open File',".", "(*.notes);;Text Files (*.txt);;Python Files (*.py)", options=options ) if self.filename: with open(self.filename,"rt") as file: content = file.read() self.current_editor = self.create_editor() self.current_editor.setText(content) editor_widget = qtw.QWidget() editor_layout = qtw.QVBoxLayout(editor_widget) editor_layout.setContentsMargins(0,0,0,0) editor_layout.addWidget(self.current_editor) currentIndex = self.tabs.addTab(editor_widget, str(self.filename)) self.text_editors.append(self.current_editor) self.tabs.setCurrentIndex(currentIndex) def _createToolBars(self): self.file_toolbar = qtw.QToolBar("File", self) self.file_toolbar.setIconSize(qtc.QSize(22,22)) self.file_toolbar.addAction(self.new_action) self.file_toolbar.addAction(self.open_action) self.file_toolbar.addAction(self.save_action) def _createActions(self): self.new_action = qtg.QAction(qtg.QIcon("./icons/new_file.png"),"New", self) self.open_action = qtg.QAction(qtg.QIcon("./icons/folder.png"),"Open", self) self.save_action = qtg.QAction(qtg.QIcon("./icons/save.png"),"Save", self) self.exit_action = qtg.QAction(qtg.QIcon("./icons/close.png"), "Exit", self) self.new_action.setShortcut("Ctrl+N") self.open_action.setShortcut("Ctrl+O") self.save_action.setShortcut("Ctrl+S") self.exit_action.setShortcut("Ctrl+Shift+Q") self.new_action.setToolTip("New file") self.open_action.setToolTip("Open a file") self.save_action.setToolTip("Save a file") self.exit_action.setToolTip("Exit Program") def _connectActions(self): self.new_action.triggered.connect(self.new_tab) self.open_action.triggered.connect(self.open_document) self.save_action.triggered.connect(self.save_document) self.exit_action.triggered.connect(self.close) def save_document (self): if not self.current_editor.document().isModified(): self.statusBar().showMessage("There are no texts to be saved!") else: options = qtw.QFileDialog.Options() file_filter = 'Notes_ file (*.notes);; Text file (*.txt);; Python file (*.py)' if not hasattr(self, 'filename') or not self.filename: self.filename = qtw.QFileDialog.getSaveFileName(self,caption='Save File',directory=".",filter=file_filter,initialFilter='Notes Files (*.notes)')[0] if self.filename: with open(self.filename,"wt") as file: file.write(self.current_editor.toHtml()) self.tabs.setTabText(self.tabs.currentIndex(), str(self.filename)) self.statusBar().showMessage(f"Saved to {self.filename}") self.changesSaved = True if __name__ == "__main__": app = qtw.QApplication(sys.argv) main = MainWindow() main.setStyleSheet( """ QToolButton[accessibleName="btn_close"] { image: url(./icons/nav_close.png); background: #161a21; border: none; } QToolButton[accessibleName="btn_close"]:hover { image: url(./icons/colored_close.png); background: #161a21; border: none; } QToolButton[accessibleName="btn_min"] { image: url(./icons/nav_minimize.png); background: #161a21; border: none; padding-right: 3px; } QToolButton[accessibleName="btn_min"]:hover { image: url(./icons/colored_minimize.png); background: #161a21; border: none; padding-right: 3px; } """ ) main.show() sys.exit(app.exec())
额外优化说明
- 将
TitleBar中对主窗口的硬编码改为self.parent(),消除全局变量依赖 - 修正
new_tab方法逻辑,用普通QWidget包裹编辑器,替代错误的QMainWindow作为标签页内容 - 修复
save_document中filename属性的判断逻辑,避免属性不存在的报错
内容的提问来源于stack exchange,提问作者adfinem_rising
相关产品推荐
相关产品推荐

