mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 22:10:54 +03:00
HiDPI: introduced (optional) repaint manager that fixes incomplete component paintings at 125% or 175% scaling on Windows (issues #860 and #582)
This commit is contained in:
@@ -26,6 +26,7 @@ import java.awt.geom.AffineTransform;
|
|||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.text.AttributedCharacterIterator;
|
import java.text.AttributedCharacterIterator;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.RepaintManager;
|
||||||
import com.formdev.flatlaf.FlatSystemProperties;
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -377,6 +378,9 @@ public class HiDPIUtils
|
|||||||
// Also RepaintManager "merges" the two repaints into one.
|
// Also RepaintManager "merges" the two repaints into one.
|
||||||
c.repaint( x, y, width, height );
|
c.repaint( x, y, width, height );
|
||||||
|
|
||||||
|
if( RepaintManager.currentManager( c ) instanceof HiDPIRepaintManager )
|
||||||
|
return;
|
||||||
|
|
||||||
// if necessary, also repaint given area in first ancestor that is larger than component
|
// if necessary, also repaint given area in first ancestor that is larger than component
|
||||||
// to avoid clipping issue (see needsSpecialRepaint())
|
// to avoid clipping issue (see needsSpecialRepaint())
|
||||||
if( needsSpecialRepaint( c, x, y, width, height ) ) {
|
if( needsSpecialRepaint( c, x, y, width, height ) ) {
|
||||||
@@ -485,4 +489,79 @@ public class HiDPIUtils
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs a {@link HiDPIRepaintManager} on Windows when running in Java 9+,
|
||||||
|
* but only if default repaint manager is currently installed.
|
||||||
|
* <p>
|
||||||
|
* Invoke once on application startup.
|
||||||
|
* Compatible with all/other L&Fs.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static void installHiDPIRepaintManager() {
|
||||||
|
if( !SystemInfo.isJava_9_orLater || !SystemInfo.isWindows )
|
||||||
|
return;
|
||||||
|
|
||||||
|
RepaintManager manager = RepaintManager.currentManager( (Component) null );
|
||||||
|
if( manager.getClass() == RepaintManager.class )
|
||||||
|
RepaintManager.setCurrentManager( new HiDPIRepaintManager() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to {@link #repaint(Component, int, int, int, int)},
|
||||||
|
* but invokes callback instead of invoking {@link Component#repaint(int, int, int, int)}.
|
||||||
|
* <p>
|
||||||
|
* For use in custom repaint managers.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static void addDirtyRegion( JComponent c, int x, int y, int width, int height, DirtyRegionCallback callback ) {
|
||||||
|
if( needsSpecialRepaint( c, x, y, width, height ) ) {
|
||||||
|
int x2 = x + c.getX();
|
||||||
|
int y2 = y + c.getY();
|
||||||
|
for( Component p = c.getParent(); p != null; p = p.getParent() ) {
|
||||||
|
x2 += p.getX();
|
||||||
|
y2 += p.getY();
|
||||||
|
if( x2 + width < p.getWidth() && y2 + height < p.getHeight() && p instanceof JComponent ) {
|
||||||
|
callback.addDirtyRegion( (JComponent) p, x2, y2, width, height );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.addDirtyRegion( c, x, y, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- interface DirtyRegionCallback --------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For {@link HiDPIUtils#addDirtyRegion(JComponent, int, int, int, int, DirtyRegionCallback)}.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public interface DirtyRegionCallback {
|
||||||
|
void addDirtyRegion( JComponent c, int x, int y, int w, int h );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class HiDPIRepaintManager ------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repaint manager that fixes a problem in Swing when repainting components
|
||||||
|
* at some scale factors (e.g. 125%, 175%, etc) on Windows.
|
||||||
|
* <p>
|
||||||
|
* Use {@link HiDPIUtils#installHiDPIRepaintManager()} to install it.
|
||||||
|
* <p>
|
||||||
|
* See {@link HiDPIUtils#repaint(Component, int, int, int, int)} for details.
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static class HiDPIRepaintManager
|
||||||
|
extends RepaintManager
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void addDirtyRegion( JComponent c, int x, int y, int w, int h ) {
|
||||||
|
HiDPIUtils.addDirtyRegion( c, x, y, w, h, super::addDirtyRegion );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,9 @@ public class FlatLafDemo
|
|||||||
// use Roboto Mono font
|
// use Roboto Mono font
|
||||||
// FlatLaf.setPreferredMonospacedFontFamily( FlatRobotoMonoFont.FAMILY );
|
// FlatLaf.setPreferredMonospacedFontFamily( FlatRobotoMonoFont.FAMILY );
|
||||||
|
|
||||||
|
// install own repaint manager to fix repaint issues at 125%, 175%, 225%, ... on Windows
|
||||||
|
// HiDPIUtils.installHiDPIRepaintManager();
|
||||||
|
|
||||||
// application specific UI defaults
|
// application specific UI defaults
|
||||||
FlatLaf.registerCustomDefaultsSource( "com.formdev.flatlaf.demo" );
|
FlatLaf.registerCustomDefaultsSource( "com.formdev.flatlaf.demo" );
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ public class FlatHiDPITest
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HiDPIUtils.installHiDPIRepaintManager();
|
||||||
|
|
||||||
FlatLaf.setGlobalExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
FlatLaf.setGlobalExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
||||||
FlatLightLaf.setup();
|
FlatLightLaf.setup();
|
||||||
|
|
||||||
@@ -124,6 +126,8 @@ public class FlatHiDPITest
|
|||||||
y += 20;
|
y += 20;
|
||||||
addAtProblematicXY( 0, y, 16, 40, 20, "JScrollBar", () -> new JScrollBar( JScrollBar.VERTICAL ) );
|
addAtProblematicXY( 0, y, 16, 40, 20, "JScrollBar", () -> new JScrollBar( JScrollBar.VERTICAL ) );
|
||||||
y += 60;
|
y += 60;
|
||||||
|
addAtProblematicXY( 0, y, 82, 60, 88, "JScrollPane", () -> new JScrollPane( new JTree() ) );
|
||||||
|
y += 80;
|
||||||
addAtProblematicXY( 0, y, 80, 16, 88, "JProgressBar", () -> {
|
addAtProblematicXY( 0, y, 80, 16, 88, "JProgressBar", () -> {
|
||||||
JProgressBar c = new JProgressBar();
|
JProgressBar c = new JProgressBar();
|
||||||
c.setValue( 60 );
|
c.setValue( 60 );
|
||||||
@@ -138,7 +142,7 @@ public class FlatHiDPITest
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
frame.getContentPane().add( testPanel );
|
frame.getContentPane().add( testPanel );
|
||||||
frame.setSize( 400, 300 );
|
frame.setSize( 400, 400 );
|
||||||
frame.setVisible( true );
|
frame.setVisible( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user