├── .github └── workflows │ └── mavenpublish.yml ├── LICENSE ├── README.md ├── comparasion.png ├── pom.xml ├── src └── main │ └── java │ └── ru │ └── krlvm │ └── swingdpi │ ├── CustomBootstrap.java │ ├── ScalableJFrame.java │ └── SwingDPI.java └── ui_defaults_list.txt /.github/workflows/mavenpublish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path 3 | 4 | name: Maven Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | packages: write 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | - name: Set up JDK 11 21 | uses: actions/setup-java@v2 22 | with: 23 | java-version: '11' 24 | distribution: 'adopt' 25 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 26 | settings-path: ${{ github.workspace }} # location for the settings.xml file 27 | 28 | - name: Build with Maven 29 | run: mvn -B package --file pom.xml 30 | 31 | - name: Publish to GitHub Packages Apache Maven 32 | run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml 33 | env: 34 | GITHUB_TOKEN: ${{ github.token }} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 krlvm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwingDPI 2 | Make using your Swing application convenient on HiDPI screens 3 | 4 | SwingDPI allows you to scale your application for convenient using on screens with high resolution (e.g. FullHD, 4K) 5 | 6 | You can download the latest build from `Releases` tab, supports Java 7 and later 7 | 8 | ![Swing application that running with SwingDPI compared with the same application without DPI scaling](https://raw.githubusercontent.com/krlvm/SwingDPI/master/comparasion.png "Swing application that running without DPI scaling compared with the same application running with SwingDPI") 9 | ###### Swing application that running with DPI-scaling compared with the same application without it 10 | 11 | ### Using in a project 12 | At first, you need to connect SwingDPI to your project. You can download .jar from the releases section and connect it to your project as a dependency, which will be extracted into your jarfile. After that, you can import SwingDPI API to your program loader class: `import ru.krlvm.swingdpi.SwingDPI` 13 | 14 | You also can add SwingDPI using Maven: 15 | ``` 16 | 17 | io.github.krlvm 18 | swingdpi 19 | 1.1.10 20 | 21 | ``` 22 | 23 | The easiest method of usage is adding this line to your loader code, before creating any frames: `SwingDPI.applyScalingAutomatically()` - SwingDPI automatically determine the system DPI scaling and apply it for your program - nothing more is needed. For more fine tuning you can play with `scale(dimension)` method that allow you to change frames and elements size depending on screen DPI. You can explore and edit the code for you according to your needs - source code is opened under the MIT license. 24 | 25 | ### Using outside a project 26 | You can scale existing Java Swing applications by modifying its .jar files. 27 | 28 | At first, open SwingDPI.jar and jar file of the application by an achiever (e.g., 7-zip) and copy contents of SwingDPI.jar to target application jar. 29 | 30 | Then open `MANIFEST.MF` of the combined JAR and look for parameter `Main-Class`. Create in the application folder a text file named `SwingDPI.txt` and fill it with `Main-Class` value, after that set `Main-Class` of the manifest to `ru.krlvm.swingdpi.CustomBootstrap`. 31 | 32 | The application should support DPI scaling now. 33 | -------------------------------------------------------------------------------- /comparasion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krlvm/SwingDPI/2a7a3044160b59c4c66ff2be84c70196d3efbbad/comparasion.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.github.krlvm 8 | swingdpi 9 | 1.2 10 | 11 | 12 | 1.6 13 | 1.6 14 | 15 | 16 | 17 | 18 | github 19 | GitHub Packages 20 | https://maven.pkg.github.com/krlvm/SwingDPI 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/ru/krlvm/swingdpi/CustomBootstrap.java: -------------------------------------------------------------------------------- 1 | package ru.krlvm.swingdpi; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileReader; 5 | import java.lang.reflect.Method; 6 | 7 | /** 8 | * SwingDPI Custom Bootstrap 9 | * 10 | * This class allows launching third-party Swing-based UI Java applications 11 | * with SwingDPI DPI scaling. Merge contents of this JAR with the your app JAR 12 | * and set Main-Class of the united JAR manifest to ru.krlvm.swingdpi.CustomBootstrap, 13 | * then create file SwingDPI.text in the program folder and write there initial 14 | * Main-Class of the manifest 15 | * 16 | * SwingDPI allows you to scale your application for convenient using on HiDPI screens 17 | * Call SwingDPI.applyScalingAutomatically() on your application start for easy scaling 18 | * GitHub Page: https://github.com/krlvm/SwingDPI 19 | * 20 | * @version 1.1 21 | * @author krlvm 22 | */ 23 | public class CustomBootstrap { 24 | 25 | public static void main(String[] args) throws Exception { 26 | SwingDPI.applyScalingAutomatically(); 27 | BufferedReader br = new BufferedReader(new FileReader("SwingDPI.txt")); 28 | StringBuilder sb = new StringBuilder(); 29 | String line = br.readLine(); 30 | while (line != null) { 31 | sb.append(line); 32 | line = br.readLine(); 33 | } 34 | br.close(); 35 | String main = sb.toString(); 36 | Class clazz = Class.forName(main); 37 | Method method = null; 38 | for (final Method clazzMethod : clazz.getMethods()) { 39 | if (clazzMethod.getName().equals("main")) { 40 | method = clazzMethod; 41 | } 42 | } 43 | if (method == null) { 44 | throw new Exception("Main method not found"); 45 | } 46 | method.invoke(null, (Object) args); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/ru/krlvm/swingdpi/ScalableJFrame.java: -------------------------------------------------------------------------------- 1 | package ru.krlvm.swingdpi; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | 6 | /** 7 | * SwingDPI Frame Scaler 8 | * 9 | * This class is an implementation of JFrame 10 | * Instead of creating/extending JFrame in your project use this class 11 | * and frame will be automatically scaled according to your SwingDPI API scale factor 12 | * 13 | * SwingDPI allows you to scale your application for convenient using on HiDPI screens 14 | * Call SwingDPI.applyScalingAutomatically() on your application start for easy scaling 15 | * GitHub Page: https://github.com/krlvm/SwingDPI 16 | * 17 | * @version 1.1 18 | * @author krlvm 19 | */ 20 | public class ScalableJFrame extends JFrame { 21 | 22 | public ScalableJFrame() throws HeadlessException { 23 | super(); 24 | } 25 | 26 | public ScalableJFrame(GraphicsConfiguration gc) { 27 | super(gc); 28 | } 29 | 30 | public ScalableJFrame(String title) throws HeadlessException { 31 | super(title); 32 | } 33 | 34 | public ScalableJFrame(String title, GraphicsConfiguration gc) { 35 | super(title, gc); 36 | } 37 | 38 | @Override 39 | public void setSize(Dimension d) { 40 | super.setSize(SwingDPI.scale(d)); 41 | } 42 | 43 | @Override 44 | public void setPreferredSize(Dimension preferredSize) { 45 | super.setPreferredSize(SwingDPI.scale(preferredSize)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/ru/krlvm/swingdpi/SwingDPI.java: -------------------------------------------------------------------------------- 1 | package ru.krlvm.swingdpi; 2 | 3 | import javax.swing.*; 4 | import javax.swing.plaf.FontUIResource; 5 | import java.awt.*; 6 | import java.awt.image.BufferedImage; 7 | import java.lang.reflect.Method; 8 | import java.util.*; 9 | import java.util.List; 10 | 11 | /** 12 | * SwingDPI API 13 | *

