![修复基于 Java 的应用程序在高 DPI 屏幕上的缩放问题](https://linux22.com/image/862285/%E4%BF%AE%E5%A4%8D%E5%9F%BA%E4%BA%8E%20Java%20%E7%9A%84%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E5%9C%A8%E9%AB%98%20DPI%20%E5%B1%8F%E5%B9%95%E4%B8%8A%E7%9A%84%E7%BC%A9%E6%94%BE%E9%97%AE%E9%A2%98.png)
有些应用程序(主要是基于 Java 的)不遵循全球 2 倍规模我在屏幕设置中设置。所以这些应用程序真的微小的在我的 3200x1800px 高 DPI 屏幕上。
如何才能让这些应用程序在较小的屏幕分辨率下运行?
答案1
测试添加到您的 java 命令行:-Dsun.java2d.uiScale=2.0
,或将其设置为您想要的比例因子。
答案2
一个主要的便利升级是使用后台脚本,自动设置分辨率每个应用程序,同时您可以一次为不同的(多个)应用程序设置不同的分辨率。
这正是下面的脚本所做的。
一个例子默认分辨率1680x1050
:
正在运行gedit
,自动更改为640x480
:
正在运行gnome-terminal
,自动更改为1280x1024
:
当应用程序关闭时,分辨率会自动设置回1680x1050
如何使用
- 将以下脚本复制到一个空文件中,并将其另存为
set_resolution.py
在脚本的头部,设置默认分辨率,在以下行:
#--- set the default resolution below default = "1680x1050" #---
在同一目录(文件夹),创建一个文本文件,确切地命名:
procsdata.txt
。在此文本文件中,设置所需的应用程序或进程,后跟一个空格,后跟所需的分辨率。每行一个应用程序或脚本,如下所示:gedit 640x480 gnome-terminal 1280x1024 java 1280x1024
通过以下命令运行脚本:
python3 /path/to/set_resolution.py
笔记
脚本使用pgrep -f <process>
,捕获所有匹配项,包括脚本。可能的缺点是,当打开与进程同名的文件时,它可能会导致名称冲突。
如果您遇到此类问题,请更改:
matches.append([p, subprocess.check_output(["pgrep", "-f", p]).decode("utf-8")])
进入:
matches.append([p, subprocess.check_output(["pgrep", p]).decode("utf-8")])
剧本
#!/usr/bin/env python3
import subprocess
import os
import time
#--- set the default resolution below
default = "1680x1050"
#---
# read the datafile
curr_dir = os.path.dirname(os.path.abspath(__file__))
datafile = curr_dir+"/procsdata.txt"
procs_data = [l.split() for l in open(datafile).read().splitlines() if not l == "\n"]
procs = [pdata[0] for pdata in procs_data]
def check_matches():
# function to find possible running (listed) applications
matches = []
for p in procs:
try:
matches.append([p, subprocess.check_output(["pgrep", "-f", p]).decode("utf-8")])
except subprocess.CalledProcessError:
pass
match = matches[-1][0] if len(matches) != 0 else None
return match
matches1 = check_matches()
while True:
time.sleep(2)
matches2 = check_matches()
if matches2 == matches1:
pass
else:
if matches2 != None:
# a listed application started up since two seconds ago
resdata = [("x").join(item[1].split("x")) for item in \
procs_data if item[0] == matches2][0]
elif matches2 == None:
# none of the listed applications is running any more
resdata = default
subprocess.Popen(["xrandr", "-s", resdata])
matches1 = matches2
time.sleep(1)
解释
当脚本启动时,它会读取您定义应用程序及其相应的所需屏幕分辨率的文件。
然后,它会密切关注正在运行的进程(pgrep -f <process>
针对每个应用程序运行),并在应用程序启动时设置分辨率。
当pgrep -f <process>
不为任何列出的应用程序产生输出时,它会将分辨率设置为“默认”。
编辑:
“动态”版本(根据要求)
虽然上述版本适用于多个列出的应用程序,但它只设置了一次一个应用程序。
以下版本可以处理同时运行的不同应用程序,这些应用程序具有不同的(所需)分辨率。后台脚本将跟踪最前面的应用程序,并相应地设置分辨率。它也可以与Alt+配合使用Tab。
请注意,如果您在桌面和列出的应用程序之间频繁切换,这种行为可能会令人烦恼;频繁的分辨率切换可能会太多。
设置方式的差异
除了使用wmctrl
和之外,设置几乎相同xdotool
:
sudo apt-get install wmctrl
sudo apt-get install xdotool
剧本
#!/usr/bin/env python3
import subprocess
import os
import sys
import time
#--- set default resolution below
resolution = "1680x1050"
#---
curr_dir = os.path.dirname(os.path.abspath(__file__))
datafile = curr_dir+"/procsdata.txt"
applist = [l.split() for l in open(datafile).read().splitlines()]
apps = [item[0] for item in applist]
def get(cmd):
try:
return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
except subprocess.CalledProcessError:
pass
def get_pids():
# returns pids of listed applications; seems ok
runs = []
for item in apps:
pid = get("pgrep -f "+item)
if pid != None:
runs.append((item, pid.strip()))
return runs
def check_frontmost():
# returns data on the frontmost window; seems ok
frontmost = str(hex(int(get("xdotool getwindowfocus").strip())))
frontmost = frontmost[:2]+"0"+frontmost[2:]
try:
wlist = get("wmctrl -lpG").splitlines()
return [l for l in wlist if frontmost in l]
except subprocess.CalledProcessError:
pass
def front_pid():
# returns the frontmost pid, seems ok
return check_frontmost()[0].split()[2]
def matching():
# nakijken
running = get_pids(); frontmost = check_frontmost()
if all([frontmost != None, len(running) != 0]):
matches = [item[0] for item in running if item[1] == frontmost[0].split()[2]]
if len(matches) != 0:
return matches[0]
else:
pass
trigger1 = matching()
while True:
time.sleep(1)
trigger2 = matching()
if trigger2 != trigger1:
if trigger2 == None:
command = "xrandr -s "+resolution
else:
command = "xrandr -s "+[it[1] for it in applist if it[0] == trigger2][0]
subprocess.Popen(["/bin/bash", "-c", command])
print(trigger2, command)
trigger1 = trigger2
笔记
- 虽然我已经运行了几个小时,没有出现任何错误,但请彻底测试它。如果可能出现错误,请发表评论。
- 该脚本 - 就其本身而言 - 适用于单个显示器设置。
答案3
对于 Linux:
sudo nano /etc/environment
添加以下内容:
JAVA_TOOL_OPTIONS=-Dsun.java2d.uiScale=2
... 最好使用 METAL 外观和感觉,因为 GTK+ 也遵循 Gnome 的一些缩放。
答案4
解决方法
我创建了一个 bash 脚本,在启动应用程序(在这个例子中是 Android Studio)之前将分辨率更改为 fullHD,并在应用程序退出时将其更改回 3200x1800:
sudo nano /usr/local/bin/studio
输入此脚本:
#!/bin/bash
# set scaling to x1.0
gsettings set org.gnome.desktop.interface scaling-factor 1
gsettings set com.ubuntu.user-interface scale-factor "{'HDMI1': 8, 'eDP1': 8}"
xrandr -s 1920x1080
# call your program
/usr/share/android-studio/data/bin/studio.sh
# set scaling to x2.0
gsettings set org.gnome.desktop.interface scaling-factor 2
gsettings set com.ubuntu.user-interface scale-factor "{'HDMI1': 8, 'eDP1': 16}"
xrandr -s 3200x1800
并赋予其可执行权限:
sudo chmod +x /usr/local/bin/studio
Alt然后你可以用+来启动它F1 studio
对于 2.0 的其他调整大小因子,请参见https://askubuntu.com/a/486611/34298
为了方便在 Firefox 中打开或关闭缩放,请使用扩展程序缩放菜单元素