3、从原型到代码:Figma设计稿导出、使用Qt Designer还原界面、理解UI文件结构

说实话,很多做桌面应用的朋友,都卡在「设计稿变代码」这一步。

设计稿画得漂漂亮亮,一到写代码就手忙脚乱。要么布局对不上,要么间距差一像素。我早期做项目时也踩过这个坑,后来摸索出一套流程——从Figma导出,到Qt Designer还原,再到理解UI文件结构。今天就把这套方法掰开揉碎讲给你听。

3.1 从Figma导出设计稿:别小看这一步

很多人觉得导出就是点个按钮。其实不然。我见过太多人导出一堆乱七八糟的素材,最后还得自己重新拼。

正确的导出姿势是这样的:

  1. 先整理图层——把同类型的控件放到一个组里。比如所有按钮放一组,所有输入框放一组。我在项目中习惯用「Btn_」「Input_」这样的前缀命名,方便后续查找。
  2. 导出为SVG——Qt Designer对SVG支持很好,而且SVG是矢量图,缩放不失真。我曾经试过用PNG,结果在高DPI屏幕上糊得一塌糊涂。
  3. 注意导出尺寸——Figma里设计稿通常是1x,但Qt Designer里可能需要2x。我的做法是:导出时直接选2x,省得后面再调。
小技巧: 如果你设计稿里有图标,建议单独导出。别把图标和背景混在一起,否则在Qt里很难做状态切换(比如hover效果)。

3.2 使用Qt Designer还原界面:从「看」到「做」

打开Qt Designer,第一件事不是拖控件,而是设置布局策略。我见过太多新手一上来就拖控件,结果窗口一拉伸,界面全乱套。

我的还原步骤:

  1. 先搭骨架——用QWidget或QFrame把界面分区。比如左侧导航区、右侧内容区、底部状态栏。这一步对应Figma里的「大区块」。
  2. 再填细节——往每个区里放具体控件。按钮、标签、输入框……注意对齐。Qt Designer有对齐辅助线,用起来很方便。
  3. 最后调样式——用QSS(Qt样式表)设置颜色、字体、圆角。这部分我后面会专门讲。
重点: 布局一定要用「布局管理器」(QHBoxLayout、QVBoxLayout、QGridLayout)。别用绝对布局,否则在不同分辨率下会出问题。我早期一个项目就是因为用了绝对布局,结果用户换了个4K屏,界面直接崩了。

3.3 理解UI文件结构:它其实是个XML

Qt Designer保存的文件是.ui格式。你如果用记事本打开它,会发现它就是个XML文件。嗯,说白了就是一堆标签。

一个典型的UI文件结构:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
  <class>MainWindow</class>
  <widget class="QMainWindow" name="MainWindow">
    <property name="geometry">
      <rect>
        <x>0</x>
        <y>0</y>
        <width>800</width>
        <height>600</height>
      </rect>
    </property>
    <widget class="QPushButton" name="pushButton">
      <property name="text">
        <string>点击我</string>
      </property>
    </widget>
  </widget>
</ui>

你看,结构其实很清晰:

  • <ui>——根节点,版本号
  • <class>——这个界面对应的Python类名
  • <widget>——每个控件,class属性是控件类型,name是对象名
  • <property>——控件的属性,比如位置、大小、文本
注意: 千万别手动修改UI文件!我试过,改完Qt Designer就打不开了。要改就在Qt Designer里改,或者用代码动态修改。

3.4 从UI文件到Python代码:两种方式

UI文件不能直接运行,得转成Python代码。有两种方式:

方式 命令/方法 适用场景
静态转换 pyuic5 -o output.py input.ui 界面固定不变时
动态加载 uic.loadUi('input.ui', self) 界面需要频繁修改时

我个人推荐动态加载。 为什么呢?因为开发过程中界面改来改去是常事。如果用静态转换,每次改完UI文件都得重新运行命令,很烦。动态加载的话,改完UI文件直接运行程序就行。

举个例子:

import sys
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QMainWindow

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        uic.loadUi('mainwindow.ui', self)  # 动态加载UI文件

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

你看,代码就这么几行。UI文件里放什么控件,程序里就能直接用。比如UI里有个按钮叫pushButton,代码里直接self.pushButton就能访问。

避坑指南: 我曾经犯过一个错——UI文件里控件名用了中文。结果动态加载时报错,说找不到对象。后来我学乖了,所有控件名都用英文,最多加个下划线。比如btn_logininput_password

3.5 实战:还原一个登录界面

光说不练假把式。咱们拿一个登录界面来实操。

Figma设计稿长这样:

  • 顶部:Logo(一张图片)
  • 中间:用户名输入框、密码输入框、登录按钮
  • 底部:注册链接

在Qt Designer里还原:

  1. 拖一个QWidget作为主容器,设置垂直布局
  2. 放一个QLabel放Logo,设置pixmap属性
  3. 放两个QLineEdit,一个设placeholderText为「请输入用户名」,另一个设echoMode为Password
  4. 放一个QPushButton,文本设为「登录」
  5. 放一个QLabel,文本设为「没有账号?注册」

对应的UI文件结构:

<widget class="QWidget" name="centralwidget">
  <layout class="QVBoxLayout" name="verticalLayout">
    <item>
      <widget class="QLabel" name="label_logo">
        <property name="pixmap">logo.png</property>
      </widget>
    </item>
    <item>
      <widget class="QLineEdit" name="lineEdit_username"/>
    </item>
    <item>
      <widget class="QLineEdit" name="lineEdit_password"/>
    </item>
    <item>
      <widget class="QPushButton" name="pushButton_login"/>
    </item>
    <item>
      <widget class="QLabel" name="label_register"/>
    </item>
  </layout>
</widget>

你看,结构一目了然。每个控件都在对应的布局里,顺序就是从上到下。

核心思路: 从Figma到Qt Designer,不是「照着画」,而是「理解结构」。设计稿里的每个区块,对应Qt里的一个容器;每个控件,对应Qt里的一个widget。理解了这一点,还原界面就是水到渠成的事。

好了,这一章就到这里。下一章咱们聊聊「信号与槽」——说白了就是怎么让按钮点下去有反应。到时候见。