14 | * API of SwingDPI 15 | *

16 | * SwingDPI allows you to scale your application for convenient using on HiDPI screens 17 | * Call SwingDPI.applyScalingAutomatically() on your application start for easy scaling 18 | * GitHub Page: https://github.com/krlvm/SwingDPI 19 | * 20 | * @author krlvm 21 | */ 22 | public class SwingDPI { 23 | 24 | public static final String VERSION = "1.2"; 25 | 26 | //is scale factor set 27 | private static boolean scaleFactorSet = false; 28 | //the applied scale factor, e.g. 1.25 when the system DPI scaling is 125% 29 | private static float scaleFactor = 1.0f; 30 | //default scale factor, 100% scale 31 | private static final float DEFAULT_SCALE_FACTOR = 1.0f; 32 | //is DPI scale applied 33 | private static boolean scaleApplied = false; 34 | //exclude/whitelist defaults (something one) 35 | private static Set BLACKLISTED_DEFAULTS; 36 | private static Set WHITELISTED_DEFAULTS; 37 | // has the Java 9+ native scaling been disabled 38 | private static final boolean isJava9 = isJava9(); 39 | private static boolean java9ScalingDisabled = !isJava9; 40 | 41 | /** 42 | * Automatically determines scale factor and applies scaling for all existing and new windows 43 | * Java 9+ Native Scaling disables 44 | */ 45 | public static void applyScalingAutomatically() { 46 | applyScalingAutomatically(true); 47 | } 48 | 49 | /** 50 | * Automatically determines scale factor and applies scaling for all existing and new windows 51 | *

