Extra-length combo-box popup sizing and positioning in multi-screen environment
See original GitHub issueFlatScreenInfo
Scale factors: 125% / 150%
Java version: 11.0.7
ID: \Display0 (main)
Size: 1920 x 1080 / 32 Bit / 60 Hz
Bounds: 1536 x 864 / x 0 / y 0 (scale -1.25)
Insets: left 0 / right 0 / top 0 / bottom 50
Scale: 1.25
ID: \Display1
Size: 1920 x 1080 / 32 Bit / 60 Hz
Bounds: 1280 x 720 / x -1280 / y -50 (scale -1.5)
Insets: left 0 / right 0 / top 0 / bottom 0
Scale: 1.5
Using the following sample program:
//package ;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.GraphicsConfiguration;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.MetalTheme;
@SuppressWarnings("serial")
public class ComboBoxTest extends JFrame {
private Container mainPane;
private JLabel scaleLabel;
public ComboBoxTest() {
super("Combo-box test");
add(initMainPanel(), BorderLayout.CENTER);
add(initStatusBar(), BorderLayout.PAGE_END);
}
private Container initMainPanel() {
JComboBox<String> history = new JComboBox<>();
history.addItem(randomItem(50));
history.addItem(randomItem(500));
history.addItem(randomItem(100));
JComponent main = new JPanel(new BorderLayout());
main.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
main.add(history, BorderLayout.PAGE_START);
mainPane = main;
return main;
}
private static String randomItem(int maxLength) {
StringBuilder buf = new StringBuilder(maxLength + 10);
buf.append(randomWord());
while (buf.length() < maxLength) {
buf.append(' ').append(randomWord());
}
return buf.toString();
}
private static String randomWord() {
final int length = (int) (Math.random() * 5 + 5);
StringBuilder buf = new StringBuilder(length);
for (int i = 0; i < length; i++) {
buf.append((char) (Math.random() * 26 + 'a'));
}
return buf.toString();
}
private Component initStatusBar() {
LookAndFeel lnf = UIManager.getLookAndFeel();
String lnfLabel = "Look and Feel: " + lnf.getName();
if (lnf instanceof MetalLookAndFeel) {
lnfLabel += " / " + MetalLookAndFeel.getCurrentTheme().getName();
}
scaleLabel = new JLabel();
updateScaleLabel();
addPropertyChangeListener("graphicsConfiguration", evt -> updateScaleLabel());
JComponent status = Box.createHorizontalBox();
status.add(new JLabel(lnfLabel));
status.add(new JLabel(", "));
status.add(scaleLabel);
status.add(Box.createHorizontalGlue());
return status;
}
void updateScaleLabel() {
GraphicsConfiguration gc = getGraphicsConfiguration();
if (gc == null) {
scaleLabel.setText("Scale: ?");
} else {
AffineTransform defaultTransform = gc.getDefaultTransform();
Set<Double> factors = new LinkedHashSet<>(1);
factors.add(defaultTransform.getScaleX());
factors.add(defaultTransform.getScaleY());
scaleLabel.setText("Scale: " + factors);
}
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(() -> {
setLookAndFeel(args.length > 0 ? args[0] : null);
ComboBoxTest frame = new ComboBoxTest();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setSize(frame.getFont().getSize() * 50, frame.getHeight());
frame.setLocation(new Point(0, 0));
frame.mainPane.requestFocusInWindow();
frame.setVisible(true);
});
}
static void setLookAndFeel(String param) {
if (param == null)
return;
String lnfClassName, themeClassName;
switch (param.toLowerCase()) {
case "ocean":
lnfClassName = "javax.swing.plaf.metal.MetalLookAndFeel";
themeClassName = "javax.swing.plaf.metal.OceanTheme";
break;
case "steel":
lnfClassName = "javax.swing.plaf.metal.MetalLookAndFeel";
themeClassName = "javax.swing.plaf.metal.DefaultMetalTheme";
break;
case "nimbus":
lnfClassName = "javax.swing.plaf.nimbus.NimbusLookAndFeel";
themeClassName = null;
break;
case "flatlaf":
lnfClassName = "com.formdev.flatlaf.FlatLightLaf";
themeClassName = null;
break;
case "plastic":
lnfClassName = "com.jgoodies.looks.plastic.Plastic3DLookAndFeel";
themeClassName = "com.jgoodies.looks.plastic.theme.SkyBluer";
break;
case "system":
lnfClassName = UIManager.getSystemLookAndFeelClassName();
themeClassName = null;
break;
case "default":
lnfClassName = UIManager.getCrossPlatformLookAndFeelClassName();
themeClassName = null;
break;
default:
return;
}
try {
if (themeClassName != null) {
MetalLookAndFeel.setCurrentTheme((MetalTheme) Class
.forName(themeClassName).getConstructor().newInstance());
}
UIManager.setLookAndFeel(lnfClassName);
} catch (LinkageError | ReflectiveOperationException | UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
}
java -cp flatlaf-0.42.jar ComboBoxTest.java flatlaf
Moving the application window to the left (secondary) monitor, then opening the combo-box popup – the popup is misaligned, using the resolution/scaling of the right (main) monitor and extends across the right monitor end:
In my opinion, the popup should not extend across monitors.
Not sure if it is related, I’m noticing – without the extra-length item:
history.addItem(randomItem(50));
history.addItem(randomItem(75));
history.addItem(randomItem(100));
when moving the application window between monitors (<kbd>Win+Shift+Left/Right-Arrow</kbd>), the first time the combo popup is opened it is shown at a weird position:
The second time the popup is opened it is aligned/positioned as expected.
Issue Analytics
- State:
- Created 3 years ago
- Comments:5
Top Results From Across the Web
JavaFX ComboBox: Pop-up is getting shifted when screen is ...
My primary screen is FHD and secondary is 2K. So if I set the 2K monitor as primary the combobox is popping up...
Read more >Combobox changing size when popup open #4551 - GitHub
Describe the bug Hi, The ComboBox loses value and changes a width when the popup was opened. Please, take a look at the...
Read more >How to Use the Multi-Display Function on Windows 10 - Eizo
In the “System > Display” menu the screen position, display size (enlargement ratio), display orientation, display method of the multi-display, and main/sub ...
Read more >Wrong popup position on dual screen in Linux : JBR-3388
Arranging the relative positions of the 2 monitors in settings makes a difference, so I managed to get a decent balance of popup...
Read more >keeping popups on a single monitor in a dual ... - QuickBooks
Open your QuickBooks Desktop. Once the pop up screen comes up, move & drag it to the main monitor. At the top menu...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
If the taskbar/dock is at the bottom, Swing changes the location of combobox popup so that the popup never overlaps the taskbar/dock. So I think it should also not overlap the taskbar/dock if it is on the right or left side.
Thank you. I saw the change and wondered if screen insets should be considered (as is currently) for a popup. Maybe it is o.k. as the insets might be occupied by an always-on-top window which might show even on top of the popup.