You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

macOS Monterey下使用Python3实现无弹窗屏幕亮度调节的方案问询

如何在macOS Monterey下无弹窗调节屏幕亮度(Python实现)

我完全理解你的困扰——模拟亮度按键的方式虽然简单,但每次弹出的系统弹窗确实会打断用户操作。针对macOS Monterey的界面变化,我给你提供几种可行的解决方案,都能实现无弹窗调节亮度,同时不影响用户手动调节时的弹窗显示:

方法1:使用第三方命令行工具brightness(最简单)

这是最省心的方案,brightness是专门用于调节屏幕亮度的命令行工具,完全不会触发系统弹窗。

步骤:

  1. 先通过Homebrew安装工具:
brew install brightness
  1. 在Python中调用该工具:
import subprocess

# 设置亮度为0.5(范围0.0到1.0,0是最暗,1是最亮)
def set_display_brightness(value):
    # -d 0 指定第一个显示器,如果有多个显示器可以调整这个数字
    subprocess.run(["brightness", "-d", "0", "-v", str(value)], check=True)

# 示例:降低亮度到当前值的80%
# 先获取当前亮度
current_brightness = float(subprocess.check_output(["brightness", "-d", "0", "-l"]).split()[-1])
set_display_brightness(current_brightness * 0.8)

方法2:适配Monterey的AppleScript(无需额外工具)

你之前的AppleScript失效是因为Monterey重新设计了Displays偏好设置的UI结构——窗口标题、控件层级都变了。以下是适配后的版本,记得加延迟等待界面加载:

import subprocess

def adjust_brightness(step):
    # step为正数是增加亮度,负数是降低,建议步长0.0625(对应系统的一格亮度)
    scpt = f'''
    tell application "System Preferences"
        reveal pane "com.apple.preference.displays"
        delay 0.5  # 必须等界面加载完成,否则会找不到控件
    end tell

    tell application "System Events"
        tell process "System Preferences"
            tell window "Displays"
                tell tab group 1
                    tell group 1
                        set current_brightness to value of slider 1
                        set new_brightness to clamp(current_brightness + {step}, 0.0, 1.0)
                        set value of slider 1 to new_brightness
                    end tell
                end tell
            end tell
        end tell
    end tell

    quit application "System Preferences"
    '''
    subprocess.run(['osascript', '-e', scpt])

# 示例:降低一格亮度
adjust_brightness(-0.0625)

注:clamp函数是AppleScript的内置函数,用来限制亮度值在0-1之间,避免超出范围报错。

方法3:用PyObjC直接调用系统框架(最底层稳定)

这种方法直接和macOS的IOKit系统框架交互,完全绕过用户界面,是最稳定无依赖的方案,也不会有任何弹窗:

import objc
from Foundation import NSBundle, NSNumber

# 加载IOKit系统框架
IOKit = NSBundle.bundleWithIdentifier_('com.apple.IOKit')
if not IOKit:
    raise RuntimeError("Could not load IOKit framework")

# 映射需要的系统函数
function_map = [
    ("IOServiceGetMatchingService", b"II@"),
    ("IOServiceMatching", b"@*"),
    ("IOServiceSetCFProperty", b"I@@@"),
]

objc.loadBundleFunctions(IOKit, globals(), function_map)

def set_brightness(brightness_value):
    # 获取显示器服务对象
    display_service = IOServiceGetMatchingService(0, IOServiceMatching("IODisplayConnect"))
    if not display_service:
        raise RuntimeError("Could not get display service")
    
    # 将亮度值转为NSNumber类型(系统要求的格式)
    brightness = NSNumber.numberWithFloat_(brightness_value)
    # 设置亮度
    result = IOServiceSetCFProperty(display_service, "Brightness", brightness)
    if result != 0:
        raise RuntimeError("Failed to set brightness")
    
    # 释放资源
    objc.retainAutoreleasedReturnValue(display_service)

# 示例:设置亮度为0.6
set_brightness(0.6)

为什么这些方法不会触发弹窗?

系统的亮度调节弹窗是**响应UI事件(比如按键、滑块拖动)**才会显示的,而上面的方法:

  • 方法1和3直接修改系统底层的亮度参数,不走UI交互路径;
  • 方法2虽然操作了偏好设置的滑块,但通过脚本操作不会触发系统的UI事件监听逻辑,所以也不会弹出窗口。

而用户手动调节时,因为是通过物理按键或拖动滑块的UI操作,所以弹窗会正常显示,完全不冲突。

内容的提问来源于stack exchange,提问作者HerrAlvé

火山引擎 最新活动