1.UI风格修改
This commit is contained in:
parent
c7a4ce7963
commit
ae4fbb8b70
@ -52,6 +52,18 @@ class IconManager:
|
|||||||
'warning': 'warning.png',
|
'warning': 'warning.png',
|
||||||
'error': 'error.png',
|
'error': 'error.png',
|
||||||
'info': 'info.png',
|
'info': 'info.png',
|
||||||
|
|
||||||
|
'up_arrow': 'up_arrows.png',
|
||||||
|
'down_arrow': 'down_arrows.png',
|
||||||
|
'left_arrow': 'left_arrows.png',
|
||||||
|
'right_arrow': 'right_arrows.png',
|
||||||
|
|
||||||
|
'solid_down_arrows': 'solid_down_arrows.png',
|
||||||
|
'solid_right_arrows': 'solid_right_arrows.png',
|
||||||
|
|
||||||
|
'minimize_icon': 'minimize_icon.png',
|
||||||
|
'windowing_icon': 'windowing_icon.png',
|
||||||
|
'close_icon': 'close_icon.png',
|
||||||
}
|
}
|
||||||
|
|
||||||
# 初始化默认图标
|
# 初始化默认图标
|
||||||
|
|||||||
1177
ui/main_window.py
1177
ui/main_window.py
File diff suppressed because it is too large
Load Diff
@ -42,24 +42,464 @@ class PropertyPanelManager:
|
|||||||
# 初始化碰撞参数加载标志位
|
# 初始化碰撞参数加载标志位
|
||||||
self._loading_collision_params = False
|
self._loading_collision_params = False
|
||||||
|
|
||||||
# 定义紧凑样式
|
# 定义现代化紧凑样式
|
||||||
self.compact_style = """
|
self.compact_style = """
|
||||||
QDoubleSpinBox {
|
QDoubleSpinBox, QSpinBox {
|
||||||
min-width: 45px;
|
min-width: 60px;
|
||||||
|
background-color: rgba(89, 100, 113, 0.15);
|
||||||
|
border: 1px solid rgba(76, 92, 110, 0.4);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 6px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox:focus, QSpinBox:focus {
|
||||||
|
border: 1px solid #4d74bd;
|
||||||
|
background-color: rgba(77, 116, 189, 0.1);
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::up-button, QSpinBox::up-button {
|
||||||
|
background-color: rgba(77, 116, 189, 0.2);
|
||||||
|
border: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
width: 14px;
|
||||||
|
subcontrol-origin: border;
|
||||||
|
subcontrol-position: top right;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::down-button, QSpinBox::down-button {
|
||||||
|
background-color: rgba(77, 116, 189, 0.2);
|
||||||
|
border: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
width: 14px;
|
||||||
|
subcontrol-origin: border;
|
||||||
|
subcontrol-position: bottom right;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::up-button:hover, QSpinBox::up-button:hover,
|
||||||
|
QDoubleSpinBox::down-button:hover, QSpinBox::down-button:hover {
|
||||||
|
background-color: rgba(77, 116, 189, 0.4);
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::up-arrow, QSpinBox::up-arrow {
|
||||||
|
image: url(icons/up_arrows.png);
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::down-arrow, QSpinBox::down-arrow {
|
||||||
|
image: url(icons/down_arrows.png);
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::up-arrow:hover, QSpinBox::up-arrow:hover {
|
||||||
|
image: url(icons/up_arrows.png);
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::down-arrow:hover, QSpinBox::down-arrow:hover {
|
||||||
|
image: url(icons/down_arrows.png);
|
||||||
}
|
}
|
||||||
QPushButton {
|
QPushButton {
|
||||||
min-width: 10px;
|
min-width: 60px;
|
||||||
|
background-color: rgba(89, 100, 113, 0.4);
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
border: 1px solid rgba(76, 92, 110, 0.4);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: rgba(89, 100, 113, 0.6);
|
||||||
|
border: 1px solid rgba(77, 116, 189, 0.6);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
QPushButton:pressed, QPushButton:checked {
|
||||||
|
background-color: rgba(77, 116, 189, 0.8);
|
||||||
|
border: 1px solid #4d74bd;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
QPushButton:disabled {
|
||||||
|
background-color: rgba(89, 100, 113, 0.2);
|
||||||
|
color: rgba(235, 235, 235, 0.4);
|
||||||
|
border: 1px solid rgba(76, 92, 110, 0.2);
|
||||||
}
|
}
|
||||||
QComboBox {
|
QComboBox {
|
||||||
min-width: 60px;
|
min-width: 80px;
|
||||||
|
background-color: rgba(89, 100, 113, 0.15);
|
||||||
|
border: 1px solid rgba(76, 92, 110, 0.4);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 6px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
QComboBox:focus {
|
||||||
|
border: 1px solid #4d74bd;
|
||||||
|
}
|
||||||
|
QComboBox::drop-down {
|
||||||
|
border: none;
|
||||||
|
border-left: 1px solid rgba(76, 92, 110, 0.4);
|
||||||
|
background-color: rgba(77, 116, 189, 0.2);
|
||||||
|
border-radius: 0 4px 4px 0;
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
|
QComboBox::drop-down:hover {
|
||||||
|
background-color: rgba(77, 116, 189, 0.4);
|
||||||
|
}
|
||||||
|
QComboBox::down-arrow {
|
||||||
|
image: url(icons/down_arrows.png);
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
}
|
}
|
||||||
QLineEdit {
|
QLineEdit {
|
||||||
min-width: 60px;
|
min-width: 80px;
|
||||||
|
background-color: rgba(89, 100, 113, 0.15);
|
||||||
|
border: 1px solid rgba(76, 92, 110, 0.4);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 6px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
QLineEdit:focus {
|
||||||
|
border: 1px solid #4d74bd;
|
||||||
|
background-color: rgba(77, 116, 189, 0.1);
|
||||||
}
|
}
|
||||||
QCheckBox {
|
QCheckBox {
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
|
font-size: 10px;
|
||||||
|
spacing: 6px;
|
||||||
|
}
|
||||||
|
QCheckBox::indicator {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border: 1px solid rgba(76, 92, 110, 0.6);
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: rgba(89, 100, 113, 0.15);
|
||||||
|
}
|
||||||
|
QCheckBox::indicator:checked {
|
||||||
|
background-color: #4d74bd;
|
||||||
|
border: 1px solid #4d74bd;
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
self.compact_style += """
|
||||||
|
QGroupBox {
|
||||||
|
margin-left: 8px;
|
||||||
|
padding-left: 0px;
|
||||||
|
}
|
||||||
|
QGroupBox::title {
|
||||||
|
left: 0px;
|
||||||
|
padding: 0 5px 5px 0;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 定义现代化状态徽章样式
|
||||||
|
self.badge_style_blue = """
|
||||||
|
QLabel {
|
||||||
|
background-color: rgba(77, 116, 189, 0.15);
|
||||||
|
border: 1px solid rgba(77, 116, 189, 0.6);
|
||||||
|
color: #4d74bd;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
font-family: 'Microsoft YaHei', 'Inter', sans-serif;
|
||||||
|
font-size: 9px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.badge_style_green = """
|
||||||
|
QLabel {
|
||||||
|
background-color: rgba(45, 255, 196, 0.15);
|
||||||
|
border: 1px solid rgba(45, 255, 196, 0.6);
|
||||||
|
color: #2dffc4;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
font-family: 'Microsoft YaHei', 'Inter', sans-serif;
|
||||||
|
font-size: 9px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 添加新的徽章样式
|
||||||
|
self.badge_style_orange = """
|
||||||
|
QLabel {
|
||||||
|
background-color: rgba(255, 165, 0, 0.15);
|
||||||
|
border: 1px solid rgba(255, 165, 0, 0.6);
|
||||||
|
color: #ffa500;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
font-family: 'Microsoft YaHei', 'Inter', sans-serif;
|
||||||
|
font-size: 9px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.badge_style_red = """
|
||||||
|
QLabel {
|
||||||
|
background-color: rgba(255, 99, 99, 0.15);
|
||||||
|
border: 1px solid rgba(255, 99, 99, 0.6);
|
||||||
|
color: #ff6363;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
font-family: 'Microsoft YaHei', 'Inter', sans-serif;
|
||||||
|
font-size: 9px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def createStatusBadge(self, text, badge_type="green"):
|
||||||
|
"""创建现代化状态徽章
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text: 徽章文字
|
||||||
|
badge_type: 徽章类型,支持 "green", "blue", "orange", "red"
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
QLabel: 配置好样式的标签
|
||||||
|
"""
|
||||||
|
badge = QLabel(text)
|
||||||
|
if badge_type == "green":
|
||||||
|
badge.setStyleSheet(self.badge_style_green)
|
||||||
|
elif badge_type == "blue":
|
||||||
|
badge.setStyleSheet(self.badge_style_blue)
|
||||||
|
elif badge_type == "orange":
|
||||||
|
badge.setStyleSheet(self.badge_style_orange)
|
||||||
|
elif badge_type == "red":
|
||||||
|
badge.setStyleSheet(self.badge_style_red)
|
||||||
|
else:
|
||||||
|
badge.setStyleSheet(self.badge_style_blue) # 默认蓝色
|
||||||
|
return badge
|
||||||
|
|
||||||
|
def createModernButton(self, text, button_type="default"):
|
||||||
|
"""创建现代化按钮
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text: 按钮文字
|
||||||
|
button_type: 按钮类型 - "default", "primary", "success", "warning", "danger"
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
QPushButton: 配置好样式的按钮
|
||||||
|
"""
|
||||||
|
button = QPushButton(text)
|
||||||
|
|
||||||
|
if button_type == "primary":
|
||||||
|
button.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
background-color: rgba(77, 116, 189, 0.8);
|
||||||
|
color: #ffffff;
|
||||||
|
border: 1px solid #4d74bd;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-family: 'Microsoft YaHei', 'Inter', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
min-height: 16px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: rgba(77, 116, 189, 1.0);
|
||||||
|
border: 1px solid rgba(77, 116, 189, 1.0);
|
||||||
|
}
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: rgba(61, 96, 169, 1.0);
|
||||||
|
border: 1px solid rgba(61, 96, 169, 1.0);
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
elif button_type == "success":
|
||||||
|
button.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
background-color: rgba(45, 255, 196, 0.15);
|
||||||
|
color: #2dffc4;
|
||||||
|
border: 1px solid rgba(45, 255, 196, 0.6);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-family: 'Microsoft YaHei', 'Inter', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 400;
|
||||||
|
min-height: 16px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: rgba(45, 255, 196, 0.25);
|
||||||
|
border: 1px solid #2dffc4;
|
||||||
|
}
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: rgba(45, 255, 196, 0.4);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
elif button_type == "warning":
|
||||||
|
button.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
background-color: rgba(255, 165, 0, 0.15);
|
||||||
|
color: #ffa500;
|
||||||
|
border: 1px solid rgba(255, 165, 0, 0.6);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-family: 'Microsoft YaHei', 'Inter', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 400;
|
||||||
|
min-height: 16px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: rgba(255, 165, 0, 0.25);
|
||||||
|
border: 1px solid #ffa500;
|
||||||
|
}
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: rgba(255, 165, 0, 0.4);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
elif button_type == "danger":
|
||||||
|
button.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
background-color: rgba(255, 99, 99, 0.15);
|
||||||
|
color: #ff6363;
|
||||||
|
border: 1px solid rgba(255, 99, 99, 0.6);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-family: 'Microsoft YaHei', 'Inter', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 400;
|
||||||
|
min-height: 16px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: rgba(255, 99, 99, 0.25);
|
||||||
|
border: 1px solid #ff6363;
|
||||||
|
}
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: rgba(255, 99, 99, 0.4);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
else: # default
|
||||||
|
# 使用全局样式,不需要额外设置
|
||||||
|
pass
|
||||||
|
|
||||||
|
return button
|
||||||
|
|
||||||
|
def createModernGroupBox(self, title, parent_layout):
|
||||||
|
"""创建现代化的分组框
|
||||||
|
|
||||||
|
Args:
|
||||||
|
title: 分组框标题
|
||||||
|
parent_layout: 父布局
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: (QGroupBox, QVBoxLayout) 分组框和其内部布局
|
||||||
|
"""
|
||||||
|
group_box = QGroupBox(title)
|
||||||
|
group_layout = QVBoxLayout(group_box)
|
||||||
|
group_layout.setSpacing(0) # 减少内部间距
|
||||||
|
group_layout.setContentsMargins(0, 3, 0, 6) # 减少内容边距
|
||||||
|
|
||||||
|
# 应用现代化样式,使用更紧凑的间距
|
||||||
|
group_box.setStyleSheet("""
|
||||||
|
QGroupBox {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 11px;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
padding-top: 15px;
|
||||||
|
border-top: 1px solid rgba(77, 116, 189, 0.3);
|
||||||
|
}
|
||||||
|
QGroupBox::title {
|
||||||
|
subcontrol-origin: padding;
|
||||||
|
subcontrol-position: top left;
|
||||||
|
left: 0px;
|
||||||
|
padding: 0 5px 5px 0;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
parent_layout.addWidget(group_box)
|
||||||
|
return group_box, group_layout
|
||||||
|
|
||||||
|
def _getFigmaSpinBoxStyle(self):
|
||||||
|
"""获取符合Figma设计的SpinBox样式"""
|
||||||
|
return """
|
||||||
|
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: 3px 6px;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
min-width: 70px;
|
||||||
|
max-width: 70px;
|
||||||
|
min-height: 18px;
|
||||||
|
max-height: 18px;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox:focus, QSpinBox:focus {
|
||||||
|
border: 1px solid #4d74bd;
|
||||||
|
background-color: rgba(77, 116, 189, 0.1);
|
||||||
|
}
|
||||||
|
QDoubleSpinBox:hover, QSpinBox:hover {
|
||||||
|
border: 1px solid rgba(77, 116, 189, 0.6);
|
||||||
|
background-color: rgba(89, 100, 113, 0.25);
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::up-button, QSpinBox::up-button {
|
||||||
|
background-color: rgba(77, 116, 189, 0.2);
|
||||||
|
border: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
width: 14px;
|
||||||
|
subcontrol-origin: border;
|
||||||
|
subcontrol-position: top right;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::down-button, QSpinBox::down-button {
|
||||||
|
background-color: rgba(77, 116, 189, 0.2);
|
||||||
|
border: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
width: 14px;
|
||||||
|
subcontrol-origin: border;
|
||||||
|
subcontrol-position: bottom right;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::up-button:hover, QSpinBox::up-button:hover,
|
||||||
|
QDoubleSpinBox::down-button:hover, QSpinBox::down-button:hover {
|
||||||
|
background-color: rgba(77, 116, 189, 0.4);
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::up-arrow, QSpinBox::up-arrow {
|
||||||
|
image: url(icons/up_arrows.png);
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
QDoubleSpinBox::down-arrow, QSpinBox::down-arrow {
|
||||||
|
image: url(icons/down_arrows.png);
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def createPropertyRow(self, label_text, widget, layout, tooltip=None):
|
||||||
|
"""创建属性行
|
||||||
|
|
||||||
|
Args:
|
||||||
|
label_text: 标签文字
|
||||||
|
widget: 控件
|
||||||
|
layout: 布局
|
||||||
|
tooltip: 工具提示
|
||||||
|
"""
|
||||||
|
row_layout = QHBoxLayout()
|
||||||
|
row_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
row_layout.setSpacing(8)
|
||||||
|
|
||||||
|
# 创建标签
|
||||||
|
label = QLabel(label_text)
|
||||||
|
label.setMinimumWidth(60)
|
||||||
|
label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
if tooltip:
|
||||||
|
label.setToolTip(tooltip)
|
||||||
|
widget.setToolTip(tooltip)
|
||||||
|
|
||||||
|
row_layout.addWidget(label)
|
||||||
|
row_layout.addWidget(widget)
|
||||||
|
row_layout.addStretch()
|
||||||
|
|
||||||
|
layout.addLayout(row_layout)
|
||||||
|
|
||||||
def setPropertyLayout(self, layout):
|
def setPropertyLayout(self, layout):
|
||||||
"""设置属性面板布局引用"""
|
"""设置属性面板布局引用"""
|
||||||
@ -139,6 +579,7 @@ class PropertyPanelManager:
|
|||||||
|
|
||||||
self.name_group = QGroupBox("物体名称")
|
self.name_group = QGroupBox("物体名称")
|
||||||
name_layout = QHBoxLayout()
|
name_layout = QHBoxLayout()
|
||||||
|
name_layout.setContentsMargins(0, 8, 0, 8)
|
||||||
self.active_check = QCheckBox()
|
self.active_check = QCheckBox()
|
||||||
# 根据模型的实际可见性状态设置复选框
|
# 根据模型的实际可见性状态设置复选框
|
||||||
self.active_check.setChecked(user_visible)
|
self.active_check.setChecked(user_visible)
|
||||||
@ -1124,161 +1565,234 @@ class PropertyPanelManager:
|
|||||||
# 获取父节点
|
# 获取父节点
|
||||||
parent = model.getParent()
|
parent = model.getParent()
|
||||||
|
|
||||||
# 变换属性部分 (Transform)
|
# 变换属性部分 (Transform) - 根据Figma设计优化
|
||||||
self.transform_group = QGroupBox("变换 Transform")
|
self.transform_group = QGroupBox("变换 Transform")
|
||||||
transform_layout = QGridLayout()
|
# 应用Figma设计的GroupBox样式
|
||||||
|
self.transform_group.setStyleSheet("""
|
||||||
|
QGroupBox {
|
||||||
|
margin-top: 0px;
|
||||||
|
border: none;
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
border-top: 1px solid rgba(77, 116, 189, 0.4);
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
QGroupBox::title {
|
||||||
|
subcontrol-origin: padding;
|
||||||
|
subcontrol-position: top left;
|
||||||
|
padding: 5px 3px 8px 0px;
|
||||||
|
margin-top: 0px;
|
||||||
|
border: none;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.6px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
self._propertyLayout.addWidget(self.transform_group)
|
||||||
|
transform_layout = QVBoxLayout()
|
||||||
|
transform_layout.setSpacing(8) # 设置行间距
|
||||||
|
transform_layout.setContentsMargins(0, 8, 0, 8)
|
||||||
|
|
||||||
# 获取当前值
|
# 获取当前值
|
||||||
relativePos = model.getPos(parent) if parent else model.getPos()
|
relativePos = model.getPos(parent) if parent else model.getPos()
|
||||||
worldPos = model.getPos(self.world.render)
|
current_scale = model.getScale()
|
||||||
|
|
||||||
|
# 位置行 (Position)
|
||||||
|
position_container = QWidget()
|
||||||
|
position_layout = QHBoxLayout(position_container)
|
||||||
|
position_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
position_layout.setSpacing(6)
|
||||||
|
|
||||||
|
# 位置标签
|
||||||
|
pos_label = QLabel("位置:")
|
||||||
|
pos_label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
color: #ebebeb;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
min-width: 31px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
position_layout.addWidget(pos_label)
|
||||||
|
|
||||||
|
# 添加弹性空间
|
||||||
|
position_layout.addStretch()
|
||||||
|
|
||||||
|
# X位置
|
||||||
|
x_pos_label = QLabel("X:")
|
||||||
|
x_pos_label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
color: #ebebeb;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
position_layout.addWidget(x_pos_label)
|
||||||
|
|
||||||
# 位置 (Position)
|
|
||||||
transform_layout.addWidget(QLabel("相对位置"), 0, 0)
|
|
||||||
self.pos_x = QDoubleSpinBox()
|
self.pos_x = QDoubleSpinBox()
|
||||||
self.pos_y = QDoubleSpinBox()
|
self.pos_x.setRange(-1000000.0, 1000000.0)
|
||||||
self.pos_z = QDoubleSpinBox()
|
|
||||||
|
|
||||||
# 设置位置控件属性
|
|
||||||
for pos_widget in [self.pos_x, self.pos_y, self.pos_z]:
|
|
||||||
pos_widget.setRange(-1000000.0, 1000000.0)
|
|
||||||
|
|
||||||
self.pos_x.setValue(relativePos.getX())
|
self.pos_x.setValue(relativePos.getX())
|
||||||
|
self.pos_x.setStyleSheet(self._getFigmaSpinBoxStyle())
|
||||||
|
position_layout.addWidget(self.pos_x)
|
||||||
|
|
||||||
|
# Y位置
|
||||||
|
y_pos_label = QLabel("Y:")
|
||||||
|
y_pos_label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
color: #ebebeb;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
position_layout.addWidget(y_pos_label)
|
||||||
|
|
||||||
|
self.pos_y = QDoubleSpinBox()
|
||||||
|
self.pos_y.setRange(-1000000.0, 1000000.0)
|
||||||
self.pos_y.setValue(relativePos.getY())
|
self.pos_y.setValue(relativePos.getY())
|
||||||
|
self.pos_y.setStyleSheet(self._getFigmaSpinBoxStyle())
|
||||||
|
position_layout.addWidget(self.pos_y)
|
||||||
|
|
||||||
|
# Z位置
|
||||||
|
z_pos_label = QLabel("Z:")
|
||||||
|
z_pos_label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
color: #ebebeb;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
position_layout.addWidget(z_pos_label)
|
||||||
|
|
||||||
|
self.pos_z = QDoubleSpinBox()
|
||||||
|
self.pos_z.setRange(-1000000.0, 1000000.0)
|
||||||
self.pos_z.setValue(relativePos.getZ())
|
self.pos_z.setValue(relativePos.getZ())
|
||||||
|
self.pos_z.setStyleSheet(self._getFigmaSpinBoxStyle())
|
||||||
|
position_layout.addWidget(self.pos_z)
|
||||||
|
|
||||||
# 连接位置变化事件
|
transform_layout.addWidget(position_container)
|
||||||
# self.pos_x.valueChanged.connect(lambda v: model.setX(parent, v) if parent else model.setX(v))
|
|
||||||
# self.pos_y.valueChanged.connect(lambda v: model.setY(parent, v) if parent else model.setY(v))
|
|
||||||
# self.pos_z.valueChanged.connect(lambda v: model.setZ(parent, v) if parent else model.setZ(v))
|
|
||||||
|
|
||||||
|
# 缩放行 (Scale)
|
||||||
|
scale_container = QWidget()
|
||||||
|
scale_layout = QHBoxLayout(scale_container)
|
||||||
|
scale_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
scale_layout.setSpacing(6)
|
||||||
|
|
||||||
|
# 缩放标签
|
||||||
|
scale_label = QLabel("缩放:")
|
||||||
|
scale_label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
color: #ebebeb;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
min-width: 31px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
scale_layout.addWidget(scale_label)
|
||||||
|
|
||||||
|
# 添加弹性空间
|
||||||
|
scale_layout.addStretch()
|
||||||
|
|
||||||
|
# X缩放
|
||||||
|
x_scale_label = QLabel("X:")
|
||||||
|
x_scale_label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
color: #ebebeb;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
scale_layout.addWidget(x_scale_label)
|
||||||
|
|
||||||
|
self.scale_x = QDoubleSpinBox()
|
||||||
|
self.scale_x.setRange(-1000, 1000)
|
||||||
|
self.scale_x.setSingleStep(0.1)
|
||||||
|
self.scale_x.setValue(current_scale.getX())
|
||||||
|
self.scale_x.setStyleSheet(self._getFigmaSpinBoxStyle())
|
||||||
|
scale_layout.addWidget(self.scale_x)
|
||||||
|
|
||||||
|
# Y缩放
|
||||||
|
y_scale_label = QLabel("Y:")
|
||||||
|
y_scale_label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
color: #ebebeb;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
scale_layout.addWidget(y_scale_label)
|
||||||
|
|
||||||
|
self.scale_y = QDoubleSpinBox()
|
||||||
|
self.scale_y.setRange(-1000, 1000)
|
||||||
|
self.scale_y.setSingleStep(0.1)
|
||||||
|
self.scale_y.setValue(current_scale.getY())
|
||||||
|
self.scale_y.setStyleSheet(self._getFigmaSpinBoxStyle())
|
||||||
|
scale_layout.addWidget(self.scale_y)
|
||||||
|
|
||||||
|
# Z缩放
|
||||||
|
z_scale_label = QLabel("Z:")
|
||||||
|
z_scale_label.setStyleSheet("""
|
||||||
|
QLabel {
|
||||||
|
color: #ebebeb;
|
||||||
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
scale_layout.addWidget(z_scale_label)
|
||||||
|
|
||||||
|
self.scale_z = QDoubleSpinBox()
|
||||||
|
self.scale_z.setRange(-1000, 1000)
|
||||||
|
self.scale_z.setSingleStep(0.1)
|
||||||
|
self.scale_z.setValue(current_scale.getZ())
|
||||||
|
self.scale_z.setStyleSheet(self._getFigmaSpinBoxStyle())
|
||||||
|
scale_layout.addWidget(self.scale_z)
|
||||||
|
|
||||||
|
transform_layout.addWidget(scale_container)
|
||||||
|
|
||||||
|
# 连接事件
|
||||||
def updateXPosition(value):
|
def updateXPosition(value):
|
||||||
model.setX(value)
|
model.setX(value)
|
||||||
self.refreshModelValues(model)
|
self.refreshModelValues(model)
|
||||||
|
|
||||||
self.pos_x.valueChanged.connect(updateXPosition)
|
|
||||||
|
|
||||||
def updateYPosition(value):
|
def updateYPosition(value):
|
||||||
model.setY(value)
|
model.setY(value)
|
||||||
self.refreshModelValues(model)
|
self.refreshModelValues(model)
|
||||||
|
|
||||||
self.pos_y.valueChanged.connect(updateYPosition)
|
|
||||||
|
|
||||||
def updateZPosition(value):
|
def updateZPosition(value):
|
||||||
model.setZ(value)
|
model.setZ(value)
|
||||||
self.refreshModelValues(model)
|
self.refreshModelValues(model)
|
||||||
|
|
||||||
|
self.pos_x.valueChanged.connect(updateXPosition)
|
||||||
|
self.pos_y.valueChanged.connect(updateYPosition)
|
||||||
self.pos_z.valueChanged.connect(updateZPosition)
|
self.pos_z.valueChanged.connect(updateZPosition)
|
||||||
|
|
||||||
# 创建并设置 X, Y, Z 标签居中
|
|
||||||
x_label1 = QLabel("X")
|
|
||||||
y_label1 = QLabel("Y")
|
|
||||||
z_label1 = QLabel("Z")
|
|
||||||
x_label1.setAlignment(Qt.AlignCenter)
|
|
||||||
y_label1.setAlignment(Qt.AlignCenter)
|
|
||||||
z_label1.setAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
transform_layout.addWidget(x_label1, 0, 1)
|
|
||||||
transform_layout.addWidget(y_label1, 0, 2)
|
|
||||||
transform_layout.addWidget(z_label1, 0, 3)
|
|
||||||
transform_layout.addWidget(self.pos_x, 1, 1)
|
|
||||||
transform_layout.addWidget(self.pos_y, 1, 2)
|
|
||||||
transform_layout.addWidget(self.pos_z, 1, 3)
|
|
||||||
|
|
||||||
# 世界位置 (只读)
|
|
||||||
transform_layout.addWidget(QLabel("世界位置"), 2, 0)
|
|
||||||
self.world_pos_x = QDoubleSpinBox()
|
|
||||||
self.world_pos_y = QDoubleSpinBox()
|
|
||||||
self.world_pos_z = QDoubleSpinBox()
|
|
||||||
|
|
||||||
# 设置世界位置控件属性
|
|
||||||
for world_pos_widget in [self.world_pos_x, self.world_pos_y, self.world_pos_z]:
|
|
||||||
world_pos_widget.setRange(-1000000.0, 1000000.0)
|
|
||||||
world_pos_widget.setReadOnly(True)
|
|
||||||
|
|
||||||
self.world_pos_x.setValue(worldPos.getX())
|
|
||||||
self.world_pos_y.setValue(worldPos.getY())
|
|
||||||
self.world_pos_z.setValue(worldPos.getZ())
|
|
||||||
|
|
||||||
transform_layout.addWidget(self.world_pos_x, 3, 1)
|
|
||||||
transform_layout.addWidget(self.world_pos_y, 3, 2)
|
|
||||||
transform_layout.addWidget(self.world_pos_z, 3, 3)
|
|
||||||
|
|
||||||
# 旋转 (Rotation)
|
|
||||||
transform_layout.addWidget(QLabel("旋转"), 4, 0)
|
|
||||||
self.rot_x = QDoubleSpinBox()
|
|
||||||
self.rot_y = QDoubleSpinBox()
|
|
||||||
self.rot_z = QDoubleSpinBox()
|
|
||||||
|
|
||||||
# 设置旋转控件属性
|
|
||||||
for rot_widget in [self.rot_x, self.rot_y, self.rot_z]:
|
|
||||||
rot_widget.setRange(-360, 360)
|
|
||||||
|
|
||||||
self.rot_x.setValue(model.getH())
|
|
||||||
self.rot_y.setValue(model.getP())
|
|
||||||
self.rot_z.setValue(model.getR())
|
|
||||||
|
|
||||||
# 连接旋转变化事件
|
|
||||||
self.rot_x.valueChanged.connect(lambda v: model.setH(v))
|
|
||||||
self.rot_y.valueChanged.connect(lambda v: model.setP(v))
|
|
||||||
self.rot_z.valueChanged.connect(lambda v: model.setR(v))
|
|
||||||
|
|
||||||
# 创建并设置 H, P, R 标签居中
|
|
||||||
h_label = QLabel("H")
|
|
||||||
p_label = QLabel("P")
|
|
||||||
r_label = QLabel("R")
|
|
||||||
h_label.setAlignment(Qt.AlignCenter)
|
|
||||||
p_label.setAlignment(Qt.AlignCenter)
|
|
||||||
r_label.setAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
transform_layout.addWidget(h_label, 4, 1)
|
|
||||||
transform_layout.addWidget(p_label, 4, 2)
|
|
||||||
transform_layout.addWidget(r_label, 4, 3)
|
|
||||||
transform_layout.addWidget(self.rot_x, 5, 1)
|
|
||||||
transform_layout.addWidget(self.rot_y, 5, 2)
|
|
||||||
transform_layout.addWidget(self.rot_z, 5, 3)
|
|
||||||
|
|
||||||
# 缩放 (Scale)
|
|
||||||
transform_layout.addWidget(QLabel("缩放"), 6, 0)
|
|
||||||
self.scale_x = QDoubleSpinBox()
|
|
||||||
self.scale_y = QDoubleSpinBox()
|
|
||||||
self.scale_z = QDoubleSpinBox()
|
|
||||||
|
|
||||||
current_scale = model.getScale()
|
|
||||||
|
|
||||||
# 设置缩放控件属性
|
|
||||||
for i, (scale_widget, scale_value) in enumerate(zip([self.scale_x, self.scale_y, self.scale_z],
|
|
||||||
[current_scale.getX(), current_scale.getY(),
|
|
||||||
current_scale.getZ()])):
|
|
||||||
scale_widget.setRange(-1000, 1000)
|
|
||||||
scale_widget.setSingleStep(0.1)
|
|
||||||
scale_widget.setValue(scale_value)
|
|
||||||
|
|
||||||
self.scale_x.valueChanged.connect(lambda value: self._onScaleValueChanged(self.scale_x, value))
|
|
||||||
self.scale_y.valueChanged.connect(lambda value: self._onScaleValueChanged(self.scale_y, value))
|
|
||||||
self.scale_z.valueChanged.connect(lambda value: self._onScaleValueChanged(self.scale_z, value))
|
|
||||||
|
|
||||||
# 连接缩放变化事件
|
# 连接缩放变化事件
|
||||||
self.scale_x.valueChanged.connect(lambda value: self._updateXScale(model, value))
|
self.scale_x.valueChanged.connect(lambda value: self._updateXScale(model, value))
|
||||||
self.scale_y.valueChanged.connect(lambda value: self._updateYScale(model, value))
|
self.scale_y.valueChanged.connect(lambda value: self._updateYScale(model, value))
|
||||||
self.scale_z.valueChanged.connect(lambda value: self._updateZScale(model, value))
|
self.scale_z.valueChanged.connect(lambda value: self._updateZScale(model, value))
|
||||||
|
|
||||||
# 创建并设置 X, Y, Z 标签居中
|
|
||||||
x_label3 = QLabel("X")
|
|
||||||
y_label3 = QLabel("Y")
|
|
||||||
z_label3 = QLabel("Z")
|
|
||||||
x_label3.setAlignment(Qt.AlignCenter)
|
|
||||||
y_label3.setAlignment(Qt.AlignCenter)
|
|
||||||
z_label3.setAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
transform_layout.addWidget(x_label3, 6, 1)
|
|
||||||
transform_layout.addWidget(y_label3, 6, 2)
|
|
||||||
transform_layout.addWidget(z_label3, 6, 3)
|
|
||||||
transform_layout.addWidget(self.scale_x, 7, 1)
|
|
||||||
transform_layout.addWidget(self.scale_y, 7, 2)
|
|
||||||
transform_layout.addWidget(self.scale_z, 7, 3)
|
|
||||||
|
|
||||||
self.transform_group.setLayout(transform_layout)
|
self.transform_group.setLayout(transform_layout)
|
||||||
self._propertyLayout.addWidget(self.transform_group)
|
|
||||||
|
|
||||||
# 碰撞检测面板
|
# 碰撞检测面板
|
||||||
self._addCollisionPanel(model)
|
self._addCollisionPanel(model)
|
||||||
|
|||||||
799
ui/widgets.py
799
ui/widgets.py
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user