亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

PyQt5通過拖動選項卡移動QDockWidget

PyQt5通過拖動選項卡移動QDockWidget

慕容森 2023-06-27 17:58:41
下面的剪輯顯示了QDockWidget通過拖動選項卡(而不是標題欄)在停靠區域之間拖動 - 但當我使用 PyQt 5.15.0 嘗試此操作時,它不起作用,選項卡不會分離。我怎樣才能啟用這種行為?我的代碼:from PyQt5 import QtCore, QtGui, QtWidgetsfrom PyQt5.QtCore import Qtif __name__ == "__main__":? ? app = QtWidgets.QApplication([])? ? main = QtWidgets.QMainWindow()? ? dock1 = QtWidgets.QDockWidget("Blue")? ? dock2 = QtWidgets.QDockWidget("Green")? ? dock3 = QtWidgets.QDockWidget("Red")? ? content1 = QtWidgets.QWidget()? ? content1.setStyleSheet("background-color:blue;")? ? content2 = QtWidgets.QWidget()? ? content2.setStyleSheet("background-color:green;")? ? content3 = QtWidgets.QWidget()? ? content3.setStyleSheet("background-color:red;")? ? dock1.setWidget(content1)? ? dock2.setWidget(content2)? ? dock3.setWidget(content3)? ? dock1.setAllowedAreas(Qt.AllDockWidgetAreas)? ? dock2.setAllowedAreas(Qt.AllDockWidgetAreas)? ? dock3.setAllowedAreas(Qt.AllDockWidgetAreas)? ? main.addDockWidget(Qt.LeftDockWidgetArea, dock1)? ? main.tabifyDockWidget(dock1, dock2)? ? main.addDockWidget(Qt.RightDockWidgetArea, dock3)? ? main.resize(400, 200)? ? main.show()? ? app.exec_()
查看完整描述

2 回答

?
一只斗牛犬

TA貢獻1784條經驗 獲得超2個贊

我的問題的解決方案是GroupedDraggingsetDockOptions.?QMainWindow我設法通過下面的代碼獲得了非常漂亮的外觀和行為,就像我想要的那樣。

from PyQt5 import QtCore, QtGui, QtWidgets

from PyQt5.QtCore import Qt



class DockWidget(QtWidgets.QDockWidget):

? ? def __init__(self, title: str):

? ? ? ? super().__init__(title)

? ? ? ? self.setTitleBarWidget(QtWidgets.QWidget())

? ? ? ? self.dockLocationChanged.connect(self.on_dockLocationChanged)


? ? def on_dockLocationChanged(self):

? ? ? ? main: QtWidgets.QMainWindow = self.parent()

? ? ? ? all_dock_widgets = main.findChildren(QtWidgets.QDockWidget)


? ? ? ? for dock_widget in all_dock_widgets:

? ? ? ? ? ? sibling_tabs = main.tabifiedDockWidgets(dock_widget)

? ? ? ? ? ? # If you pull a tab out of a group the other tabs still see it as a sibling while dragging...

? ? ? ? ? ? sibling_tabs = [s for s in sibling_tabs if not s.isFloating()]


? ? ? ? ? ? if len(sibling_tabs) != 0:

? ? ? ? ? ? ? ? # Hide title bar

? ? ? ? ? ? ? ? dock_widget.setTitleBarWidget(QtWidgets.QWidget())

? ? ? ? ? ? else:

? ? ? ? ? ? ? ? # Re-enable title bar

? ? ? ? ? ? ? ? dock_widget.setTitleBarWidget(None)


? ? def minimumSizeHint(self) -> QtCore.QSize:

? ? ? ? return QtCore.QSize(100, 100)



if __name__ == "__main__":

? ? app = QtWidgets.QApplication([])

? ? main = QtWidgets.QMainWindow()


? ? dock1 = DockWidget("Blue")

? ? dock2 = DockWidget("Green")

? ? dock3 = DockWidget("Red")


? ? content1 = QtWidgets.QWidget()

? ? content1.setStyleSheet("background-color:blue;")

? ? content1.setMinimumSize(QtCore.QSize(50, 50))


? ? content2 = QtWidgets.QWidget()

? ? content2.setStyleSheet("background-color:green;")

? ? content2.setMinimumSize(QtCore.QSize(50, 50))


? ? content3 = QtWidgets.QWidget()

? ? content3.setStyleSheet("background-color:red;")

? ? content3.setMinimumSize(QtCore.QSize(50, 50))


? ? dock1.setWidget(content1)

? ? dock2.setWidget(content2)

? ? dock3.setWidget(content3)


? ? dock1.setAllowedAreas(Qt.AllDockWidgetAreas)

? ? dock2.setAllowedAreas(Qt.AllDockWidgetAreas)

? ? dock3.setAllowedAreas(Qt.AllDockWidgetAreas)


? ? main.addDockWidget(Qt.LeftDockWidgetArea, dock1)

? ? main.tabifyDockWidget(dock1, dock2)

? ? main.addDockWidget(Qt.RightDockWidgetArea, dock3)


? ? main.setDockOptions(main.GroupedDragging | main.AllowTabbedDocks | main.AllowNestedDocks)


? ? main.setTabPosition(Qt.AllDockWidgetAreas, QtWidgets.QTabWidget.North)

? ? main.resize(400, 200)

? ? main.show()


? ? app.exec_()


查看完整回答
反對 回復 2023-06-27
?
LEATH

