feat(ui): 设置页支持启用/禁用 TUN 并改进默认字体回退

- 设置页新增「启用虚拟网卡 (TUN)」复选框;未启用时隐藏虚拟网卡名称输入框,
  显示橙色警告"⚠️ TUNTAP 未启用:虚拟网卡未挂载",保存时写入 TUNName=null
- 勾选后恢复名称输入框,留空自动填入默认值 KLALB_SRv6
- 控制台同步输出英文警告:禁用时 "WARNING: TUNTAP is disabled..."、
  挂载失败时 "WARNING: Failed to mount TUN adapter..."
- UIEnv 默认字体改为按平台探测回退:
  雅黑/PingFang/Noto 等候选 → 系统 Label.font → Java Dialog 逻辑字体
This commit is contained in:
2026-08-22 00:12:56 +08:00
parent 455139dfe9
commit 9c5a81da25
5 changed files with 85 additions and 12 deletions
+2
View File
@@ -92,6 +92,8 @@ transmitnagledelaytime=Transmit nagle delay time
linknagledelaytime=Link nagle delay time
linkconnectionscount=Link connections count
tunname=Virtual network device name
enabletun=Enable TUN device
tundisabledwarning=⚠️ TUNTAP is disabled: Virtual network device not mounted
dashboard=Dashboard
backplanedelay=Backplane delay
backplanepps=Backplane PPS
+2
View File
@@ -92,6 +92,8 @@ transmitnagledelaytime=传输粘包等待时间
linknagledelaytime=链路粘包等待时间
linkconnectionscount=链路连接数
tunname=虚拟网卡名称
enabletun=启用虚拟网卡 (TUN)
tundisabledwarning=⚠️ TUNTAP 未启用:虚拟网卡未挂载
dashboard=仪表盘
backplanedelay=背板处理延迟
backplanepps=背板包转发率
@@ -661,12 +661,13 @@ public class KLALBController {
} catch (Exception e) {
System.err.println("挂载虚拟网卡失败,可能是无管理员权限?请尝试使用管理员权限运行软件");
System.err.println("WARNING: Failed to mount TUN adapter (requires administrator privileges)");
e.printStackTrace();
}
});
t.start();
}else {
System.out.println(" Tun Adapter Disabled");
System.out.println(" WARNING: TUNTAP is disabled: Virtual network device not mounted");
}
udpr=new UDPProtocolRegister(this);
@@ -98,6 +98,9 @@ public class KLALBStateGUI3 extends XFrame {
private JCheckBox denyQuery;
private ClosableTabbedPane tabbedPane; // 可关闭的标签页面板
private JCheckBox nogui;
private JCheckBox enableTun;
private TextSettingItem tunNameItem;
private SettingItem tunWarningItem;
// ==================== 配置和回调 ====================
private KLALBConfig config; // 配置文件
@@ -820,10 +823,29 @@ public class KLALBStateGUI3 extends XFrame {
asnFieldSet = asn.getTextField();
settings.getView().add(asn);
TextSettingItem tunName = new TextSettingItem(UIEnv.getRsb().getString("tunname"),
// 启用虚拟网卡 (TUN)
CheckBoxSettingItem enableTunc = new CheckBoxSettingItem(UIEnv.getRsb().getString("enabletun"),
CONST.itemwidth, CONST.settingheight);
enableTun = enableTunc.getCheckBox();
settings.getView().add(enableTunc);
tunNameItem = new TextSettingItem(UIEnv.getRsb().getString("tunname"),
CONST.itemwidth, CONST.settingheight);
tunDeviceName = tunName.getTextField();
settings.getView().add(tunName);
tunDeviceName = tunNameItem.getTextField();
settings.getView().add(tunNameItem);
tunWarningItem = new SettingItem(UIEnv.getRsb().getString("tundisabledwarning"),
UIEnv.getFont().deriveFont(13.0f), CONST.itemwidth, CONST.settingheight);
tunWarningItem.getLabel().setForeground(new Color(220, 80, 0));
settings.getView().add(tunWarningItem);
enableTun.addActionListener(e -> {
boolean en = enableTun.isSelected();
if (en && (tunDeviceName.getText().trim().isEmpty() || tunDeviceName.getText().trim().equalsIgnoreCase("null"))) {
tunDeviceName.setText(CONST.KLALB_S_RV6);
}
updateTunVisibility(en);
});
// 链接设置标题
SettingItem six = new SettingItem(UIEnv.getRsb().getString("linksettings"),
@@ -1026,6 +1048,19 @@ public class KLALBStateGUI3 extends XFrame {
delayLbound.getSlider().addChangeListener(cll);
}
private void updateTunVisibility(boolean enabled) {
if (tunNameItem != null) {
tunNameItem.setVisible(enabled);
}
if (tunWarningItem != null) {
tunWarningItem.setVisible(!enabled);
}
if (yspc != null && yspc.getView() != null) {
yspc.getView().revalidate();
yspc.getView().repaint();
}
}
// ==================== 配置保存方法 ====================
/**
* 保存配置到文件
@@ -1134,11 +1169,16 @@ public class KLALBStateGUI3 extends XFrame {
}
}
String tunNameText=tunDeviceName.getText().trim();
if(tunNameText.equals("") || tunNameText.equalsIgnoreCase("null")) {
kck.setTUNName(null);
}else {
kck.setTUNName(tunNameText);
// 保存TUN虚拟网卡设置
if (!enableTun.isSelected()) {
kck.setTUNName(null);
} else {
String tunNameText = tunDeviceName.getText().trim();
if (tunNameText.equals("") || tunNameText.equalsIgnoreCase("null")) {
kck.setTUNName(CONST.KLALB_S_RV6);
} else {
kck.setTUNName(tunNameText);
}
}
// 保存TCP监听设置
@@ -1539,7 +1579,10 @@ public class KLALBStateGUI3 extends XFrame {
asnFieldSet.setText(vasn != null ? vasn.toString() : "");
String tunname=kck.getTUNName();
tunDeviceName.setText(tunname!=null?tunname:"");
boolean isTunActive = (tunname != null && !tunname.trim().isEmpty() && !tunname.trim().equalsIgnoreCase("null"));
enableTun.setSelected(isTunActive);
tunDeviceName.setText(isTunActive ? tunname.trim() : "");
updateTunVisibility(isTunActive);
// 加载TCP监听
MultiProtocolSocketAddress mpat = kck.getTCPListen();
+27 -2
View File
@@ -80,7 +80,7 @@ public class UIEnv {
// TODO 自动生成的 catch 块
e.printStackTrace();
}*/
font=new Font("微软雅黑",Font.PLAIN , 12);
font = pickDefaultFont(12);
/*try {
font = Font.createFont(Font.PLAIN, UIEnv.class.getResourceAsStream("/assets/SourceHanSansCN-Light.otf")).deriveFont(13f);
} catch (FontFormatException e1) {
@@ -117,7 +117,32 @@ public class UIEnv {
start.setFont(font.deriveFont(Font.BOLD, fontsize));
start.setBackground(defaultcolor);
}
public static Font getFont(){
private static Font pickDefaultFont(int size) {
String[] preferredFonts = new String[] {
"Microsoft YaHei UI", "Microsoft YaHei", "微软雅黑",
"PingFang SC", ".AppleSystemUIFont", "Helvetica Neue",
"Noto Sans CJK SC", "Source Han Sans SC", "WenQuanYi Micro Hei",
"Segoe UI", "Arial"
};
try {
String[] available = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
java.util.Set<String> set = new java.util.HashSet<>(java.util.Arrays.asList(available));
for (String name : preferredFonts) {
if (set.contains(name)) {
return new Font(name, Font.PLAIN, size);
}
}
} catch (Throwable t) {
// fallback in case of headless or security restrictions
}
Font sysFont = UIManager.getFont("Label.font");
if (sysFont != null) {
return sysFont.deriveFont(Font.PLAIN, (float) size);
}
return new Font(Font.DIALOG, Font.PLAIN, size);
}
public static Font getFont(){
if(icon==null)
inituie();
return font;