52 | * Java 9+ Native Scaling is very buggy and have a poor font rendering 53 | * If you don't want to disable the Java 9 Scaling, SwingDPI will not work 54 | * to avoid double scaling 55 | */ 56 | public static void applyScalingAutomatically(boolean disableJava9NativeScaling) { 57 | if (isJava9) { 58 | if (!disableJava9NativeScaling) { 59 | return; 60 | } else { 61 | disableJava9NativeScaling(); 62 | } 63 | } 64 | determineScaleFactor(); 65 | if (scaleFactor != DEFAULT_SCALE_FACTOR) { 66 | setScaleApplied(true); 67 | } 68 | } 69 | 70 | /** 71 | * Determines, sets the system DPI scaling setting and retrieves scale factor 72 | * Returns 1.0 if Java 9 scaling is preferred 73 | * 74 | * @return DPI scale factor 75 | */ 76 | public static float determineScaleFactor() { 77 | return isJava9 && !java9ScalingDisabled ? 1.0F : _determineScaleFactor(); 78 | } 79 | 80 | /** 81 | * Determines, sets the system DPI scaling setting and retrieves scale factor 82 | * 83 | * @return DPI scale factor 84 | */ 85 | public static float _determineScaleFactor() { 86 | float resolution = Toolkit.getDefaultToolkit().getScreenResolution(); //gets the screen resolution in percent, i.e. system DPI scaling 87 | if (resolution != 100.0f) { //when the system DPI scaling is not 100% 88 | setScaleFactor(resolution / 96.0f); //divide the system DPI scaling by default (100%) DPI and get the scale factor 89 | } 90 | return scaleFactor; 91 | } 92 | 93 | /** 94 | * Applies/disables scale for new and existing frames 95 | * 96 | * @param apply - enable or disable scaling 97 | */ 98 | public static void setScaleApplied(boolean apply) { 99 | setScaleApplied(apply, true); 100 | } 101 | 102 | /** 103 | * Applies/disables scale for new and the existing frames 104 | * 105 | * @param apply - enable or disable scaling 106 | * @param scaleExistingFrames - enable or disable scaling for existing frames 107 | */ 108 | public static void setScaleApplied(boolean apply, boolean scaleExistingFrames) { 109 | if (apply == scaleApplied) { 110 | return; // scale already applied/disabled 111 | } 112 | scaleApplied = apply; 113 | if (!apply) { 114 | setScaleFactor(1.0f); // after that, the scaling factor should be determined again 115 | } 116 | 117 | UIDefaults defaults = UIManager.getLookAndFeelDefaults(); // gets the Swing UI defaults - we will writing in them 118 | for (Object key : Collections.list(defaults.keys())) { // processing all default UI keys 119 | if(isWindowsLF() && Arrays.asList 120 | ( 121 | "RadioButtonMenuItem.font", 122 | "CheckBoxMenuItem.font", 123 | "MenuBar.font", 124 | "PopupMenu.font", 125 | "MenuItem.font", 126 | "Menu.font", 127 | "ToolTip.font" 128 | ).contains(key.toString())) { 129 | continue; 130 | } 131 | if (BLACKLISTED_DEFAULTS != null) { 132 | if (BLACKLISTED_DEFAULTS.contains(key.toString())) { 133 | continue; 134 | } 135 | } else if (WHITELISTED_DEFAULTS != null) { 136 | if (!WHITELISTED_DEFAULTS.contains(key.toString())) { 137 | continue; 138 | } 139 | } 140 | Object original = defaults.get(key); 141 | Object newValue = scale(key, original); 142 | if (newValue != null && newValue != original) { 143 | defaults.put(key, newValue); //updating defaults 144 | } 145 | } 146 | fixJOptionPaneIcons(); 147 | if (scaleExistingFrames) { 148 | for (Frame frame : Frame.getFrames()) { //gets all created frames 149 | if (!(frame instanceof JFrame)) { 150 | return; 151 | } 152 | Dimension dimension = frame.getSize(); 153 | frame.setSize(scale(dimension)); 154 | for (Component component : ((JFrame) frame).getContentPane().getComponents()) { 155 | dimension = component.getSize(); 156 | Dimension newDimension = scale(dimension); 157 | if (component instanceof JTextField) { 158 | component.setPreferredSize(newDimension); 159 | } else { 160 | component.setSize(newDimension); 161 | } 162 | } 163 | } 164 | } 165 | } 166 | 167 | /** 168 | * Retrieves a boolean that determines whether scaling is applied or not. 169 | * 170 | * @return is scaling applied 171 | */ 172 | public static boolean isScaleApplied() { 173 | return scaleApplied; 174 | } 175 | 176 | /** 177 | * Sets the scale factor 178 | * 179 | * @param scaleFactor - new scale factor 180 | */ 181 | public static void setScaleFactor(float scaleFactor) { 182 | disableJava9NativeScaling(); // avoid double scaling 183 | if (!scaleFactorSet) { 184 | scaleFactorSet = true; 185 | } 186 | SwingDPI.scaleFactor = scaleFactor; 187 | } 188 | 189 | /** 190 | * Retrieves the current scale factor 191 | * 192 | * @return scale factor 193 | */ 194 | public static float getScaleFactor() { 195 | if (!scaleFactorSet) { 196 | determineScaleFactor(); 197 | } 198 | return scaleFactor; 199 | } 200 | 201 | /** 202 | * Retrieves a scaled version of the param from Swing UI defaults 203 | * 204 | * @param key - param key 205 | * @param original - original value 206 | * @param scaleFactor - scale factor 207 | * @return a scaled param version 208 | */ 209 | private static Object scale(Object key, Object original, float scaleFactor) { 210 | if (original instanceof Font) { 211 | if (original instanceof FontUIResource && key.toString().endsWith(".font")) { 212 | int newSize = (int) (Math.round((float) ((Font) original).getSize()) * scaleFactor); 213 | return new FontUIResource(((Font) original).getName(), ((Font) original).getStyle(), newSize); 214 | } 215 | return original; 216 | } 217 | if (original instanceof Integer) { 218 | if (!endsWithOneOf((key instanceof String) ? ((String) key).toLowerCase() : "")) { 219 | return original; 220 | } 221 | return (int) ((Integer) original * scaleFactor); 222 | } 223 | return null; 224 | } 225 | 226 | /** 227 | * Retrieves a scaled version of the param from Swing UI defaults 228 | * 229 | * @param key - param key 230 | * @param original - original value 231 | * @return a scaled param version 232 | */ 233 | private static Object scale(Object key, Object original) { 234 | return scale(key, original, scaleFactor); 235 | } 236 | 237 | /** 238 | * Scales dimension 239 | * 240 | * @param dimension - dimension to scale 241 | * @return a scaled version of the dimension 242 | */ 243 | public static Dimension scale(Dimension dimension) { 244 | if (!scaleFactorSet) { 245 | return dimension; 246 | } 247 | dimension.setSize((int) (dimension.getWidth() * scaleFactor), (int) (dimension.getHeight() * scaleFactor)); 248 | return dimension; 249 | } 250 | 251 | /** 252 | * Retrieves a scaled version of a dimension 253 | * 254 | * @param dimension - dimension to scale 255 | * @return a scaled version of the dimension 256 | */ 257 | public static Dimension getScaledDimension(Dimension dimension) { 258 | if (!scaleFactorSet) { 259 | return dimension; 260 | } 261 | return new Dimension((int) (dimension.getWidth() * scaleFactor), (int) (dimension.getHeight() * scaleFactor)); 262 | } 263 | 264 | public static Dimension scale(int width, int height) { 265 | return scale(new Dimension(width, height)); 266 | } 267 | 268 | public static int scale(int i) { 269 | if (!scaleFactorSet) { 270 | return i; 271 | } 272 | return (int) (i * scaleFactor); 273 | } 274 | 275 | private static boolean endsWithOneOf(String text) { 276 | for (String suffix : new String[]{"width", "height", "indent", "size", "gap"}) { 277 | if (suffix.endsWith(text)) { 278 | return true; 279 | } 280 | } 281 | return false; 282 | } 283 | 284 | /** 285 | * Retrieves scaled version of dimension 286 | * The scaling algorithm is optimized for frame scaling 287 | * 288 | * @param dimension - dimension to scale 289 | * @return a scaled version of the dimension 290 | */ 291 | public static Dimension scaleFrame(Dimension dimension) { 292 | if (!scaleFactorSet) { 293 | return dimension; 294 | } 295 | return scale((int) (dimension.width - (dimension.width * .2)), (int) (dimension.height - (dimension.height * .15))); 296 | } 297 | 298 | /** 299 | * If font of specific component did not scaled automatically use this method 300 | * 301 | * @param component - component for scale 302 | */ 303 | public static void scaleFont(Component component) { 304 | setFontSize(component, component.getFont().getSize()); 305 | } 306 | 307 | public static void setFontSize(Component component, float size) { 308 | Font font = component.getFont(); 309 | component.setFont(font.deriveFont(size * scaleFactor)); 310 | } 311 | 312 | // https://stackoverflow.com/questions/33926645/joptionpane-icon-gets-cropped-in-windows-10 313 | private static void fixJOptionPaneIcons() { 314 | if (!isWindowsLF() || isJava9 || (scaleFactor != 1.25 && scaleFactor != 1.5)) return; 315 | try { 316 | String[][] icons = { 317 | {"OptionPane.warningIcon", "65581"}, 318 | {"OptionPane.questionIcon", "65583"}, 319 | {"OptionPane.errorIcon", "65585"}, 320 | {"OptionPane.informationIcon", "65587"} 321 | }; 322 | 323 | //obtain a method for creating proper icons 324 | Method getIconBits = Class.forName("sun.awt.shell.Win32ShellFolder2").getDeclaredMethod("getIconBits", long.class, int.class); 325 | getIconBits.setAccessible(true); 326 | int icon32Size = (scaleFactor == 1) ? (32) : ((scaleFactor == 1.25) ? (40) : ((scaleFactor == 1.5) ? (45) : ((int) (32 * scaleFactor)))); 327 | Object[] arguments = {null, icon32Size}; 328 | for (String[] s : icons) { 329 | if (UIManager.get(s[0]) instanceof ImageIcon) { 330 | arguments[0] = Long.valueOf(s[1]); 331 | //this method is static, so the first argument can be null 332 | int[] iconBits = (int[]) getIconBits.invoke(null, arguments); 333 | if (iconBits != null) { 334 | //create an image from the obtained array 335 | BufferedImage img = new BufferedImage(icon32Size, icon32Size, BufferedImage.TYPE_INT_ARGB); 336 | img.setRGB(0, 0, icon32Size, icon32Size, iconBits, 0, icon32Size); 337 | ImageIcon newIcon = new ImageIcon(img); 338 | //override previous icon with the new one 339 | UIManager.put(s[0], newIcon); 340 | } 341 | } 342 | } 343 | } catch (Exception ex) { 344 | ex.printStackTrace(); 345 | } 346 | } 347 | 348 | /** 349 | * Exclude some UI Defaults from scaling (blacklist) 350 | * 351 | * @param toExclude - UI Defaults to exclude 352 | * @throws IllegalStateException - if UI Defaults is in whitelist mode 353 | */ 354 | public static void excludeDefaults(Collection toExclude) { 355 | if (WHITELISTED_DEFAULTS != null) { 356 | throw new IllegalStateException("UI Defaults is in whitelist mode"); 357 | } 358 | if (BLACKLISTED_DEFAULTS == null) { 359 | BLACKLISTED_DEFAULTS = new HashSet(); 360 | } 361 | BLACKLISTED_DEFAULTS.addAll(toExclude); 362 | } 363 | 364 | /** 365 | * Exclude some UI Defaults from scaling (blacklist) 366 | * 367 | * @param toExclude - UI Defaults to exclude 368 | * @throws IllegalStateException - if UI Defaults is in whitelist mode 369 | */ 370 | public static void excludeDefaults(String... toExclude) { 371 | excludeDefaults(Arrays.asList(toExclude)); 372 | } 373 | 374 | /** 375 | * Allow to scale only specified UI Defaults (whitelist) 376 | * 377 | * @param toWhitelist - UI Defaults to whitelist 378 | * @throws IllegalStateException - if UI Defaults is in blacklist mode 379 | */ 380 | public static void whitelistDefaults(Collection toWhitelist) { 381 | if (BLACKLISTED_DEFAULTS != null) { 382 | throw new IllegalStateException("UI Defaults is in blacklist mode"); 383 | } 384 | if (WHITELISTED_DEFAULTS == null) { 385 | WHITELISTED_DEFAULTS = new HashSet(); 386 | } 387 | WHITELISTED_DEFAULTS.addAll(toWhitelist); 388 | } 389 | 390 | /** 391 | * Allow to scale only specified UI Defaults (whitelist) 392 | * 393 | * @param toWhitelist - UI Defaults to whitelist 394 | * @throws IllegalStateException - if UI Defaults is in blacklist mode 395 | */ 396 | public static void whitelistDefaults(String... toWhitelist) { 397 | whitelistDefaults(Arrays.asList(toWhitelist)); 398 | } 399 | 400 | public static void disableJava9NativeScaling() { 401 | if (isJava9) { 402 | System.setProperty("sun.java2d.uiScale", "1.0"); 403 | System.setProperty("glass.win.uiScale", "100%"); 404 | System.setProperty("prism.allowhidpi", "false"); 405 | java9ScalingDisabled = true; 406 | } 407 | } 408 | 409 | public static boolean isLegacyScalingEnabled() { 410 | return !java9ScalingDisabled; 411 | } 412 | 413 | // or greater 414 | public static boolean isJava9() { 415 | return !System.getProperty("java.specification.version").startsWith("1."); 416 | } 417 | private static boolean isWindowsLF() { 418 | return UIManager.getLookAndFeel().getClass().getName().equals("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); 419 | } 420 | } -------------------------------------------------------------------------------- /ui_defaults_list.txt: -------------------------------------------------------------------------------- 1 | List.font 2 | TableHeader.font 3 | Panel.font 4 | TextArea.font 5 | ToggleButton.font 6 | ComboBox.font 7 | ScrollPane.font 8 | Spinner.font 9 | RadioButtonMenuItem.font 10 | Slider.font 11 | EditorPane.font 12 | OptionPane.font 13 | ToolBar.font 14 | Tree.font 15 | CheckBoxMenuItem.font 16 | TitledBorder.font 17 | Table.font 18 | MenuBar.font 19 | PopupMenu.font 20 | Label.font 21 | MenuItem.font 22 | TextField.font 23 | TextPane.font 24 | CheckBox.font 25 | ProgressBar.font 26 | FormattedTextField.font 27 | ColorChooser.font 28 | Menu.font 29 | PasswordField.font 30 | Viewport.font 31 | TabbedPane.font 32 | RadioButton.font 33 | ToolTip.font 34 | Button.font 35 | --------------------------------------------------------------------------------