TA貢獻1936條經驗 獲得超7個贊

將其發布為已接受答案的一點額外內容。該版本適用于 Qt5 和 Qt6,并且能夠檢測極端情況,例如拉出選項卡并將其放入同一組中或將浮動選項卡組與停靠窗口合并:


from PySide6 import QtCore, QtWidgets

from PySide6.QtCore import Qt


from typing import TypeVar, List, Optional


TDockWidget = TypeVar('TDockWidget', bound='DockWidget')



class DockWidget(QtWidgets.QDockWidget):

    def __init__(self: TDockWidget, title: str, parent: Optional[QtWidgets.QWidget] = None) -> None:

        super(_DockWidget, self).__init__(title, parent)

        self.setTitleBarWidget(QtWidgets.QWidget())

        self.visibilityChanged.connect(self.on_visibility_changed)

        self.dockLocationChanged.connect(self.on_dock_location_changed)


    @QtCore.Slot(bool)

    def on_visibility_changed(self: TDockWidget, is_visible: bool) -> None:

        # this visibility monitor is really only needed to detect merges of

        # tabbed, floating windows with existing docked windows

        if not is_visible and isinstance(self.parent(), QtWidgets.QMainWindow):

            main_window: QtWidgets.QMainWindow = self.parent()

            all_dockwidgets: List[QtWidgets.QDockWidget] = main_window.findChildren(QtWidgets.QDockWidget)

            for dockwidget in all_dockwidgets:

                if hasattr(dockwidget, 'on_dock_location_changed'):

                    dockwidget.on_dock_location_changed(main_window.dockWidgetArea(dockwidget), False)


    @QtCore.Slot(Qt.DockWidgetArea)

    def on_dock_location_changed(self: TDockWidget, area: Qt.DockWidgetArea, update_others: bool = True) -> None:

        if not isinstance(self.parent(), QtWidgets.QMainWindow):

            # mysterious parents call for a title

            self.setTitleBarWidget(None)

            return


        main_window: QtWidgets.QMainWindow = self.parent()

        if not main_window.tabifiedDockWidgets(self):

            # if there's no siblings we ain't a tab!

            self.setTitleBarWidget(None)


            if not update_others:

                # prevent infinite recursion

                return


            # force an update to all other docks that may now no longer be tabs

            all_dockwidgets: List[QtWidgets.QDockWidget] = main_window.findChildren(QtWidgets.QDockWidget)

            for dockwidget in all_dockwidgets:

                if dockwidget != self and hasattr(dockwidget, 'on_dock_location_changed'):

                    dockwidget.on_dock_location_changed(main_window.dockWidgetArea(dockwidget), False)

            return


        # at this point the dockwidget is either a resting tab or a tab

        # that is being dragged and hasn't been dropped yet (siblings are updated post-drop)

        # collect all siblings of this dockwidget...

        tab_siblings: List[QtWidgets.QDockWidget] = main_window.tabifiedDockWidgets(self)

        # and filter for non-floating siblings in the same area

        tab_siblings = [x for x in tab_siblings if main_window.dockWidgetArea(x) == area and not x.isFloating()]


        if tab_siblings:

            if self.titleBarWidget() is not None:

                # no changes needed, prevent infinite recursion

                return


            # show a title if we're not floating (this tab is settled),

            # hide it otherwise (this tab just became floating but wasn't dropped)

            self.setTitleBarWidget(QtWidgets.QWidget() if not self.isFloating() else None)


            # in this case it's also a good idea to tell to reconsider their situation

            # since Qt won't notify them separately

            for sibling in tab_siblings:

                if hasattr(sibling, 'on_dock_location_changed'):

                    sibling.on_dock_location_changed(main_window.dockWidgetArea(sibling), True)

        else:

            self.setTitleBarWidget(None)



if __name__ == "__main__":

    app = QtWidgets.QApplication([])

    main = QtWidgets.QMainWindow()


    dock1 = DockWidget("Blue")

    dock2 = DockWidget("Green")

    dock3 = DockWidget("Red")


    content1 = QtWidgets.QWidget()

    content1.setStyleSheet("background-color:blue;")

    content1.setMinimumSize(QtCore.QSize(50, 50))


    content2 = QtWidgets.QWidget()

    content2.setStyleSheet("background-color:green;")

    content2.setMinimumSize(QtCore.QSize(50, 50))


    content3 = QtWidgets.QWidget()

    content3.setStyleSheet("background-color:red;")

    content3.setMinimumSize(QtCore.QSize(50, 50))


    dock1.setWidget(content1)

    dock2.setWidget(content2)

    dock3.setWidget(content3)


    dock1.setAllowedAreas(Qt.AllDockWidgetAreas)

    dock2.setAllowedAreas(Qt.AllDockWidgetAreas)

    dock3.setAllowedAreas(Qt.AllDockWidgetAreas)


    main.addDockWidget(Qt.LeftDockWidgetArea, dock1)

    main.tabifyDockWidget(dock1, dock2)

    main.addDockWidget(Qt.RightDockWidgetArea, dock3)


    main.setDockOptions(main.GroupedDragging | main.AllowTabbedDocks | main.AllowNestedDocks)


    main.setTabPosition(Qt.AllDockWidgetAreas, QtWidgets.QTabWidget.North)

    main.resize(400, 200)

    main.show()


    app.exec_()


查看完整回答
反對 回復 2023-06-27
  • 2 回答
  • 0 關注
  • 292 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號