<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>界面与串口 on 扎塔-Zata</title><link>https://www.zata.cc/tags/%E7%95%8C%E9%9D%A2%E4%B8%8E%E4%B8%B2%E5%8F%A3/</link><description>Recent content in 界面与串口 on 扎塔-Zata</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>扎塔-Zata</copyright><lastBuildDate>Thu, 24 Sep 2026 17:09:06 +0800</lastBuildDate><atom:link href="https://www.zata.cc/tags/%E7%95%8C%E9%9D%A2%E4%B8%8E%E4%B8%B2%E5%8F%A3/index.xml" rel="self" type="application/rss+xml"/><item><title>PyQt-设备像素设置</title><link>https://www.zata.cc/p/pyqt-%E8%AE%BE%E5%A4%87%E5%83%8F%E7%B4%A0%E8%AE%BE%E7%BD%AE/</link><pubDate>Thu, 24 Apr 2025 11:06:37 +0800</pubDate><guid>https://www.zata.cc/p/pyqt-%E8%AE%BE%E5%A4%87%E5%83%8F%E7%B4%A0%E8%AE%BE%E7%BD%AE/</guid><description>&lt;img src="https://www.zata.cc/p/pyqt-%E8%AE%BE%E5%A4%87%E5%83%8F%E7%B4%A0%E8%AE%BE%E7%BD%AE/images/index/index.png" alt="Featured image of post PyQt-设备像素设置" />&lt;h3 id="让qt应用在高doi或者高分辨率显示器上看起来更加清晰--最新pyqt6已经不需要设置">让Qt应用在高DOI或者高分辨率显示器上看起来更加清晰 （最新pyqt6已经不需要设置）
&lt;/h3>&lt;p>QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)&lt;/p>
&lt;p>&lt;strong>目的&lt;/strong>&lt;/p>
&lt;p>这两行代码的目的是让你的 Qt 应用程序在高 DPI（Dots Per Inch，每英寸点数）或高分辨率显示器（例如 Retina 屏、4K 显示器）上看起来更清晰、大小更合适。&lt;/p>
&lt;p>&lt;strong>代码解释&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;code>QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)&lt;/code>&lt;/p>
&lt;ul>
&lt;li>&lt;code>QApplication&lt;/code>: 这是你的 Qt 应用程序的核心类。&lt;/li>
&lt;li>&lt;code>setAttribute&lt;/code>: 这是设置应用程序级别属性的方法。&lt;/li>
&lt;li>&lt;code>Qt.AA_EnableHighDpiScaling&lt;/code>: 这是一个枚举值（属性标志）。当它被设置为 &lt;code>True&lt;/code> 时，它告诉 Qt 启用基于显示器 DPI 的自动缩放。这意味着 Qt 会尝试自动调整窗口、控件（按钮、文本框等）的大小以及字体大小，使它们在不同 DPI 的屏幕上看起来比例一致。&lt;/li>
&lt;li>&lt;code>True&lt;/code>: 启用这个属性。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;code>QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)&lt;/code>&lt;/p>
&lt;ul>
&lt;li>&lt;code>Qt.AA_UseHighDpiPixmaps&lt;/code>: 这是另一个属性标志。当它被设置为 &lt;code>True&lt;/code> 时，它告诉 Qt 在高 DPI 显示器上使用高分辨率版本的像素图（pixmaps），也就是图标和图片。如果你为图标提供了 &lt;code>@2x&lt;/code> 或类似的高分辨率版本（例如 &lt;code>icon.png&lt;/code> 和 &lt;code>icon@2x.png&lt;/code>），设置此项能让 Qt 自动选择合适的版本，从而在高 DPI 屏幕上显示清晰的图标，而不是模糊的低分辨率版本。&lt;/li>
&lt;li>&lt;code>True&lt;/code>: 启用这个属性。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>何时以及如何使用&lt;/strong>&lt;/p>
&lt;p>这两行代码&lt;strong>非常重要&lt;/strong>的一点是：它们&lt;strong>必须&lt;/strong>在创建 &lt;code>QApplication&lt;/code> 实例&lt;strong>之前&lt;/strong>被调用。因为它们影响应用程序如何初始化以及如何与操作系统的显示设置交互。&lt;/p>
&lt;p>&lt;strong>简单示例 (以 PyQt5 为例)&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 导入你需要的 PyQt 或 PySide 模块&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 可能是 PyQt5, PyQt6, PySide2, PySide6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 这里以 PyQt6 为例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># from PyQt6.QtCore import Qt # Qt 模块包含枚举值&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt5.QtWidgets&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QMainWindow&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QWidget&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QVBoxLayout&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QHBoxLayout&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QTabWidget&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QAction&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QFileDialog&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QMessageBox&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QSplitter&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QToolBar&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QStatusBar&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QLabel&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QComboBox&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">QApplication&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt5.QtCore&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Qt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># --- 关键步骤 ---&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 在创建 QApplication 实例之前设置高 DPI 属性&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 注意: 在 Qt 6 已经自动支持了， 所以不需要单独写代码&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 在 Qt 5 中，通常直接是 Qt.AA_...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 设置高 DPI 支持&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># PyQt5 需要显式启用高 DPI 缩放&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">QApplication&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setAttribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Qt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">AA_EnableHighDpiScaling&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">QApplication&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setAttribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Qt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">AA_UseHighDpiPixmaps&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># --- 关键步骤结束 ---&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 创建 QApplication 实例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># sys.argv 允许你传递命令行参数给应用程序&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QApplication&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 创建一个简单的窗口&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">window&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QWidget&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">window&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setWindowTitle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;高 DPI 示例&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 添加一些控件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">layout&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QVBoxLayout&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">label&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QLabel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;这个标签在高 DPI 屏幕上应该看起来很清晰。&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">label&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">window&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setLayout&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">layout&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 设置窗口大小并显示&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">window&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">resize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">300&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">150&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">window&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">show&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 启动应用程序的事件循环&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 程序会在这里等待用户交互，直到窗口关闭&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">app&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exec&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="https://www.zata.cc/p/pyqt-%E8%AE%BE%E5%A4%87%E5%83%8F%E7%B4%A0%E8%AE%BE%E7%BD%AE/images/index/index-1.png"
width="302"
height="182"
srcset="https://www.zata.cc/p/pyqt-%E8%AE%BE%E5%A4%87%E5%83%8F%E7%B4%A0%E8%AE%BE%E7%BD%AE/images/index/index-1_hu1288030797340108617.png 480w, https://www.zata.cc/p/pyqt-%E8%AE%BE%E5%A4%87%E5%83%8F%E7%B4%A0%E8%AE%BE%E7%BD%AE/images/index/index-1_hu15337750663736976716.png 1024w"
loading="lazy"
alt="默认DPI特性"
class="gallery-image"
data-flex-grow="165"
data-flex-basis="398px"
>&lt;/p>
&lt;p>&lt;strong>总结&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>为了让你的 PyQt/PySide 应用在现代高分辨率屏幕上获得良好的视觉效果（避免元素过小或图像模糊），请在创建 &lt;code>QApplication&lt;/code> 对象之前添加这两行代码（pyqt5）。&lt;/li>
&lt;li>&lt;code>AA_EnableHighDpiScaling&lt;/code> 主要负责 UI 元素（控件、字体、布局）的缩放。&lt;/li>
&lt;li>&lt;code>AA_UseHighDpiPixmaps&lt;/code> 主要负责图像和图标的清晰度。&lt;/li>
&lt;/ul>
&lt;p>在较新的 Qt 版本（尤其是 Qt 6）中，&lt;code>AA_EnableHighDpiScaling&lt;/code> 可能已经是默认启用的，但显式设置它是一个好的实践，可以确保跨版本和平台的兼容性。而 &lt;code>AA_UseHighDpiPixmaps&lt;/code> 通常仍然需要显式设置以加载高分辨率图像资源。&lt;/p>
&lt;h3 id="设备像素比">设备像素比
&lt;/h3>&lt;p>除了之前提到的 &lt;code>AA_EnableHighDpiScaling&lt;/code> 和 &lt;code>AA_UseHighDpiPixmaps&lt;/code> 这两个用于&lt;strong>自动&lt;/strong>处理高 DPI 的应用程序属性之外，还有一些相关的函数和概念，它们允许你&lt;strong>查询&lt;/strong> DPI 信息或进行更手动的控制。&lt;/p>
&lt;p>最接近且常用的相关功能是查询&lt;strong>设备像素比 (Device Pixel Ratio)&lt;/strong>。&lt;/p>
&lt;p>&lt;strong>核心概念：设备像素比 (Device Pixel Ratio)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>定义&lt;/strong>：设备像素比是指物理像素（屏幕上实际的光点）与设备无关像素（也称为逻辑像素，是应用程序绘制时使用的标准坐标单位，通常基于 96 DPI）之间的比例。&lt;/li>
&lt;li>&lt;strong>意义&lt;/strong>：
&lt;ul>
&lt;li>在标准 DPI 显示器上，这个比例通常是 1.0。&lt;/li>
&lt;li>在高 DPI 显示器（如 Retina 或 4K 屏）上，这个比例会大于 1.0（例如 1.5, 2.0, 2.5 等），表示一个逻辑像素对应了多个物理像素。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>用途&lt;/strong>：你可以使用这个比率来：
&lt;ol>
&lt;li>&lt;strong>手动缩放&lt;/strong>：在需要精确控制像素的情况下（例如自定义绘图 &lt;code>paintEvent&lt;/code>），将逻辑坐标或尺寸乘以这个比率来得到物理像素尺寸。&lt;/li>
&lt;li>&lt;strong>加载资源&lt;/strong>：根据比率选择不同分辨率的图像资源（虽然 &lt;code>AA_UseHighDpiPixmaps&lt;/code> 通常会自动处理）。&lt;/li>
&lt;li>&lt;strong>调试&lt;/strong>：检查应用程序当前的缩放状态。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>相关函数和类&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;code>QWidget.devicePixelRatio() -&amp;gt; int&lt;/code> / &lt;code>QWidget.devicePixelRatioF() -&amp;gt; float&lt;/code>&lt;/p>
&lt;ul>
&lt;li>获取&lt;strong>控件（Widget）当前所在屏幕&lt;/strong>的设备像素比。&lt;/li>
&lt;li>返回整数版本 (&lt;code>devicePixelRatio&lt;/code>) 或更精确的浮点数版本 (&lt;code>devicePixelRatioF&lt;/code>)。&lt;/li>
&lt;li>这是最常用的，因为它直接关联到你正在操作的那个窗口或控件。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;code>QScreen&lt;/code> 类&lt;/p>
&lt;ul>
&lt;li>代表一个物理显示屏幕。&lt;/li>
&lt;li>&lt;code>QGuiApplication.primaryScreen()&lt;/code>: 获取系统的主屏幕对象。&lt;/li>
&lt;li>&lt;code>QWidget.screen()&lt;/code>: 获取控件当前所在的 &lt;code>QScreen&lt;/code> 对象。&lt;/li>
&lt;li>&lt;code>QScreen.devicePixelRatio() -&amp;gt; float&lt;/code>: 获取&lt;strong>这个特定屏幕&lt;/strong>的设备像素比。&lt;/li>
&lt;li>&lt;code>QScreen.logicalDotsPerInch() -&amp;gt; float&lt;/code>: 获取屏幕的逻辑 DPI (通常是 96 DPI，但也可能被系统设置为其他值)。&lt;/li>
&lt;li>&lt;code>QScreen.physicalDotsPerInch() -&amp;gt; float&lt;/code>: 获取屏幕的物理 DPI (实际硬件的像素密度)。&lt;/li>
&lt;li>&lt;code>QScreen.geometry() -&amp;gt; QRect&lt;/code>: 获取屏幕的几何尺寸（使用逻辑像素）。&lt;/li>
&lt;li>&lt;code>QScreen.availableGeometry() -&amp;gt; QRect&lt;/code>: 获取屏幕的可用几何尺寸（排除任务栏等，使用逻辑像素）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>教程和示例&lt;/strong>&lt;/p>
&lt;p>下面的示例展示了如何获取窗口和屏幕的设备像素比以及其他相关信息，并包含了一个简单的自定义绘图控件，演示如何在 &lt;code>paintEvent&lt;/code> 中考虑像素比。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt6.QtWidgets&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">QApplication&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QMainWindow&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QWidget&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QLabel&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QVBoxLayout&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QTextEdit&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># QGuiApplication 用于获取屏幕信息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt6.QtGui&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">QGuiApplication&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QPainter&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QColor&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QFont&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QPaintEvent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt6.QtCore&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Qt&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QRectF&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QSize&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># --- 依然建议先设置自动缩放属性 ---&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 这让 Qt 框架自动处理大部分 UI 元素的缩放&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Qt 6 风格&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QApplication&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setAttribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Qt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ApplicationAttribute&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">AA_EnableHighDpiScaling&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QApplication&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setAttribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Qt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ApplicationAttribute&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">AA_UseHighDpiPixmaps&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">except&lt;/span> &lt;span class="ne">AttributeError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Qt 5 风格&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QApplication&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setAttribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Qt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">AA_EnableHighDpiScaling&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QApplication&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setAttribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Qt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">AA_UseHighDpiPixmaps&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ---&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 自定义绘图控件，演示如何在 paintEvent 中使用 devicePixelRatio&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">DrawingWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QWidget&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">minimumSizeHint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">QSize&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 提供一个基于逻辑像素的最小尺寸提示&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">QSize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">200&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">100&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 重写 paintEvent 进行自定义绘图&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">paintEvent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">event&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">QPaintEvent&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QPainter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setRenderHint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QPainter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">RenderHint&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Antialiasing&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 让绘制更平滑&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 获取当前控件的设备像素比 (浮点数版本更精确)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ratio&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">devicePixelRatioF&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 准备绘制信息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Device Pixel Ratio: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ratio&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logical_rect&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QRectF&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">10.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">10.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">180.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">50.0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 使用逻辑像素定义矩形&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 绘制背景矩形 (QPainter 默认使用逻辑坐标)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setBrush&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QColor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">230&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">240&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">255&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="c1"># 淡蓝色背景&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setPen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Qt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">PenStyle&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">NoPen&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 无边框&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">drawRoundedRect&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logical_rect&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">5.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">5.0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 圆角矩形&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 绘制文字 (QPainter 会根据 Qt 的缩放设置自动处理字体大小)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 但如果你需要基于物理像素精确控制，可能需要手动计算&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setPen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QColor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;black&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">font&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QFont&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 你可以尝试设置逻辑点大小，Qt 会处理缩放&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">font&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setPointSizeF&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setFont&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">font&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 在矩形内绘制文本 (文本位置也是逻辑坐标)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">drawText&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logical_rect&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">adjusted&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">Qt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">AlignmentFlag&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">AlignCenter&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 示例：如果需要绘制一个固定物理像素大小的线条 (需要手动计算)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 假设需要绘制一条 2 个物理像素宽的线&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">physical_line_width&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logical_line_width&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">physical_line_width&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">ratio&lt;/span> &lt;span class="c1"># 计算对应的逻辑宽度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">pen&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pen&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># 获取当前画笔&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">pen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setColor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QColor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;red&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">pen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setWidthF&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logical_line_width&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 设置逻辑宽度&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setPen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pen&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 绘制线条 (坐标仍是逻辑像素)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">drawLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logical_rect&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">left&lt;/span>&lt;span class="p">()),&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logical_rect&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">bottom&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logical_rect&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">right&lt;/span>&lt;span class="p">()),&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logical_rect&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">bottom&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">painter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># 结束绘制&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 主窗口类&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MainWindow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QMainWindow&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">super&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="fm">__init__&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setWindowTitle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;查询 DPI 和设备像素比&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setGeometry&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">500&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">450&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 初始位置和大小 (逻辑像素)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 用于显示信息的文本框&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info_display&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QTextEdit&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info_display&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setReadOnly&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info_display&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setLineWrapMode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QTextEdit&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">LineWrapMode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">NoWrap&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 不自动换行&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 自定义绘图控件实例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">drawing_widget&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">DrawingWidget&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 布局&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">central_widget&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QWidget&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QVBoxLayout&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">central_widget&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QLabel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;信息查询结果:&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info_display&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QLabel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;自定义绘图区域:&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">drawing_widget&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setCentralWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">central_widget&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 在窗口显示后查询信息会更可靠&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">initial_query_done&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 查询并显示 DPI 和屏幕信息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">query_and_display_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. 获取窗口自身的设备像素比&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 注意: 最好在窗口实际显示到屏幕上之后获取 (例如在 showEvent 或 moveEvent 中)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">window_dpr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">devicePixelRatio&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">window_dpr_f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">devicePixelRatioF&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;--- 窗口 (Window) ---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;devicePixelRatio(): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">window_dpr&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> (int)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;devicePixelRatioF(): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">window_dpr_f&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> (float)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. 获取窗口所在的屏幕信息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">current_screen&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">screen&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># QWidget.screen() 获取当前屏幕&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 如果窗口还没显示或找不到屏幕，尝试获取主屏幕&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">current_screen&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QGuiApplication&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">primaryScreen&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">screen_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">screen_dpr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">devicePixelRatio&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logical_dpi_x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">logicalDotsPerInchX&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logical_dpi_y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">logicalDotsPerInchY&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">physical_dpi_x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">physicalDotsPerInchX&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">physical_dpi_y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">physicalDotsPerInchY&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">geometry&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">geometry&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># 逻辑像素矩形&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">available_geometry&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">current_screen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">availableGeometry&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># 可用逻辑像素矩形&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">--- 当前屏幕 (Screen: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">screen_name&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">) ---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;devicePixelRatio(): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">screen_dpr&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;logicalDotsPerInch (X, Y): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">logical_dpi_x&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.1f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">logical_dpi_y&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.1f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;physicalDotsPerInch (X, Y): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">physical_dpi_x&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.1f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">physical_dpi_y&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.1f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;geometry (逻辑像素): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">geometry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">width&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">x&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">geometry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">height&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> @ (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">geometry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">,&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">geometry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;availableGeometry (逻辑像素): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">available_geometry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">width&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">x&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">available_geometry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">height&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 计算物理像素尺寸&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">physical_width&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">geometry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">width&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">screen_dpr&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">physical_height&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">geometry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">height&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">screen_dpr&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;物理像素 (计算): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">physical_width&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">x&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">physical_height&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">无法获取屏幕信息。&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info_display&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setText&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 更新自定义绘图区域，因为它依赖于 devicePixelRatio&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">drawing_widget&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">update&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 重写 showEvent，在窗口首次显示时查询信息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">showEvent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">event&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">super&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">showEvent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">initial_query_done&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_and_display_info&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">initial_query_done&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 重写 moveEvent，当窗口移动（可能移动到不同 DPI 的屏幕）时更新信息&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">moveEvent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">event&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">super&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">moveEvent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 只有在窗口可见时移动才更新，避免初始化时多次调用&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isVisible&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_and_display_info&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># --- 主程序入口 ---&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QApplication&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">main_window&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">MainWindow&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">main_window&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">show&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">app&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exec&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>代码解释&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;code>AA_&lt;/code> 属性设置&lt;/strong>：我们仍然保留了开头的 &lt;code>AA_EnableHighDpiScaling&lt;/code> 和 &lt;code>AA_UseHighDpiPixmaps&lt;/code> 设置，因为它们是让 Qt 框架自动处理大部分 UI 缩放的基础，推荐使用。&lt;/li>
&lt;li>&lt;strong>&lt;code>DrawingWidget&lt;/code>&lt;/strong>：这是一个自定义控件，重写了 &lt;code>paintEvent&lt;/code>。
&lt;ul>
&lt;li>在 &lt;code>paintEvent&lt;/code> 内部，我们首先通过 &lt;code>self.devicePixelRatioF()&lt;/code> 获取当前控件的设备像素比 &lt;code>ratio&lt;/code>。&lt;/li>
&lt;li>我们使用 &lt;code>QPainter&lt;/code> 进行绘图。&lt;code>QPainter&lt;/code> 的坐标系统默认是基于&lt;strong>逻辑像素&lt;/strong>的。当你调用 &lt;code>drawRect&lt;/code>, &lt;code>drawText&lt;/code> 等函数时，你提供的坐标和尺寸是逻辑单位。&lt;/li>
&lt;li>Qt 的渲染引擎在启用了高 DPI 缩放后，会自动将这些逻辑坐标映射到物理像素上进行绘制。因此，对于标准的控件和文本绘制，你通常&lt;strong>不需要&lt;/strong>手动乘以 &lt;code>ratio&lt;/code>。&lt;/li>
&lt;li>&lt;strong>手动缩放场景&lt;/strong>：示例中演示了如果你需要绘制一个具有&lt;strong>固定物理像素宽度&lt;/strong>的线条（例如 2 像素），你需要用物理宽度除以 &lt;code>ratio&lt;/code> 得到对应的逻辑宽度，然后设置给 &lt;code>QPen&lt;/code>。这是手动控制像素级细节的一个例子。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>&lt;code>MainWindow&lt;/code>&lt;/strong>：
&lt;ul>
&lt;li>&lt;code>query_and_display_info&lt;/code> 方法：
&lt;ul>
&lt;li>获取窗口自身的 &lt;code>devicePixelRatio()&lt;/code> 和 &lt;code>devicePixelRatioF()&lt;/code>。&lt;/li>
&lt;li>通过 &lt;code>self.screen()&lt;/code> 或 &lt;code>QGuiApplication.primaryScreen()&lt;/code> 获取当前的 &lt;code>QScreen&lt;/code> 对象。&lt;/li>
&lt;li>从 &lt;code>QScreen&lt;/code> 对象获取更详细的信息，如屏幕的 &lt;code>devicePixelRatio&lt;/code>, 逻辑 DPI, 物理 DPI, 几何尺寸（逻辑像素）等。&lt;/li>
&lt;li>计算并显示屏幕的物理像素尺寸。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>showEvent&lt;/code> 和 &lt;code>moveEvent&lt;/code>：重写这两个事件处理函数，确保在窗口首次显示或移动到新屏幕时，调用 &lt;code>query_and_display_info&lt;/code> 来更新显示的信息，并触发 &lt;code>DrawingWidget&lt;/code> 的重绘 (&lt;code>update()&lt;/code>)。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>总结&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>AA_EnableHighDpiScaling&lt;/code> 和 &lt;code>AA_UseHighDpiPixmaps&lt;/code> 是实现&lt;strong>自动&lt;/strong>高 DPI 适应性的关键属性，适用于大多数标准 UI 元素。&lt;/li>
&lt;li>&lt;code>QWidget.devicePixelRatio()&lt;/code>, &lt;code>QWidget.devicePixelRatioF()&lt;/code> 和 &lt;code>QScreen&lt;/code> 类及其方法允许你&lt;strong>查询&lt;/strong>当前的缩放比例和屏幕信息。&lt;/li>
&lt;li>查询到的 &lt;code>devicePixelRatio&lt;/code> 对于需要&lt;strong>手动控制像素级细节&lt;/strong>的场景（如自定义绘图、与需要物理像素坐标的库交互）非常有用。&lt;/li>
&lt;li>对于标准的 &lt;code>QPainter&lt;/code> 绘图操作，通常使用逻辑坐标即可，Qt 的自动缩放机制会处理好物理像素的映射。只有在需要精确控制物理尺寸或绘制像素对齐的图形时，才需要手动介入计算。&lt;/li>
&lt;/ul></description></item><item><title>PyQt-入门教程（AI生成）</title><link>https://www.zata.cc/p/pyqt-%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8Bai%E7%94%9F%E6%88%90/</link><pubDate>Thu, 24 Apr 2025 10:39:35 +0800</pubDate><guid>https://www.zata.cc/p/pyqt-%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8Bai%E7%94%9F%E6%88%90/</guid><description>&lt;img src="https://www.zata.cc/p/pyqt-%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8Bai%E7%94%9F%E6%88%90/images/index/index.png" alt="Featured image of post PyQt-入门教程（AI生成）" />&lt;h3 id="pyqt6-入门教程详细版本">PyQt6 入门教程（详细版本）
&lt;/h3>&lt;p>PyQt6 是一个用于创建桌面应用程序的 Python 库，它是 Qt 框架的 Python 绑定。Qt 是一个功能强大的跨平台框架，支持 GUI 开发、网络编程、数据库操作等。通过 PyQt6，你可以轻松地开发跨平台的桌面应用程序。&lt;/p>
&lt;p>本教程将从零开始，逐步引导你学习 PyQt6 的基本概念和使用方法。&lt;/p>
&lt;hr>
&lt;h2 id="一环境准备">一、环境准备
&lt;/h2>&lt;p>在开始之前，你需要确保你的开发环境已经安装了以下内容：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Python&lt;/strong>&lt;br>
确保你已经安装了 Python 3.6 或更高版本。可以通过以下命令检查：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">python --version
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>安装 PyQt6&lt;/strong>&lt;br>
使用 &lt;code>pip&lt;/code> 安装 PyQt6：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pip install PyQt6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>安装 PyQt6 工具（可选）&lt;/strong>&lt;br>
如果你想使用 Qt Designer（一个可视化设计工具），可以安装 &lt;code>pyqt6-tools&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pip install pyqt6-tools
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>安装完成后，可以在 &lt;code>Scripts&lt;/code> 目录下找到 &lt;code>designer.exe&lt;/code> 文件，启动它即可使用 Qt Designer。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="二第一个-pyqt6-程序">二、第一个 PyQt6 程序
&lt;/h2>&lt;p>让我们从一个简单的例子开始，创建一个窗口并显示它。&lt;/p>
&lt;h3 id="示例代码hello-world">示例代码：Hello World
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt6.QtWidgets&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">QApplication&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QWidget&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 创建主程序类&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MyApp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QWidget&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">super&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="fm">__init__&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">initUI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">initUI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 设置窗口标题&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setWindowTitle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Hello PyQt6&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 设置窗口大小&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setGeometry&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">400&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">300&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 显示窗口&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">show&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 创建应用实例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QApplication&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 创建窗口实例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">window&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">MyApp&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 进入主循环&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">app&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exec&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="代码解析">代码解析
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>导入模块&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>QApplication&lt;/code>: 管理应用程序的控制流和主要设置。&lt;/li>
&lt;li>&lt;code>QWidget&lt;/code>: 所有用户界面对象的基类。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>创建自定义类&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>MyApp&lt;/code> 继承自 &lt;code>QWidget&lt;/code>，我们在这里定义窗口的行为。&lt;/li>
&lt;li>&lt;code>__init__&lt;/code> 方法初始化窗口，并调用 &lt;code>initUI&lt;/code> 方法设置界面。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>设置窗口属性&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>setWindowTitle&lt;/code>: 设置窗口标题。&lt;/li>
&lt;li>&lt;code>setGeometry&lt;/code>: 设置窗口的位置和大小（x, y, width, height）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>显示窗口&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>调用 &lt;code>show()&lt;/code> 方法让窗口可见。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>主程序入口&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>创建 &lt;code>QApplication&lt;/code> 实例。&lt;/li>
&lt;li>创建窗口实例并进入主事件循环。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>运行上述代码后，你会看到一个标题为 &amp;ldquo;Hello PyQt6&amp;rdquo; 的窗口。&lt;/p>
&lt;hr>
&lt;h2 id="三添加控件">三、添加控件
&lt;/h2>&lt;p>在 PyQt6 中，你可以通过添加控件（如按钮、标签、文本框等）来丰富界面。&lt;/p>
&lt;h3 id="示例代码带按钮的窗口">示例代码：带按钮的窗口
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt6.QtWidgets&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">QApplication&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QWidget&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QPushButton&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QVBoxLayout&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QLabel&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MyApp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QWidget&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">super&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="fm">__init__&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">initUI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">initUI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 设置窗口标题和大小&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setWindowTitle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Button Example&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setGeometry&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">300&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 创建垂直布局&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QVBoxLayout&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 创建标签&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">label&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QLabel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Hello, PyQt6!&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">label&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 创建按钮&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">button&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QPushButton&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Click Me&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">button&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">clicked&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">connect&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">on_button_click&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 绑定点击事件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">button&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 设置布局&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setLayout&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">layout&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">on_button_click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 修改标签文本&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">label&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setText&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Button Clicked!&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QApplication&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">window&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">MyApp&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">window&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">show&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">app&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exec&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="代码解析-1">代码解析
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>控件介绍&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>QLabel&lt;/code>: 用于显示文本或图片。&lt;/li>
&lt;li>&lt;code>QPushButton&lt;/code>: 按钮控件。&lt;/li>
&lt;li>&lt;code>QVBoxLayout&lt;/code>: 垂直布局管理器，用于排列控件。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>事件绑定&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>button.clicked.connect(self.on_button_click)&lt;/code> 将按钮的点击事件与自定义方法 &lt;code>on_button_click&lt;/code> 绑定。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>动态更新界面&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>在 &lt;code>on_button_click&lt;/code> 方法中修改标签的文本内容。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>运行代码后，点击按钮会触发事件，标签的内容会变为 &amp;ldquo;Button Clicked!&amp;quot;。&lt;/p>
&lt;hr>
&lt;h2 id="四信号与槽机制">四、信号与槽机制
&lt;/h2>&lt;p>PyQt6 的核心之一是信号与槽机制（Signals and Slots）。信号是由控件发出的事件，槽是响应这些事件的函数。&lt;/p>
&lt;h3 id="示例代码信号与槽">示例代码：信号与槽
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt6.QtWidgets&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">QApplication&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QWidget&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QPushButton&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QLineEdit&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QVBoxLayout&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MyApp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QWidget&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">super&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="fm">__init__&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">initUI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">initUI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setWindowTitle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Signal and Slot Example&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setGeometry&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">300&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 创建垂直布局&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QVBoxLayout&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 创建输入框&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">input_box&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QLineEdit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">input_box&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 创建按钮&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">button&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QPushButton&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Show Text&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">button&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">clicked&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">connect&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">show_text&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 绑定点击事件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addWidget&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">button&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 设置布局&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setLayout&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">layout&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">show_text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 获取输入框内容并显示&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">input_box&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Input Text: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QApplication&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">window&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">MyApp&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">window&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">show&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">app&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exec&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="代码解析-2">代码解析
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>QLineEdit&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>用于接收用户输入的单行文本框。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>信号与槽&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>button.clicked.connect(self.show_text)&lt;/code> 将按钮的点击信号连接到 &lt;code>show_text&lt;/code> 方法。&lt;/li>
&lt;li>在 &lt;code>show_text&lt;/code> 方法中，通过 &lt;code>self.input_box.text()&lt;/code> 获取输入框的内容。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>运行代码后，在输入框中输入内容并点击按钮，控制台会打印出输入的文本。&lt;/p>
&lt;hr>
&lt;h2 id="五使用-qt-designer-设计界面">五、使用 Qt Designer 设计界面
&lt;/h2>&lt;p>对于复杂的界面，手动编写代码可能效率较低。这时可以使用 Qt Designer 来设计界面，然后将其转换为 Python 代码。&lt;/p>
&lt;h3 id="步骤">步骤
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>打开 Qt Designer&lt;/strong>&lt;br>
启动 &lt;code>designer.exe&lt;/code>，创建一个新的窗口或对话框。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>设计界面&lt;/strong>&lt;br>
拖拽控件到窗口中，设置控件属性。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>保存 &lt;code>.ui&lt;/code> 文件&lt;/strong>&lt;br>
将设计好的界面保存为 &lt;code>.ui&lt;/code> 文件。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>使用 &lt;code>pyuic6&lt;/code> 转换为 Python 代码&lt;/strong>&lt;br>
在终端中运行以下命令：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pyuic6 your_file.ui -o your_file.py
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>加载 &lt;code>.ui&lt;/code> 文件&lt;/strong>&lt;br>
也可以直接在代码中加载 &lt;code>.ui&lt;/code> 文件：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt6.uic&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">loadUi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">PyQt6.QtWidgets&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">QMainWindow&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">QApplication&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MainWindow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QMainWindow&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">super&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="fm">__init__&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">loadUi&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;your_file.ui&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QApplication&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">window&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">MainWindow&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">window&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">show&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">app&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exec&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="六总结">六、总结
&lt;/h2>&lt;p>通过本教程，你应该已经掌握了以下内容：&lt;/p>
&lt;ol>
&lt;li>如何安装 PyQt6 和相关工具。&lt;/li>
&lt;li>创建一个简单的窗口并添加控件。&lt;/li>
&lt;li>使用信号与槽机制处理用户交互。&lt;/li>
&lt;li>使用 Qt Designer 快速设计界面。&lt;/li>
&lt;/ol>
&lt;p>接下来，你可以尝试更复杂的项目，例如多窗口应用、数据绑定、文件操作等。PyQt6 提供了丰富的功能，适合开发各种类型的桌面应用程序。祝你学习愉快！&lt;/p></description></item><item><title>pyserial-使用教程</title><link>https://www.zata.cc/p/pyserial-%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/</link><pubDate>Thu, 03 Apr 2025 10:15:25 +0800</pubDate><guid>https://www.zata.cc/p/pyserial-%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/</guid><description>&lt;img src="https://www.zata.cc/p/pyserial-%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/images/index/index.svg" alt="Featured image of post pyserial-使用教程" />&lt;h2 id="基础教程">基础教程
&lt;/h2>&lt;h3 id="1-安装-pyserial">1. 安装 pyserial
&lt;/h3>&lt;p>首先，你需要安装 &lt;code>pyserial&lt;/code> 库。可以通过 pip 安装：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pip install pyserial
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h3 id="2-基本概念">2. 基本概念
&lt;/h3>&lt;p>串口通信（Serial Communication）是通过串行端口（如 USB 转串口设备、COM 端口等）进行数据传输的一种方式。常见用途包括与微控制器（如 Arduino）、传感器或其他硬件设备通信。&lt;/p>
&lt;p>在 Python 中，&lt;code>pyserial&lt;/code> 提供了一个简单的接口来操作串口。&lt;/p>
&lt;hr>
&lt;h3 id="3-基础代码示例">3. 基础代码示例
&lt;/h3>&lt;p>以下是一个简单的示例，展示如何打开串口、发送数据和接收数据：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">serial&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 配置串口参数&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">port&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;COM3&amp;#39;&lt;/span> &lt;span class="c1"># Windows 示例，Linux/Mac 可能是 &amp;#39;/dev/ttyUSB0&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">baudrate&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">9600&lt;/span> &lt;span class="c1"># 波特率，根据设备设置&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">timeout&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="c1"># 读取超时时间（秒）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 初始化串口&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ser&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">serial&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Serial&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">port&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">port&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">baudrate&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">baudrate&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">timeout&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;已连接到 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">port&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">except&lt;/span> &lt;span class="n">serial&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">SerialException&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;连接失败: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exit&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 发送数据&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Hello, Serial!&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="c1"># 将字符串编码为字节并发送&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;已发送: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 接收数据&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 等待一秒，确保有数据返回&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">in_waiting&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="c1"># 检查是否有数据在缓冲区&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">readline&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># 读取一行并解码&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;收到: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 关闭串口&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;串口已关闭&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h3 id="4-代码解释">4. 代码解释
&lt;/h3>&lt;ul>
&lt;li>&lt;strong>&lt;code>serial.Serial()&lt;/code>&lt;/strong>: 创建一个串口对象，参数包括端口号、波特率和超时时间。&lt;/li>
&lt;li>&lt;strong>&lt;code>port&lt;/code>&lt;/strong>: 串口名称。Windows 上是 &lt;code>COMx&lt;/code>（如 &lt;code>COM3&lt;/code>），Linux/Mac 上是 &lt;code>/dev/ttyUSBx&lt;/code> 或 &lt;code>/dev/ttySx&lt;/code>。&lt;/li>
&lt;li>&lt;strong>&lt;code>baudrate&lt;/code>&lt;/strong>: 数据传输速率，常见值有 9600、115200 等，需与设备一致。&lt;/li>
&lt;li>&lt;strong>&lt;code>timeout&lt;/code>&lt;/strong>: 读取超时，避免程序无限等待。&lt;/li>
&lt;li>&lt;strong>&lt;code>write()&lt;/code>&lt;/strong>: 发送数据，需将字符串编码为字节（如 &lt;code>encode('utf-8')&lt;/code>）。&lt;/li>
&lt;li>&lt;strong>&lt;code>readline()&lt;/code>&lt;/strong>: 读取一行数据（以换行符 &lt;code>\n&lt;/code> 结束）。&lt;/li>
&lt;li>&lt;strong>&lt;code>in_waiting&lt;/code>&lt;/strong>: 检查缓冲区是否有数据。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h3 id="5-如何找到串口号">5. 如何找到串口号
&lt;/h3>&lt;p>在连接设备后，你需要知道设备的串口号。可以用以下代码列出所有可用串口：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">serial.tools.list_ports&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ports&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">serial&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tools&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">list_ports&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">comports&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">port&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">ports&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;端口: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">port&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, 描述: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">port&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">description&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>运行后会显示类似：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">端口: COM3, 描述: USB Serial Port (COM3)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">端口: COM1, 描述: Communications Port (COM1)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>根据描述选择正确的端口。&lt;/p>
&lt;hr>
&lt;h3 id="6-常见问题与解决">6. 常见问题与解决
&lt;/h3>&lt;ul>
&lt;li>&lt;strong>端口被占用&lt;/strong>: 确保没有其他程序（如 Arduino IDE 的串口监视器）占用端口。&lt;/li>
&lt;li>&lt;strong>波特率不匹配&lt;/strong>: 确认波特率与设备一致。&lt;/li>
&lt;li>&lt;strong>无数据返回&lt;/strong>: 检查设备是否正确连接并发送数据。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h3 id="7-高级示例持续读取数据">7. 高级示例：持续读取数据
&lt;/h3>&lt;p>以下是一个循环读取串口数据的示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">serial&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ser&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">serial&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Serial&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;COM3&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">9600&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">in_waiting&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">readline&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;收到: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 短暂休眠，避免占用过多 CPU&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">except&lt;/span> &lt;span class="ne">KeyboardInterrupt&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;程序终止&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">finally&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;串口已关闭&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h3 id="8-与硬件交互示例如-arduino">8. 与硬件交互示例（如 Arduino）
&lt;/h3>&lt;p>假设 Arduino 运行以下代码：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">setup&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Serial&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">9600&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">loop&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Serial&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">available&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">String&lt;/span> &lt;span class="n">msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Serial&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">readString&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Serial&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">println&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;收到: &amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">msg&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Python 端可以这样与之交互：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">serial&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ser&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">serial&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Serial&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;COM3&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">9600&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 等待 Arduino 重启&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Test&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">in_waiting&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">readline&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 输出: 收到: Test&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h3 id="9-更多资源">9. 更多资源
&lt;/h3>&lt;ul>
&lt;li>官方文档: &lt;a class="link" href="https://pyserial.readthedocs.io/" target="_blank" rel="noopener"
>pyserial 文档&lt;/a>&lt;/li>
&lt;li>示例项目: 搜索 “Python serial Arduino” 可找到更多与硬件交互的案例。&lt;/li>
&lt;/ul>
&lt;h2 id="代码实战">代码实战
&lt;/h2>&lt;h3 id="发送命令随后接收数据校验重发">发送命令，随后接收数据，校验，重发
&lt;/h3>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-py" data-lang="py">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">set_current&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">port&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">current&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;设置镀膜电流&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">global_logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;开始设置镀膜电流 - 端口: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">port&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, 电流值: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">current&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ready&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">SerialReader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">port&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">port&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">baudrate&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">baudrate_global&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">command&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;CMD05,&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">current&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">global_logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;发送设置电流命令: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">command&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retry_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">max_retries&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">retry_count&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">max_retries&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ready&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">send_command&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">command&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">start_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start_time&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">response&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;CMD05&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">global_logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;设置镀膜电流成功 - 响应: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">expected_response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;CMD05,&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">current&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">expected_response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">global_logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;命令响应一致，设置成功&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">global_logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">warning&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;命令响应不一致 - 期望: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">expected_response&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, 实际: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 显示成功消息框&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messagebox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">showinfo&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;命令响应不一致&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; 期望: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">expected_response&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, 实际: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ready&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">read_data&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retry_count&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">retry_count&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">max_retries&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">global_logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">warning&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;设置镀膜电流失败 - 无响应&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item></channel></rss>