Compare commits

...

10 Commits

Author SHA1 Message Date
玉宇清音 b75d2f4d93 x 2024-01-27 09:54:39 +08:00
玉宇清音 6dbeaf3837 save 2024-01-14 09:01:09 +08:00
玉宇清音 fdf57c51fd pycharm配置更新 2024-01-02 19:27:31 +08:00
玉宇清音 6c39e2d295 pycharm配置更新 2023-12-31 20:08:24 +08:00
玉宇清音 113e244448 更新README 2023-12-31 18:03:55 +08:00
玉宇清音 a7f701375e 添加图片 2023-12-31 17:58:24 +08:00
heisehuanyin 847ca2f002
Create README.md 2023-12-31 17:44:22 +08:00
玉宇清音 d12945f7b4 基本拼接功能的实现 2023-12-31 17:38:12 +08:00
玉宇清音 f7223984aa 携带bug的功能实现版本 2023-12-31 10:53:10 +08:00
玉宇清音 108d307ccd 删除冗余打印代码 2023-12-30 21:55:15 +08:00
11 changed files with 220 additions and 45 deletions

View File

@ -4,11 +4,9 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="55c45e43-6fd9-4244-902d-86f83a348f5b" name="Changes" comment="">
<list default="true" id="55c45e43-6fd9-4244-902d-86f83a348f5b" name="Changes" comment="pycharm配置更新">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockPanel.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockPanel.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Manager.py" beforeDir="false" afterPath="$PROJECT_DIR$/Manager.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/SplitPanel.py" beforeDir="false" afterPath="$PROJECT_DIR$/SplitPanel.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -23,11 +21,34 @@
</option>
</component>
<component name="Git.Settings">
<option name="PUSH_TAGS">
<GitPushTagMode>
<option name="argument" value="--tags" />
<option name="title" value="All" />
</GitPushTagMode>
</option>
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="GitHubPullRequestSearchHistory">{
&quot;lastFilter&quot;: {
&quot;state&quot;: &quot;OPEN&quot;,
&quot;assignee&quot;: &quot;heisehuanyin&quot;
}
}</component>
<component name="GithubPullRequestsUISettings">
<option name="selectedUrlAndAccountId">
<UrlAndAccount>
<option name="accountId" value="e2cefb47-a99c-4e4b-bae0-586cfe078ae3" />
<option name="url" value="https://github.com/heisehuanyin/QDragsView.git" />
</UrlAndAccount>
</option>
</component>
<component name="HierarchyBrowserManager">
<option name="IS_AUTOSCROLL_TO_SOURCE" value="true" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 2
}</component>
@ -39,20 +60,20 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"Python.DockPanel.executor": "Debug",
"Python.Manager.executor": "Run",
"Python.SplitPanel.executor": "Run",
"Python.Widget.executor": "Run",
"Python.test.executor": "Run",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
"git-widget-placeholder": "main",
"settings.editor.selected.configurable": "preferences.sourceCode"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;Python.DockPanel.executor&quot;: &quot;Debug&quot;,
&quot;Python.Manager.executor&quot;: &quot;Run&quot;,
&quot;Python.SplitPanel.executor&quot;: &quot;Run&quot;,
&quot;Python.Widget.executor&quot;: &quot;Run&quot;,
&quot;Python.test.executor&quot;: &quot;Run&quot;,
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;main&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;inlay.hints&quot;
}
}]]></component>
}</component>
<component name="RunManager" selected="Python.SplitPanel">
<configuration name="DockPanel" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="SimpleIDE" />
@ -114,7 +135,7 @@
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/SplitPanel.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="EMULATE_TERMINAL" value="true" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
@ -142,6 +163,12 @@
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<list>
<item itemvalue="Python.DockPanel" />
<item itemvalue="Python.Manager" />
<item itemvalue="Python.SplitPanel" />
<item itemvalue="Python.test" />
</list>
<recent_temporary>
<list>
<item itemvalue="Python.SplitPanel" />
@ -167,6 +194,63 @@
<option name="presentableId" value="Default" />
<updated>1703843144486</updated>
</task>
<task id="LOCAL-00001" summary="删除冗余打印代码">
<option name="closed" value="true" />
<created>1703944526835</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1703944526835</updated>
</task>
<task id="LOCAL-00002" summary="基本拼接功能的实现">
<option name="closed" value="true" />
<created>1704015498724</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1704015498724</updated>
</task>
<task id="LOCAL-00003" summary="添加图片">
<option name="closed" value="true" />
<created>1704016704879</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1704016704879</updated>
</task>
<task id="LOCAL-00004" summary="更新README">
<option name="closed" value="true" />
<created>1704017038264</created>
<option name="number" value="00004" />
<option name="presentableId" value="LOCAL-00004" />
<option name="project" value="LOCAL" />
<updated>1704017038264</updated>
</task>
<task id="LOCAL-00005" summary="pycharm配置更新">
<option name="closed" value="true" />
<created>1704024507110</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1704024507110</updated>
</task>
<task id="LOCAL-00006" summary="pycharm配置更新">
<option name="closed" value="true" />
<created>1704194851950</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1704194851950</updated>
</task>
<option name="localTasksCounter" value="7" />
<servers />
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="删除冗余打印代码" />
<MESSAGE value="基本拼接功能的实现" />
<MESSAGE value="添加图片" />
<MESSAGE value="更新README" />
<MESSAGE value="pycharm配置更新" />
<option name="LAST_COMMIT_MESSAGE" value="pycharm配置更新" />
</component>
</project>

