1.UI更新
This commit is contained in:
parent
54fca09914
commit
64c7a30bc2
@ -16,13 +16,336 @@ from PyQt5.QtWidgets import (QApplication, QMainWindow, QMenuBar, QMenu, QAction
|
|||||||
QLabel, QLineEdit, QFormLayout, QDoubleSpinBox, QScrollArea,
|
QLabel, QLineEdit, QFormLayout, QDoubleSpinBox, QScrollArea,
|
||||||
QFileSystemModel, QButtonGroup, QToolButton, QPushButton, QHBoxLayout,
|
QFileSystemModel, QButtonGroup, QToolButton, QPushButton, QHBoxLayout,
|
||||||
QComboBox, QGroupBox, QInputDialog, QFileDialog, QMessageBox, QDesktopWidget, QDialog,
|
QComboBox, QGroupBox, QInputDialog, QFileDialog, QMessageBox, QDesktopWidget, QDialog,
|
||||||
QSpinBox, QFrame, QRadioButton, QTextEdit, QTabWidget)
|
QSpinBox, QFrame, QRadioButton, QTextEdit, QTabWidget, QSizePolicy)
|
||||||
from PyQt5.QtCore import Qt, QDir, QTimer, QSize, QPoint, QUrl, QRect
|
from PyQt5.QtCore import Qt, QDir, QTimer, QSize, QPoint, QUrl, QRect
|
||||||
from direct.showbase.ShowBaseGlobal import aspect2d
|
from direct.showbase.ShowBaseGlobal import aspect2d
|
||||||
from panda3d.core import OrthographicLens
|
from panda3d.core import OrthographicLens
|
||||||
|
|
||||||
from ui.widgets import CustomPanda3DWidget, CustomFileView, CustomTreeWidget,CustomAssetsTreeWidget, CustomConsoleDockWidget
|
from ui.widgets import CustomPanda3DWidget, CustomFileView, CustomTreeWidget,CustomAssetsTreeWidget, CustomConsoleDockWidget
|
||||||
from ui.icon_manager import get_icon_manager, get_icon
|
from ui.icon_manager import get_icon_manager, get_icon
|
||||||
|
|
||||||
|
|
||||||
|
class StyledTerrainDialog(QDialog):
|
||||||
|
"""与新建项目对话框风格一致的参数输入对话框"""
|
||||||
|
|
||||||
|
def __init__(self, parent, title, fields, primary_text="确认", secondary_text="取消"):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWindowTitle(title)
|
||||||
|
self.setObjectName("styledTerrainDialog")
|
||||||
|
self.setModal(True)
|
||||||
|
self.resize(508, 241)
|
||||||
|
self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint)
|
||||||
|
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||||
|
|
||||||
|
self.dragging = False
|
||||||
|
self.drag_position = QPoint()
|
||||||
|
self.icon_manager = get_icon_manager()
|
||||||
|
self._title_icon_size = QSize(18, 18)
|
||||||
|
self._icon_close = self.icon_manager.get_icon('close_icon', self._title_icon_size)
|
||||||
|
self.field_widgets = {}
|
||||||
|
|
||||||
|
self.setStyleSheet("""
|
||||||
|
QDialog#styledTerrainDialog {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
QFrame#baseFrame {
|
||||||
|
background-color: #000000;
|
||||||
|
border: 1px solid #3E3E42;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
QWidget#titleBar {
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 5px 5px 0px 0px;
|
||||||
|
min-height: 32px;
|
||||||
|
max-height: 32px;
|
||||||
|
}
|
||||||
|
QLabel#titleLabel {
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.7px;
|
||||||
|
}
|
||||||
|
QWidget#controlButtons QPushButton {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
color: #EBEBEB;
|
||||||
|
font-size: 14px;
|
||||||
|
min-width: 18px;
|
||||||
|
max-width: 18px;
|
||||||
|
min-height: 18px;
|
||||||
|
max-height: 18px;
|
||||||
|
padding: 0px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
QWidget#controlButtons QPushButton:hover {
|
||||||
|
background-color: #2A2D2E;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
QPushButton#closeButton {
|
||||||
|
border-radius: 0px 5px 0px 0px;
|
||||||
|
}
|
||||||
|
QPushButton#closeButton:hover {
|
||||||
|
background-color: #2A2D2E;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
QWidget#contentWidget {
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 0px 0px 5px 5px;
|
||||||
|
}
|
||||||
|
QFrame#contentContainer {
|
||||||
|
background-color: #19191B;
|
||||||
|
border: 1px solid #2C2F36;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
QLabel[role="fieldLabel"] {
|
||||||
|
color: #EBEBEB;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 0.6px;
|
||||||
|
}
|
||||||
|
QLabel[role="hint"] {
|
||||||
|
color: rgba(235, 235, 235, 0.6);
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.55px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox, QSpinBox {
|
||||||
|
background-color: rgba(89, 100, 113, 0.2);
|
||||||
|
color: #EBEBEB;
|
||||||
|
border: 1px solid rgba(76, 92, 110, 0.6);
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0px 10px;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.55px;
|
||||||
|
min-height: 30px;
|
||||||
|
max-height: 30px;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox:focus, QSpinBox:focus {
|
||||||
|
border: 1px solid #3067C0;
|
||||||
|
background-color: rgba(48, 103, 192, 0.1);
|
||||||
|
}
|
||||||
|
QDoubleSpinBox:hover, QSpinBox:hover {
|
||||||
|
border: 1px solid #3067C0;
|
||||||
|
background-color: rgba(89, 100, 113, 0.3);
|
||||||
|
}
|
||||||
|
QDoubleSpinBox:disabled, QSpinBox:disabled {
|
||||||
|
background-color: rgba(89, 100, 113, 0.1);
|
||||||
|
color: rgba(235, 235, 235, 0.4);
|
||||||
|
border: 1px solid rgba(76, 92, 110, 0.2);
|
||||||
|
}
|
||||||
|
QPushButton {
|
||||||
|
background-color: rgba(89, 98, 118, 0.5);
|
||||||
|
color: #EBEBEB;
|
||||||
|
border: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0px 12px;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
min-width: 90px;
|
||||||
|
min-height: 30px;
|
||||||
|
max-height: 30px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #3067C0;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: #2556A0;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
QPushButton:disabled {
|
||||||
|
background-color: rgba(89, 98, 118, 0.3);
|
||||||
|
color: rgba(235, 235, 235, 0.4);
|
||||||
|
}
|
||||||
|
QPushButton#primaryButton {
|
||||||
|
min-width: 120px;
|
||||||
|
max-width: 120px;
|
||||||
|
}
|
||||||
|
QPushButton#secondaryButton {
|
||||||
|
min-width: 120px;
|
||||||
|
max-width: 120px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
main_layout = QVBoxLayout(self)
|
||||||
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
main_layout.setSpacing(0)
|
||||||
|
|
||||||
|
base_frame = QFrame()
|
||||||
|
base_frame.setObjectName('baseFrame')
|
||||||
|
base_frame.setFrameShape(QFrame.NoFrame)
|
||||||
|
base_frame.setAttribute(Qt.WA_StyledBackground, True)
|
||||||
|
|
||||||
|
base_layout = QVBoxLayout(base_frame)
|
||||||
|
base_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
base_layout.setSpacing(0)
|
||||||
|
|
||||||
|
self.createTitleBar()
|
||||||
|
base_layout.addWidget(self.title_bar)
|
||||||
|
|
||||||
|
content_widget = QWidget()
|
||||||
|
content_widget.setObjectName('contentWidget')
|
||||||
|
content_layout = QVBoxLayout(content_widget)
|
||||||
|
content_layout.setContentsMargins(15, 10, 15, 10)
|
||||||
|
content_layout.setSpacing(0)
|
||||||
|
|
||||||
|
content_container = QFrame()
|
||||||
|
content_container.setObjectName('contentContainer')
|
||||||
|
content_container.setFrameShape(QFrame.NoFrame)
|
||||||
|
content_container.setAttribute(Qt.WA_StyledBackground, True)
|
||||||
|
|
||||||
|
container_layout = QVBoxLayout(content_container)
|
||||||
|
container_layout.setContentsMargins(15, 10, 15, 10)
|
||||||
|
container_layout.setSpacing(10)
|
||||||
|
|
||||||
|
for field in fields:
|
||||||
|
row_widget = QWidget()
|
||||||
|
row_layout = QHBoxLayout(row_widget)
|
||||||
|
row_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
row_layout.setSpacing(10)
|
||||||
|
|
||||||
|
label = QLabel(field.get("label", ""))
|
||||||
|
label.setProperty('role', 'fieldLabel')
|
||||||
|
label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||||
|
label.setMinimumWidth(field.get("label_width", 80))
|
||||||
|
label.setMaximumWidth(field.get("label_width", 120))
|
||||||
|
row_layout.addWidget(label)
|
||||||
|
|
||||||
|
widget_type = field.get("type", "double")
|
||||||
|
if widget_type == "int":
|
||||||
|
widget = QSpinBox()
|
||||||
|
widget.setRange(field.get("min", 0), field.get("max", 1000))
|
||||||
|
widget.setSingleStep(field.get("step", 1))
|
||||||
|
widget.setValue(field.get("value", field.get("default", 0)))
|
||||||
|
else:
|
||||||
|
widget = QDoubleSpinBox()
|
||||||
|
widget.setRange(field.get("min", 0.0), field.get("max", 1000.0))
|
||||||
|
widget.setSingleStep(field.get("step", 0.1))
|
||||||
|
widget.setDecimals(field.get("decimals", 2))
|
||||||
|
widget.setValue(field.get("value", field.get("default", 0.0)))
|
||||||
|
|
||||||
|
widget.setFixedHeight(30)
|
||||||
|
widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||||
|
row_layout.addWidget(widget, 1)
|
||||||
|
|
||||||
|
if field.get("suffix"):
|
||||||
|
suffix_label = QLabel(field["suffix"])
|
||||||
|
suffix_label.setProperty('role', 'fieldLabel')
|
||||||
|
row_layout.addWidget(suffix_label)
|
||||||
|
|
||||||
|
self.field_widgets[field.get("name", field.get("label", ""))] = widget
|
||||||
|
container_layout.addWidget(row_widget)
|
||||||
|
|
||||||
|
separator = QFrame()
|
||||||
|
separator.setFrameShape(QFrame.HLine)
|
||||||
|
separator.setFrameShadow(QFrame.Plain)
|
||||||
|
separator.setFixedHeight(1)
|
||||||
|
separator.setStyleSheet("background-color: #2C2F36; border: none;")
|
||||||
|
container_layout.addWidget(separator)
|
||||||
|
|
||||||
|
button_row_widget = QWidget()
|
||||||
|
button_row_layout = QHBoxLayout(button_row_widget)
|
||||||
|
button_row_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
button_row_layout.setSpacing(10)
|
||||||
|
button_row_layout.addStretch()
|
||||||
|
|
||||||
|
self.confirmButton = QPushButton(primary_text)
|
||||||
|
self.confirmButton.setObjectName('primaryButton')
|
||||||
|
self.confirmButton.setFixedSize(120, 30)
|
||||||
|
self.confirmButton.clicked.connect(self.accept)
|
||||||
|
button_row_layout.addWidget(self.confirmButton)
|
||||||
|
|
||||||
|
self.cancelButton = QPushButton(secondary_text)
|
||||||
|
self.cancelButton.setObjectName('secondaryButton')
|
||||||
|
self.cancelButton.setFixedSize(120, 30)
|
||||||
|
self.cancelButton.clicked.connect(self.reject)
|
||||||
|
button_row_layout.addWidget(self.cancelButton)
|
||||||
|
|
||||||
|
container_layout.addWidget(button_row_widget)
|
||||||
|
|
||||||
|
content_layout.addWidget(content_container, 0, Qt.AlignTop)
|
||||||
|
base_layout.addWidget(content_widget)
|
||||||
|
main_layout.addWidget(base_frame)
|
||||||
|
|
||||||
|
def createTitleBar(self):
|
||||||
|
self.title_bar = QFrame()
|
||||||
|
self.title_bar.setObjectName("titleBar")
|
||||||
|
|
||||||
|
title_layout = QHBoxLayout(self.title_bar)
|
||||||
|
title_layout.setContentsMargins(12, 0, 12, 0)
|
||||||
|
title_layout.setSpacing(0)
|
||||||
|
|
||||||
|
controls = QWidget()
|
||||||
|
controls.setObjectName("controlButtons")
|
||||||
|
controls_layout = QHBoxLayout(controls)
|
||||||
|
controls_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
controls_layout.setSpacing(0)
|
||||||
|
|
||||||
|
self.close_button = QPushButton()
|
||||||
|
self.close_button.setObjectName("closeButton")
|
||||||
|
self.close_button.clicked.connect(self.reject)
|
||||||
|
self.close_button.setFocusPolicy(Qt.NoFocus)
|
||||||
|
controls_layout.addWidget(self.close_button)
|
||||||
|
|
||||||
|
self._applyTitleBarIcons()
|
||||||
|
|
||||||
|
left_placeholder = QWidget()
|
||||||
|
left_placeholder.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
|
||||||
|
title_layout.addWidget(left_placeholder)
|
||||||
|
|
||||||
|
self.title_label = QLabel(self.windowTitle())
|
||||||
|
self.title_label.setObjectName("titleLabel")
|
||||||
|
self.title_label.setAlignment(Qt.AlignCenter)
|
||||||
|
title_layout.addWidget(self.title_label, 1)
|
||||||
|
|
||||||
|
title_layout.addWidget(controls)
|
||||||
|
left_placeholder.setFixedWidth(controls.sizeHint().width())
|
||||||
|
|
||||||
|
def _applyTitleBarIcons(self):
|
||||||
|
if self._icon_close:
|
||||||
|
self.close_button.setIcon(self._icon_close)
|
||||||
|
self.close_button.setIconSize(self._title_icon_size)
|
||||||
|
self.close_button.setText("")
|
||||||
|
self.close_button.setToolTip("关闭")
|
||||||
|
|
||||||
|
def setWindowTitle(self, title):
|
||||||
|
super().setWindowTitle(title)
|
||||||
|
if hasattr(self, "title_label"):
|
||||||
|
self.title_label.setText(title)
|
||||||
|
|
||||||
|
def mousePressEvent(self, event):
|
||||||
|
if event.button() == Qt.LeftButton and hasattr(self, "title_bar"):
|
||||||
|
if self.title_bar.geometry().contains(event.pos()):
|
||||||
|
self.dragging = True
|
||||||
|
self.drag_position = event.globalPos() - self.frameGeometry().topLeft()
|
||||||
|
event.accept()
|
||||||
|
super().mousePressEvent(event)
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, event):
|
||||||
|
if event.buttons() == Qt.LeftButton and self.dragging:
|
||||||
|
self.move(event.globalPos() - self.drag_position)
|
||||||
|
event.accept()
|
||||||
|
super().mouseMoveEvent(event)
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, event):
|
||||||
|
if event.button() == Qt.LeftButton:
|
||||||
|
self.dragging = False
|
||||||
|
super().mouseReleaseEvent(event)
|
||||||
|
|
||||||
|
def get_value(self, name):
|
||||||
|
widget = self.field_widgets.get(name)
|
||||||
|
if isinstance(widget, (QDoubleSpinBox, QSpinBox)):
|
||||||
|
return widget.value()
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
from PyQt5.QtWebEngineWidgets import QWebEngineView
|
from PyQt5.QtWebEngineWidgets import QWebEngineView
|
||||||
WEB_ENGINE_AVAILABLE = True
|
WEB_ENGINE_AVAILABLE = True
|
||||||
@ -4194,170 +4517,108 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
def onCreateFlatTerrain(self):
|
def onCreateFlatTerrain(self):
|
||||||
"""创建平面地形"""
|
"""创建平面地形"""
|
||||||
dialog = QDialog(self)
|
fields = [
|
||||||
dialog.setWindowTitle("创建平面地形")
|
{
|
||||||
dialog.setModal(True)
|
"name": "width",
|
||||||
dialog.resize(300,200)
|
"label": "宽度:",
|
||||||
# 设置对话框样式
|
"type": "double",
|
||||||
dialog.setStyleSheet("""
|
"min": 0.0,
|
||||||
QDialog {
|
"max": 10000.0,
|
||||||
background-color: #252538;
|
"step": 0.1,
|
||||||
color: #e0e0ff;
|
"decimals": 2,
|
||||||
}
|
"value": 0.30,
|
||||||
QLabel {
|
"label_width": 60
|
||||||
color: #e0e0ff;
|
},
|
||||||
font-weight: 500;
|
{
|
||||||
}
|
"name": "height",
|
||||||
QPushButton {
|
"label": "高度:",
|
||||||
background-color: #8b5cf6;
|
"type": "double",
|
||||||
color: white;
|
"min": 0.0,
|
||||||
border: none;
|
"max": 10000.0,
|
||||||
padding: 6px 12px;
|
"step": 0.1,
|
||||||
border-radius: 4px;
|
"decimals": 2,
|
||||||
font-weight: 500;
|
"value": 0.30,
|
||||||
min-width: 80px;
|
"label_width": 60
|
||||||
}
|
},
|
||||||
QPushButton:hover {
|
{
|
||||||
background-color: #7c3aed;
|
"name": "resolution",
|
||||||
}
|
"label": "分辨率:",
|
||||||
QPushButton:pressed {
|
"type": "int",
|
||||||
background-color: #6d28d9;
|
"min": 16,
|
||||||
}
|
"max": 2048,
|
||||||
QPushButton:disabled {
|
"step": 16,
|
||||||
background-color: #4c4c6e;
|
"value": 256,
|
||||||
color: #8888aa;
|
"label_width": 60
|
||||||
}
|
},
|
||||||
QDoubleSpinBox, QSpinBox {
|
]
|
||||||
background-color: #2d2d44;
|
dialog = StyledTerrainDialog(self, "创建平面地形", fields, primary_text="创建", secondary_text="取消")
|
||||||
color: #e0e0ff;
|
|
||||||
border: 1px solid #3a3a4a;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
|
|
||||||
layout = QVBoxLayout(dialog)
|
|
||||||
|
|
||||||
width_layout = QHBoxLayout()
|
|
||||||
width_layout.addWidget(QLabel("宽度:"))
|
|
||||||
width_spin = QDoubleSpinBox()
|
|
||||||
width_spin.setRange(0,10000)
|
|
||||||
width_spin.setValue(0.3)
|
|
||||||
width_layout.addWidget(width_spin)
|
|
||||||
layout.addLayout(width_layout)
|
|
||||||
|
|
||||||
# 高度
|
|
||||||
height_layout = QHBoxLayout()
|
|
||||||
height_layout.addWidget(QLabel("高度:"))
|
|
||||||
height_spin = QDoubleSpinBox()
|
|
||||||
height_spin.setRange(0, 10000)
|
|
||||||
height_spin.setValue(0.3)
|
|
||||||
height_layout.addWidget(height_spin)
|
|
||||||
layout.addLayout(height_layout)
|
|
||||||
|
|
||||||
# 分辨率
|
|
||||||
resolution_layout = QHBoxLayout()
|
|
||||||
resolution_layout.addWidget(QLabel("分辨率:"))
|
|
||||||
resolution_spin = QSpinBox()
|
|
||||||
resolution_spin.setRange(16, 2048)
|
|
||||||
resolution_spin.setValue(256)
|
|
||||||
resolution_spin.setSingleStep(16)
|
|
||||||
resolution_layout.addWidget(resolution_spin)
|
|
||||||
layout.addLayout(resolution_layout)
|
|
||||||
|
|
||||||
# 按钮
|
|
||||||
button_layout = QHBoxLayout()
|
|
||||||
ok_button = QPushButton("创建")
|
|
||||||
cancel_button = QPushButton("取消")
|
|
||||||
button_layout.addWidget(ok_button)
|
|
||||||
button_layout.addWidget(cancel_button)
|
|
||||||
layout.addLayout(button_layout)
|
|
||||||
|
|
||||||
# 连接信号
|
|
||||||
ok_button.clicked.connect(dialog.accept)
|
|
||||||
cancel_button.clicked.connect(dialog.reject)
|
|
||||||
|
|
||||||
# 显示对话框
|
|
||||||
if dialog.exec_() == QDialog.Accepted:
|
if dialog.exec_() == QDialog.Accepted:
|
||||||
width = width_spin.value()
|
width = dialog.get_value("width")
|
||||||
height = height_spin.value()
|
height = dialog.get_value("height")
|
||||||
resolution = resolution_spin.value()
|
resolution = int(dialog.get_value("resolution"))
|
||||||
|
|
||||||
# 调用世界对象创建地形
|
|
||||||
terrain_info = self.world.createFlatTerrain((width, height), resolution)
|
terrain_info = self.world.createFlatTerrain((width, height), resolution)
|
||||||
if terrain_info:
|
if terrain_info:
|
||||||
QMessageBox.information(self, "成功", "平面地形创建成功!")
|
QMessageBox.information(self, "成功", "平面地形创建成功!")
|
||||||
else:
|
else:
|
||||||
QMessageBox.warning(self, "错误", "平面地形创建失败!")
|
QMessageBox.warning(self, "警告", "平面地形创建失败!")
|
||||||
|
|
||||||
def onCreateHeightmapTerrain(self):
|
def onCreateHeightmapTerrain(self):
|
||||||
"""从高度图创建地形"""
|
"""从高度图创建地形"""
|
||||||
dialog = self.createStyledFileDialog(
|
file_dialog = self.createStyledFileDialog(
|
||||||
self,
|
self,
|
||||||
"选择高度图文件",
|
"选择高度图文件",
|
||||||
"",
|
"",
|
||||||
"图像文件 (*.png *.jpg *.jpeg *.bmp *.tga);;所有文件 (*)"
|
"图像文件 (*.png *.jpg *.jpeg *.bmp *.tga);;所有文件 (*)"
|
||||||
)
|
)
|
||||||
|
|
||||||
if dialog.exec_() == QDialog.Accepted:
|
if file_dialog.exec_() == QDialog.Accepted:
|
||||||
file_path = dialog.selectedFiles()[0]
|
file_path = file_dialog.selectedFiles()[0]
|
||||||
if file_path:
|
if file_path:
|
||||||
#创建对话框获取地形参数
|
fields = [
|
||||||
dialog = QDialog(self)
|
{
|
||||||
dialog.setWindowTitle("设置地形参数")
|
"name": "x_scale",
|
||||||
dialog.setModal(True)
|
"label": "X缩放:",
|
||||||
dialog.resize(300,250)
|
"type": "double",
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 1000.0,
|
||||||
|
"step": 0.1,
|
||||||
|
"decimals": 2,
|
||||||
|
"value": 0.30,
|
||||||
|
"label_width": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "y_scale",
|
||||||
|
"label": "Y缩放:",
|
||||||
|
"type": "double",
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 1000.0,
|
||||||
|
"step": 0.1,
|
||||||
|
"decimals": 2,
|
||||||
|
"value": 0.30,
|
||||||
|
"label_width": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "z_scale",
|
||||||
|
"label": "Z缩放:",
|
||||||
|
"type": "double",
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 1000.0,
|
||||||
|
"step": 1.0,
|
||||||
|
"decimals": 2,
|
||||||
|
"value": 50.0,
|
||||||
|
"label_width": 70
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
layout = QVBoxLayout(dialog)
|
params_dialog = StyledTerrainDialog(self, "设置地形参数", fields, primary_text="创建", secondary_text="取消")
|
||||||
|
|
||||||
x_scale_layout = QHBoxLayout()
|
if params_dialog.exec_() == QDialog.Accepted:
|
||||||
x_scale_layout.addWidget(QLabel("X缩放:"))
|
x_scale = params_dialog.get_value("x_scale")
|
||||||
x_scale_spin = QDoubleSpinBox()
|
y_scale = params_dialog.get_value("y_scale")
|
||||||
x_scale_spin.setRange(0.1,1000)
|
z_scale = params_dialog.get_value("z_scale")
|
||||||
x_scale_spin.setValue(0.3)
|
|
||||||
x_scale_spin.setSingleStep(10)
|
|
||||||
x_scale_layout.addWidget(x_scale_spin)
|
|
||||||
layout.addLayout(x_scale_layout)
|
|
||||||
|
|
||||||
# Y缩放
|
|
||||||
y_scale_layout = QHBoxLayout()
|
|
||||||
y_scale_layout.addWidget(QLabel("Y缩放:"))
|
|
||||||
y_scale_spin = QDoubleSpinBox()
|
|
||||||
y_scale_spin.setRange(0.1, 1000)
|
|
||||||
y_scale_spin.setValue(0.3)
|
|
||||||
y_scale_spin.setSingleStep(10)
|
|
||||||
y_scale_layout.addWidget(y_scale_spin)
|
|
||||||
layout.addLayout(y_scale_layout)
|
|
||||||
|
|
||||||
# Z缩放
|
|
||||||
z_scale_layout = QHBoxLayout()
|
|
||||||
z_scale_layout.addWidget(QLabel("Z缩放:"))
|
|
||||||
z_scale_spin = QDoubleSpinBox()
|
|
||||||
z_scale_spin.setRange(0.1, 1000)
|
|
||||||
z_scale_spin.setValue(50)
|
|
||||||
z_scale_spin.setSingleStep(5)
|
|
||||||
z_scale_layout.addWidget(z_scale_spin)
|
|
||||||
layout.addLayout(z_scale_layout)
|
|
||||||
|
|
||||||
# 按钮
|
|
||||||
button_layout = QHBoxLayout()
|
|
||||||
ok_button = QPushButton("创建")
|
|
||||||
cancel_button = QPushButton("取消")
|
|
||||||
button_layout.addWidget(ok_button)
|
|
||||||
button_layout.addWidget(cancel_button)
|
|
||||||
layout.addLayout(button_layout)
|
|
||||||
|
|
||||||
# 连接信号
|
|
||||||
ok_button.clicked.connect(dialog.accept)
|
|
||||||
cancel_button.clicked.connect(dialog.reject)
|
|
||||||
|
|
||||||
# 显示对话框
|
|
||||||
if dialog.exec_() == QDialog.Accepted:
|
|
||||||
x_scale = x_scale_spin.value()
|
|
||||||
y_scale = y_scale_spin.value()
|
|
||||||
z_scale = z_scale_spin.value()
|
|
||||||
|
|
||||||
# 调用世界对象创建地形
|
|
||||||
terrain_info = self.world.createTerrainFromHeightMap(
|
terrain_info = self.world.createTerrainFromHeightMap(
|
||||||
file_path,
|
file_path,
|
||||||
(x_scale, y_scale, z_scale)
|
(x_scale, y_scale, z_scale)
|
||||||
@ -4365,7 +4626,7 @@ class MainWindow(QMainWindow):
|
|||||||
if terrain_info:
|
if terrain_info:
|
||||||
QMessageBox.information(self, "成功", "高度图地形创建成功!")
|
QMessageBox.information(self, "成功", "高度图地形创建成功!")
|
||||||
else:
|
else:
|
||||||
QMessageBox.warning(self, "错误", "高度图地形创建失败!")
|
QMessageBox.warning(self, "警告", "高度图地形创建失败!")
|
||||||
|
|
||||||
def onOpenAssemblyDisassemblyConfig(self):
|
def onOpenAssemblyDisassemblyConfig(self):
|
||||||
"""打开拆装配置界面"""
|
"""打开拆装配置界面"""
|
||||||
|
|||||||
333
ui/widgets.py
333
ui/widgets.py
@ -60,10 +60,15 @@ class NewProjectDialog(QDialog):
|
|||||||
}
|
}
|
||||||
QWidget#titleBar {
|
QWidget#titleBar {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
border-radius: 5px 5px 0px 0px;
|
border-radius: 5px 5px 0px 0px;
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
max-height: 32px;
|
max-height: 32px;
|
||||||
}
|
}
|
||||||
|
QWidget#titleBar QWidget {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
QLabel#titleLabel {
|
QLabel#titleLabel {
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
@ -231,7 +236,7 @@ class NewProjectDialog(QDialog):
|
|||||||
content_widget = QWidget()
|
content_widget = QWidget()
|
||||||
content_widget.setObjectName('contentWidget')
|
content_widget.setObjectName('contentWidget')
|
||||||
content_layout = QVBoxLayout(content_widget)
|
content_layout = QVBoxLayout(content_widget)
|
||||||
content_layout.setContentsMargins(15, 10, 15, 10)
|
content_layout.setContentsMargins(10, 10, 10, 10)
|
||||||
content_layout.setSpacing(0)
|
content_layout.setSpacing(0)
|
||||||
|
|
||||||
content_container = QFrame()
|
content_container = QFrame()
|
||||||
@ -769,37 +774,49 @@ class CustomAssetsTreeWidget(QTreeWidget):
|
|||||||
self._restoreExpandedState(expanded_paths)
|
self._restoreExpandedState(expanded_paths)
|
||||||
|
|
||||||
def createNewFolder(self, parent_item):
|
def createNewFolder(self, parent_item):
|
||||||
"""创建新文件夹"""
|
"""新建文件夹"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
parent_path = parent_item.data(0, Qt.UserRole)
|
parent_path = parent_item.data(0, Qt.UserRole)
|
||||||
folder_name, ok = StyledMessageBox.getText(self, "新建文件夹", "文件夹名称:")
|
dialog = StyledTextInputDialog(self, "新建文件夹", "文件夹名称", "请输入文件夹名称")
|
||||||
|
if dialog.exec_() != QDialog.Accepted:
|
||||||
|
return
|
||||||
|
|
||||||
|
folder_name = dialog.text()
|
||||||
|
if not folder_name:
|
||||||
|
return
|
||||||
|
|
||||||
if ok and folder_name:
|
|
||||||
new_folder_path = os.path.join(parent_path, folder_name)
|
new_folder_path = os.path.join(parent_path, folder_name)
|
||||||
try:
|
try:
|
||||||
os.makedirs(new_folder_path, exist_ok=True)
|
os.makedirs(new_folder_path, exist_ok=True)
|
||||||
self._refreshWithStatePreservation()
|
self._refreshWithStatePreservation()
|
||||||
print(f"创建文件夹: {new_folder_path}")
|
print(f"新建文件夹: {new_folder_path}")
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print(f"创建文件夹失败: {e}")
|
print(f"新建文件夹失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
def createNewFile(self, parent_item):
|
def createNewFile(self, parent_item):
|
||||||
"""创建新文件"""
|
"""新建文件"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
parent_path = parent_item.data(0, Qt.UserRole)
|
parent_path = parent_item.data(0, Qt.UserRole)
|
||||||
file_name, ok = StyledMessageBox.getText(self, "新建文件", "文件名称:")
|
dialog = StyledTextInputDialog(self, "新建文件", "文件名称", "请输入文件名称")
|
||||||
|
if dialog.exec_() != QDialog.Accepted:
|
||||||
|
return
|
||||||
|
|
||||||
|
file_name = dialog.text()
|
||||||
|
if not file_name:
|
||||||
|
return
|
||||||
|
|
||||||
if ok and file_name:
|
|
||||||
new_file_path = os.path.join(parent_path, file_name)
|
new_file_path = os.path.join(parent_path, file_name)
|
||||||
try:
|
try:
|
||||||
with open(new_file_path, 'w', encoding='utf-8') as f:
|
with open(new_file_path, "w", encoding="utf-8") as f:
|
||||||
f.write("")
|
f.write("")
|
||||||
self._refreshWithStatePreservation()
|
self._refreshWithStatePreservation()
|
||||||
print(f"创建文件: {new_file_path}")
|
print(f"新建文件: {new_file_path}")
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print(f"创建文件失败: {e}")
|
print(f"新建文件失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
def renameItem(self, item):
|
def renameItem(self, item):
|
||||||
"""重命名文件或文件夹"""
|
"""重命名文件或文件夹"""
|
||||||
@ -808,19 +825,26 @@ class CustomAssetsTreeWidget(QTreeWidget):
|
|||||||
old_path = item.data(0, Qt.UserRole)
|
old_path = item.data(0, Qt.UserRole)
|
||||||
old_name = os.path.basename(old_path)
|
old_name = os.path.basename(old_path)
|
||||||
|
|
||||||
new_name, ok = StyledMessageBox.getText(self, "重命名", "新名称:", text=old_name)
|
dialog = StyledTextInputDialog(self, "重命名", "新名称", "请输入新名称", old_name)
|
||||||
|
if dialog.exec_() != QDialog.Accepted:
|
||||||
|
return
|
||||||
|
|
||||||
|
new_name = dialog.text()
|
||||||
|
if not new_name or new_name == old_name:
|
||||||
|
return
|
||||||
|
|
||||||
if ok and new_name and new_name != old_name:
|
|
||||||
parent_dir = os.path.dirname(old_path)
|
parent_dir = os.path.dirname(old_path)
|
||||||
new_path = os.path.join(parent_dir, new_name)
|
new_path = os.path.join(parent_dir, new_name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.rename(old_path, new_path)
|
os.rename(old_path, new_path)
|
||||||
|
item.setText(0, new_name)
|
||||||
|
item.setData(0, Qt.UserRole, new_path)
|
||||||
self._refreshWithStatePreservation()
|
self._refreshWithStatePreservation()
|
||||||
print(f"重命名: {old_path} -> {new_path}")
|
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print(f"重命名失败: {e}")
|
print(f"重命名失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
def deleteItem(self, item):
|
def deleteItem(self, item):
|
||||||
"""删除文件或文件夹"""
|
"""删除文件或文件夹"""
|
||||||
import os
|
import os
|
||||||
@ -2081,6 +2105,285 @@ class StyledMessageBox:
|
|||||||
ok = dialog.exec_()
|
ok = dialog.exec_()
|
||||||
return dialog.textValue(), ok
|
return dialog.textValue(), ok
|
||||||
|
|
||||||
|
class StyledTextInputDialog(QDialog):
|
||||||
|
"""与新建项目样式一致的文本输入对话框"""
|
||||||
|
|
||||||
|
def __init__(self, parent, title, label_text="", placeholder="", default_text=""):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWindowTitle(title)
|
||||||
|
self.setObjectName("styledTextInputDialog")
|
||||||
|
self.setModal(True)
|
||||||
|
self.resize(420, 186)
|
||||||
|
self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint)
|
||||||
|
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||||
|
|
||||||
|
self.dragging = False
|
||||||
|
self.drag_position = QPoint()
|
||||||
|
self.icon_manager = get_icon_manager()
|
||||||
|
self._title_icon_size = QSize(18, 18)
|
||||||
|
self._icon_close = self.icon_manager.get_icon('close_icon', self._title_icon_size)
|
||||||
|
|
||||||
|
self.setStyleSheet("""
|
||||||
|
QDialog#styledTextInputDialog {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
QFrame#baseFrame {
|
||||||
|
background-color: #000000;
|
||||||
|
border: 1px solid #3E3E42;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
QWidget#titleBar {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px 5px 0px 0px;
|
||||||
|
min-height: 32px;
|
||||||
|
max-height: 32px;
|
||||||
|
}
|
||||||
|
QWidget#titleBar QWidget {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
QLabel#titleLabel {
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.7px;
|
||||||
|
}
|
||||||
|
QWidget#controlButtons QPushButton {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
color: #EBEBEB;
|
||||||
|
font-size: 14px;
|
||||||
|
min-width: 18px;
|
||||||
|
max-width: 18px;
|
||||||
|
min-height: 18px;
|
||||||
|
max-height: 18px;
|
||||||
|
padding: 0px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
QWidget#controlButtons QPushButton:hover {
|
||||||
|
background-color: #2A2D2E;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
QPushButton#closeButton {
|
||||||
|
border-radius: 0px 5px 0px 0px;
|
||||||
|
}
|
||||||
|
QPushButton#closeButton:hover {
|
||||||
|
background-color: #2A2D2E;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
QWidget#contentWidget {
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 0px 0px 5px 5px;
|
||||||
|
}
|
||||||
|
QFrame#contentContainer {
|
||||||
|
background-color: #19191B;
|
||||||
|
border: 1px solid #2C2F36;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
QLabel[role="fieldLabel"] {
|
||||||
|
color: #EBEBEB;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 0.6px;
|
||||||
|
}
|
||||||
|
QLineEdit {
|
||||||
|
background-color: rgba(89, 100, 113, 0.2);
|
||||||
|
color: #EBEBEB;
|
||||||
|
border: 1px solid rgba(76, 92, 110, 0.6);
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0px 10px;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.55px;
|
||||||
|
min-height: 30px;
|
||||||
|
max-height: 30px;
|
||||||
|
}
|
||||||
|
QLineEdit:focus {
|
||||||
|
border: 1px solid #3067C0;
|
||||||
|
background-color: rgba(48, 103, 192, 0.1);
|
||||||
|
}
|
||||||
|
QLineEdit:hover {
|
||||||
|
border: 1px solid #3067C0;
|
||||||
|
background-color: rgba(89, 100, 113, 0.3);
|
||||||
|
}
|
||||||
|
QPushButton {
|
||||||
|
background-color: rgba(89, 98, 118, 0.5);
|
||||||
|
color: #EBEBEB;
|
||||||
|
border: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0px 12px;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
min-width: 120px;
|
||||||
|
min-height: 30px;
|
||||||
|
max-height: 30px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #3067C0;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: #2556A0;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
main_layout = QVBoxLayout(self)
|
||||||
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
main_layout.setSpacing(0)
|
||||||
|
|
||||||
|
base_frame = QFrame()
|
||||||
|
base_frame.setObjectName('baseFrame')
|
||||||
|
base_frame.setFrameShape(QFrame.NoFrame)
|
||||||
|
base_frame.setAttribute(Qt.WA_StyledBackground, True)
|
||||||
|
|
||||||
|
base_layout = QVBoxLayout(base_frame)
|
||||||
|
base_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
base_layout.setSpacing(0)
|
||||||
|
|
||||||
|
self._createTitleBar()
|
||||||
|
base_layout.addWidget(self.title_bar)
|
||||||
|
base_layout.addSpacing(10)
|
||||||
|
|
||||||
|
content_widget = QWidget()
|
||||||
|
content_widget.setObjectName('contentWidget')
|
||||||
|
content_layout = QVBoxLayout(content_widget)
|
||||||
|
content_layout.setContentsMargins(10, 0, 10, 10)
|
||||||
|
content_layout.setSpacing(0)
|
||||||
|
|
||||||
|
content_container = QFrame()
|
||||||
|
content_container.setObjectName('contentContainer')
|
||||||
|
content_container.setFrameShape(QFrame.NoFrame)
|
||||||
|
content_container.setAttribute(Qt.WA_StyledBackground, True)
|
||||||
|
content_container.setFixedWidth(400)
|
||||||
|
|
||||||
|
container_layout = QVBoxLayout(content_container)
|
||||||
|
container_layout.setContentsMargins(15, 10, 15, 10)
|
||||||
|
container_layout.setSpacing(10)
|
||||||
|
|
||||||
|
if label_text:
|
||||||
|
label = QLabel(label_text)
|
||||||
|
label.setProperty('role', 'fieldLabel')
|
||||||
|
container_layout.addWidget(label)
|
||||||
|
|
||||||
|
self.line_edit = QLineEdit()
|
||||||
|
self.line_edit.setPlaceholderText(placeholder)
|
||||||
|
self.line_edit.setText(default_text)
|
||||||
|
container_layout.addWidget(self.line_edit)
|
||||||
|
|
||||||
|
separator = QFrame()
|
||||||
|
separator.setFrameShape(QFrame.HLine)
|
||||||
|
separator.setFrameShadow(QFrame.Plain)
|
||||||
|
separator.setFixedHeight(1)
|
||||||
|
separator.setStyleSheet("background-color: #2C2F36; border: none;")
|
||||||
|
container_layout.addWidget(separator)
|
||||||
|
|
||||||
|
button_row = QHBoxLayout()
|
||||||
|
button_row.setContentsMargins(0, 0, 0, 0)
|
||||||
|
button_row.setSpacing(10)
|
||||||
|
button_row.addStretch()
|
||||||
|
|
||||||
|
self.confirmButton = QPushButton("确认")
|
||||||
|
self.confirmButton.setObjectName("primaryButton")
|
||||||
|
self.confirmButton.clicked.connect(self._onAccept)
|
||||||
|
button_row.addWidget(self.confirmButton)
|
||||||
|
|
||||||
|
self.cancelButton = QPushButton("取消")
|
||||||
|
self.cancelButton.setObjectName("secondaryButton")
|
||||||
|
self.cancelButton.clicked.connect(self.reject)
|
||||||
|
button_row.addWidget(self.cancelButton)
|
||||||
|
|
||||||
|
container_layout.addLayout(button_row)
|
||||||
|
|
||||||
|
content_layout.addWidget(content_container, 0, Qt.AlignTop)
|
||||||
|
base_layout.addWidget(content_widget)
|
||||||
|
main_layout.addWidget(base_frame)
|
||||||
|
|
||||||
|
self.confirmButton.setDefault(True)
|
||||||
|
self.confirmButton.setAutoDefault(True)
|
||||||
|
self.line_edit.selectAll()
|
||||||
|
self.line_edit.setFocus()
|
||||||
|
|
||||||
|
def _createTitleBar(self):
|
||||||
|
self.title_bar = QFrame()
|
||||||
|
self.title_bar.setObjectName("titleBar")
|
||||||
|
|
||||||
|
title_layout = QHBoxLayout(self.title_bar)
|
||||||
|
title_layout.setContentsMargins(12, 6, 12, 6)
|
||||||
|
title_layout.setSpacing(0)
|
||||||
|
|
||||||
|
controls = QWidget()
|
||||||
|
controls.setObjectName("controlButtons")
|
||||||
|
controls_layout = QHBoxLayout(controls)
|
||||||
|
controls_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
controls_layout.setSpacing(0)
|
||||||
|
|
||||||
|
self.close_button = QPushButton()
|
||||||
|
self.close_button.setObjectName("closeButton")
|
||||||
|
self.close_button.clicked.connect(self.reject)
|
||||||
|
self.close_button.setFocusPolicy(Qt.NoFocus)
|
||||||
|
self.close_button.setFixedSize(18, 18)
|
||||||
|
controls_layout.addWidget(self.close_button)
|
||||||
|
|
||||||
|
self._applyTitleBarIcons()
|
||||||
|
|
||||||
|
left_placeholder = QWidget()
|
||||||
|
left_placeholder.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
|
||||||
|
title_layout.addWidget(left_placeholder)
|
||||||
|
|
||||||
|
self.title_label = QLabel(self.windowTitle())
|
||||||
|
self.title_label.setObjectName("titleLabel")
|
||||||
|
self.title_label.setAlignment(Qt.AlignCenter)
|
||||||
|
title_layout.addWidget(self.title_label, 1)
|
||||||
|
|
||||||
|
title_layout.addWidget(controls)
|
||||||
|
left_placeholder.setFixedWidth(controls.sizeHint().width())
|
||||||
|
|
||||||
|
def _applyTitleBarIcons(self):
|
||||||
|
if self._icon_close:
|
||||||
|
self.close_button.setIcon(self._icon_close)
|
||||||
|
self.close_button.setIconSize(self._title_icon_size)
|
||||||
|
self.close_button.setText("")
|
||||||
|
self.close_button.setToolTip("关闭")
|
||||||
|
|
||||||
|
def setWindowTitle(self, title):
|
||||||
|
super().setWindowTitle(title)
|
||||||
|
if hasattr(self, "title_label"):
|
||||||
|
self.title_label.setText(title)
|
||||||
|
|
||||||
|
def _onAccept(self):
|
||||||
|
if self.line_edit.text().strip():
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
def text(self):
|
||||||
|
return self.line_edit.text().strip()
|
||||||
|
|
||||||
|
def mousePressEvent(self, event):
|
||||||
|
if event.button() == Qt.LeftButton and self.title_bar.geometry().contains(event.pos()):
|
||||||
|
self.dragging = True
|
||||||
|
self.drag_position = event.globalPos() - self.frameGeometry().topLeft()
|
||||||
|
event.accept()
|
||||||
|
super().mousePressEvent(event)
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, event):
|
||||||
|
if event.buttons() == Qt.LeftButton and self.dragging:
|
||||||
|
self.move(event.globalPos() - self.drag_position)
|
||||||
|
event.accept()
|
||||||
|
super().mouseMoveEvent(event)
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, event):
|
||||||
|
if event.button() == Qt.LeftButton:
|
||||||
|
self.dragging = False
|
||||||
|
super().mouseReleaseEvent(event)
|
||||||
|
|
||||||
|
|
||||||
class CustomTreeWidget(QTreeWidget):
|
class CustomTreeWidget(QTreeWidget):
|
||||||
"""自定义场景树部件"""
|
"""自定义场景树部件"""
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user