JEditorPaneのStyleSheetをLight・Darkテーマに合わせて切り替える
Total: 44
, Today: 11
, Yesterday: 33
Posted by aterai at
Last-modified:
Summary
JEditorPane
のStyleSheet
を起動時のシステムテーマがLight
かDark
かなどに応じて切り替えるよう設定します。
Screenshot

Advertisement
Source Code Examples
public static void updateTheme(JEditorPane editor) {
updateTheme(editor, isDarkMode());
}
public static void updateTheme(JEditorPane editor, boolean isDark) {
EditorKit kit = editor.getEditorKit();
HTMLEditorKit htmlEditorKit;
if (kit instanceof HTMLEditorKit) {
htmlEditorKit = (HTMLEditorKit) kit;
} else {
htmlEditorKit = new HTMLEditorKit();
}
if (isDark) {
htmlEditorKit.setStyleSheet(makeDarkStyleSheet());
editor.setBackground(new Color(0x1E_1F_22));
} else {
htmlEditorKit.setStyleSheet(makeLightStyleSheet());
editor.setBackground(new Color(0xEE_EE_EE));
}
editor.setEditorKit(htmlEditorKit);
}
public static boolean isDarkMode() {
boolean isDark;
String os = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
if (os.contains("windows")) {
isDark = isWindowsDarkMode();
} else if (os.contains("linux")) {
isDark = isLinuxDarkMode();
} else if (os.contains("mac")) {
isDark = isMackDarkMode();
} else {
isDark = false;
}
return isDark;
}
public static String getProcessOutput(String... cmd)
throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder(cmd);
builder.redirectErrorStream(true);
Process p = builder.start();
String str;
try (BufferedReader pr = new BufferedReader(
new InputStreamReader(p.getInputStream()))) {
str = pr.lines().collect(Collectors.joining(System.lineSeparator()));
}
return str;
}
public static boolean isWindowsDarkMode() {
String[] cmd = {
"powershell.exe",
"Get-ItemPropertyValue",
"-Path",
"HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
"-Name",
"AppsUseLightTheme;"
};
boolean isDarkMode;
try {
String str = getProcessOutput(cmd).trim();
isDarkMode = Objects.equals("0", str);
} catch (IOException | InterruptedException ex) {
Logger.getGlobal().severe(ex::getMessage);
isDarkMode = false;
}
return isDarkMode;
}
public static boolean isLinuxDarkMode() {
Toolkit tk = Toolkit.getDefaultToolkit();
Object theme = tk.getDesktopProperty("gnome.Net/ThemeName");
return Objects.toString(theme).contains("dark");
}
public static boolean isMackDarkMode() {
return false;
}
// https://raw.githack.com/google/code-prettify/master/styles/index.html
// Prettify Themes Gallery
public static StyleSheet makeLightStyleSheet() {
StyleSheet styleSheet = new StyleSheet();
styleSheet.addRule("pre{background:#eeeeee}");
styleSheet.addRule(".str{color:#008800}");
styleSheet.addRule(".kwd{color:#000088}");
styleSheet.addRule(".com{color:#880000}");
styleSheet.addRule(".typ{color:#660066}");
styleSheet.addRule(".lit{color:#006666}");
styleSheet.addRule(".pun{color:#666600}");
styleSheet.addRule(".pln{color:#000000}");
styleSheet.addRule(".tag{color:#000088}");
styleSheet.addRule(".atn{color:#660066}");
styleSheet.addRule(".atv{color:#008800}");
styleSheet.addRule(".dec{color:#660066}");
return styleSheet;
}
public static StyleSheet makeDarkStyleSheet() {
StyleSheet styleSheet = new StyleSheet();
styleSheet.addRule("pre{background:#1e1f22}");
styleSheet.addRule(".str{color:#ffa0a0}");
styleSheet.addRule(".kwd{color:#f0e68c;font-weight:bold}");
styleSheet.addRule(".com{color:#87ceeb}");
styleSheet.addRule(".typ{color:#98fb98}");
styleSheet.addRule(".lit{color:#cd5c5c}");
styleSheet.addRule(".pun{color:#ffffff}");
styleSheet.addRule(".pln{color:#ffffff}");
styleSheet.addRule(".tag{color:#f0e68c;font-weight:bold}");
styleSheet.addRule(".atn{color:#bdb76b;font-weight:bold}");
styleSheet.addRule(".atv{color:#ffa0a0}");
styleSheet.addRule(".dec{color:#98fb98}");
return styleSheet;
}
View in GitHub: Java, KotlinExplanation
OS
がWindows
の場合、個人用設定の色をライト、ダークで切り替えてもSwing
アプリ側でそのイベントを取得できないWindows 7
などではDesktopPropertyの変更を監視するのようにToolkit
にPropertyChangeListener
を追加することで画面の配色変更を取得可能だったが、Windows 10
やWindows 11
では動作しない?- このサンプルでは、起動時や
JRadioButtonMenuItem
でテーマを手動切り替えしたときに、レジストリからHKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize
の値を取得して0
の場合はDark
テーマと判断し、StyleSheet
の切り替えを実行 - Detector: A plain Java class that offers some utility methods to detect dark theme on MacOS and Windows · GitHub
OS
がLinux(Ubuntu+gnome)
の場合、設定の外観、スタイルをデフォルト(ライト)、ダークで切り替えると、Swing
アプリ側でもそのイベントを取得可能GTKLookAndFeel
はデフォルトでスタイル切り替えが発生するとSynthTheme
を切り替えて各コンポーネントの配色を変更している- 以下のように、
Toolkit
にデスクトッププロパティをgnome.Net/ThemeName
としてPropertyChangeListener
を追加すればスタイル切り替えイベントを取得可能なので、テーマ名にdark
が含まれる場合はDark
テーマと判断し、StyleSheet
の切り替えを実行String key = "gnome.Net/ThemeName"; Toolkit.getDefaultToolkit().addPropertyChangeListener(key, e -> { if (sys.isSelected()) { boolean isDark = Objects.toString(e.getNewValue()).contains("dark"); ThemeUtils.updateTheme(editor, isDark); loadHtml(editor); } });
OS
がMac
の場合には、このサンプルは未対応だが、以下のサイトの方法で対応可能
Reference
- Dansoftowner/jSystemThemeDetector: Java library for detecting that the (desktop) operating system uses dark UI theme or not
- Detector: A plain Java class that offers some utility methods to detect dark theme on MacOS and Windows · GitHub
- Prettify Themes Gallery
- DesktopPropertyの変更を監視する