View File

@ -32,12 +32,12 @@ class DragHeader(QFrame):
self.min_button=QPushButton("-")
self.min_button.clicked.connect(lambda : self.retrieve_request[QWidget].emit(parent))
self.min_button.setMaximumSize(22,22)
self.min_button.setMinimumSize(22,22)
self.min_button.setMaximumSize(22,22)
self.layout_inst.addWidget(self.min_button,stretch=0, alignment=Qt.AlignRight)
self.close_button=QPushButton("x")
self.close_button.clicked.connect(lambda : self.close_request[QWidget].emit(parent))
self.close_button.setMaximumSize(22,22)
self.close_button.setMinimumSize(22,22)
self.close_button.setMaximumSize(22,22)
self.layout_inst.addWidget(self.close_button, stretch=0, alignment=Qt.AlignRight)
pass
@ -91,6 +91,7 @@ class DockPanel(QWidget):
self.can_close = True
DragManager.instance().register_dockpanel(self)
self.destroyed.connect(lambda :DragManager.instance().remove_dockpanel(self))
pass
def reset_parent_res(self, pinst):
@ -109,15 +110,10 @@ class DockPanel(QWidget):
drag_trans.setHotSpot(QPoint(5,5))
drag_trans.exec()
def __del__(self):
DragManager.instance().remove_dockpanel(self)
def sync_status(self):
self.drag_header.setVisible(self.default_header)
def paintEvent(self, a0):
super(DockPanel, self).paintEvent(a0)
print(self.windowTitle() + "::" + str(self.isVisible()))
if __name__ == "__main__":
app=QApplication([])

View File

@ -1,9 +1,19 @@
from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow
from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow, QMessageBox
from PyQt5.QtCore import QObject, QEvent, QRect, QMargins, Qt, QMimeData
from PyQt5.QtGui import QPainter, QColor, QDragEnterEvent, QDropEvent
from enum import Enum
import re
class PlaceArea(Enum):
LeftArea = 0,
RightArea = 1,
TopArea = 2,
BottomArea = 3,
CenterArea = 4,
UndefineArea = 5,
class AcceptPanel(QWidget):
def __init__(self, mgr):
@ -19,11 +29,13 @@ class AcceptPanel(QWidget):
self.mgr_inst = mgr
self.target_anchor :QWidget = None
self.target_area = PlaceArea.UndefineArea
def resizeEvent(self, a0):
total_rect = self.rect()
total_rect = total_rect - QMargins(5, 5, 5, 5)
anchor_width = 30
self.target_area = PlaceArea.UndefineArea
self.left_rect = QRect(int(total_rect.left()), int(total_rect.center().y() - anchor_width / 2), int(anchor_width), int(anchor_width))
self.right_rect = QRect(int(total_rect.right() - anchor_width), int(total_rect.center().y() - anchor_width / 2), int(anchor_width), int(anchor_width))
@ -47,24 +59,29 @@ class AcceptPanel(QWidget):
painter.fillRect(self.right_rect, Qt.green)
painter.fillRect(self.center_rect, Qt.green)
def mouseMoveEvent(self, a0):
def dragMoveEvent(self, a0):
self.hover_rect = self.rect()
print(a0.pos())
if self.left_rect.contains(a0.pos()):
self.hover_rect.setWidth(int(self.hover_rect.width() / 3))
self.target_area = PlaceArea.LeftArea
elif self.right_rect.contains(a0.pos()):
self.target_area = PlaceArea.RightArea
self.hover_rect.setWidth(int(self.hover_rect.width() / 3))
self.hover_rect.moveLeft(int(self.rect().right() - self.hover_rect.width()))
elif self.top_rect.contains(a0.pos()):
self.target_area = PlaceArea.TopArea
self.hover_rect.setHeight(int(self.hover_rect.height() / 3))
elif self.center_rect.contains(a0.pos()):
self.target_area = PlaceArea.CenterArea
pass
elif self.bottom_rect.contains(a0.pos()):
self.target_area = PlaceArea.BottomArea
self.hover_rect.setHeight(int(self.hover_rect.height() / 3))
self.hover_rect.moveTop(int(self.rect().bottom() - self.hover_rect.height()))
else:
self.hover_rect = QRect()
self.target_area = PlaceArea.UndefineArea
self.update()
@ -79,27 +96,84 @@ class AcceptPanel(QWidget):
regex = re.compile("view-drags\\(([^\\(\\)]+)\\)")
result = regex.match(a0.mimeData().text())
if result:
from SplitPanel import SplitPanel, SplitType
from DockPanel import DockPanel
view_id = result.group(1)
adjust_view = self.mgr_inst.get_dockpanel(view_id)
target_view = self.target_anchor
adjust_view: DockPanel = self.mgr_inst.get_dockpanel(view_id)
abandon_frame = adjust_view.parent_res
if abandon_frame is None:
QMessageBox.critical(self, "操作无效", "视图不能与自身进行替换和拼接操作!");
self.setVisible(False)
self.setParent(self.__peak_window(self.target_anchor))
return
remains_attach_frame = abandon_frame.parent_res
target_view: DockPanel = self.target_anchor
if self.target_area == PlaceArea.CenterArea and not target_view.can_replace:
self.setVisible(False)
return
if self.target_area == PlaceArea.UndefineArea:
self.setVisible(False)
return
# 移除源视图
parent_frame_rm = adjust_view.parent_res
self_siblings = parent_frame_rm.child()
if parent_frame_rm.parent_res is None:
main_window:QMainWindow = parent_frame_rm.parent()
self_siblings = abandon_frame.child()
if remains_attach_frame is None:
main_window:QMainWindow = abandon_frame.parent()
views = [self_siblings[0], self_siblings[1]]
views.pop(views.index(adjust_view))
main_window.setCentralWidget(views[0])
views[0].setParent(main_window)
views[0].parent_res = None
else:
pparent_frame = parent_frame_rm.parent_res
if self_siblings[0] == adjust_view:
pparent_frame.replace_view(self_siblings[1], parent_frame_rm)
remains_attach_frame.replace_view(self_siblings[1], abandon_frame)
else:
pparent_frame.replace_view(self_siblings[0], parent_frame_rm)
remains_attach_frame.replace_view(self_siblings[0], abandon_frame)
abandon_frame.setParent(None)
abandon_frame.parent_res = None
del abandon_frame
place_frame = target_view.parent_res
split_group:QWidget = None # 声明类型
if self.target_area == PlaceArea.LeftArea:
split_group = SplitPanel(adjust_view, target_view, SplitType.SPLIT_H)
split_group.set_split_info(SplitType.SPLIT_H, 1/3)
elif self.target_area == PlaceArea.RightArea:
split_group = SplitPanel(target_view, adjust_view, SplitType.SPLIT_H)
split_group.set_split_info(SplitType.SPLIT_H, 2/3)
elif self.target_area == PlaceArea.TopArea:
split_group = SplitPanel(adjust_view, target_view, SplitType.SPLIT_V)
split_group.set_split_info(SplitType.SPLIT_V, 1/3)
elif self.target_area == PlaceArea.BottomArea:
split_group = SplitPanel(target_view, adjust_view, SplitType.SPLIT_V)
split_group.set_split_info(SplitType.SPLIT_V, 2/3)
elif self.target_area == PlaceArea.CenterArea:
split_group = adjust_view
if place_frame is None:
main_window = target_view.parent()
main_window.setCentralWidget(split_group)
split_group.parent_res = None
target_view.setVisible(False)
self.mgr_inst.remove_dockpanel(target_view)
del target_view
else:
place_frame.replace_view(split_group, target_view)
self.setVisible(False)
self.setParent(self.__peak_window(self.target_anchor))
def __peak_window(self, obj: QWidget):
if obj is None:
return None
if obj.__class__.__name__ == "QMainWindow":
return obj
return self.__peak_window(obj.parent())
class DragManager(QObject):

22
README.md Normal file
View File

@ -0,0 +1,22 @@
# QDragsView
## 开发目标
1. 完成一个拖拽式拼接视图类库模拟VS视图的部分功能
2. 使用Python语言完成
## 开发环境
1. PyQt5
2. Python3.12
3. PyCharm
4. Win10
## 图片
![初始界面](full.png)
初始示例界面
![调整后界面](adjust.png)
调整后的界面
![削减视图后界面](reduce.png)
削减视图数量后界面

View File

@ -1,4 +1,4 @@
import Manager
from Manager import DragManager
from DockPanel import DockPanel
from PyQt5.QtWidgets import QApplication, QWidget, QFrame
from enum import Enum
@ -87,10 +87,6 @@ class SplitPanel(QWidget):
self.split_member[1].setVisible(True)
pass
def paintEvent(self, a0):
super(SplitPanel, self).paintEvent(a0)
print(self.split_member[0].windowTitle() + "\\" + self.split_member[1].windowTitle())
def child(self):
return self.split_member[0], self.split_member[1], self.split_info[0]
@ -117,9 +113,12 @@ class SplitPanel(QWidget):
self.split_member = (new, self.split_member[1])
else:
self.split_member = (self.split_member[0], new)
new.parent_res = self
new.setParent(self)
old.setParent(None)
self.split_member[0].setParent(self)
self.split_member[0].parent_res = self
self.split_member[1].setParent(self)
self.split_member[1].parent_res = self
self.sync_status()
self.update()
pass
@ -128,7 +127,7 @@ class SplitPanel(QWidget):
if __name__ == "__main__":
app = QApplication([])
ow = QMainWindow()
app.installEventFilter(Manager.DragManager.instance())
app.installEventFilter(DragManager.instance())
a = DockPanel("docka", None, None)
b = DockPanel("dockb", None, None)

Binary file not shown.

Binary file not shown.

BIN
adjust.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
full.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
reduce.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB