jformdesigner / flatlaf Goto Github PK
View Code? Open in Web Editor NEWFlatLaf - Swing Look and Feel (with Darcula/IntelliJ themes support)
Home Page: https://www.formdev.com/flatlaf/
License: Apache License 2.0
FlatLaf - Swing Look and Feel (with Darcula/IntelliJ themes support)
Home Page: https://www.formdev.com/flatlaf/
License: Apache License 2.0
I am using FlatDarculaLaf with version 0.14 from Maven, and I noticed that the tooltips of disabled buttons are using a bright yellow background and dark text, and this attracts the eye, while anything disabled should not attract it. The "real" Darcula from Intellij uses the same colors for tooltips of disabled buttons as for the enabled ones, and this is OK.
BTW the "real" Darcula has cool little triangles in the tooltip shapes pointing to the original mouse location, while FlatDarculaLaf doesn't have them, but this is not so important.
I want to use toggle buttons like tabs so I set the underline type. I also increase the size of the underline. The problem is that the line is too close from the text and I don't know if there is a way to have a taller button when the style is underline (something similar to the "TabbedPane.tabHeight" property).
Here is an example comparing tabs and toggle buttons:
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(new FlatLightLaf());
UIDefaults defaults = UIManager.getDefaults();
defaults.put("ToggleButton.underline.underlineHeight", 3);
defaults.put("TabbedPane.tabSelectionHeight", 3);
defaults.put("TabbedPane.tabHeight", 22);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel centerPane = new JPanel(new BorderLayout());
JToolBar toolBar = new JToolBar();
toolBar.setFloatable(false);
ButtonGroup buttonGroup = new ButtonGroup();
JToggleButton button1 = new JToggleButton("My first button");
button1.setSelected(true);
button1.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_UNDERLINE);
buttonGroup.add(button1);
toolBar.add(button1);
JToggleButton button2 = new JToggleButton("My second button");
button2.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_UNDERLINE);
buttonGroup.add(button2);
toolBar.add(button2);
centerPane.add(toolBar, BorderLayout.NORTH);
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
tabbedPane.addTab("My first tab", new JPanel());
tabbedPane.addTab("My second tab", new JPanel());
centerPane.add(tabbedPane);
frame.getContentPane().add(centerPane);
frame.setSize(400, 300);
frame.setVisible(true);
}
I know TabScroller is private on BasicTabPaneUI but is there any hope of possibly getting rid of it? In your excellent look and feel this is one of the few things that detracts from the moderness and throws us back to old java L&Fs. I hate it completely.
Whenn adding the line "FlatLightLaf.install();" to my java-classes, I receiv the error
"cannot find symbol
symbol: variable FlatLightLaf
location: class CarolaHartmannMilesVerlag"
although I addes the jar-file to my classpath.
I am using Netbeans 11.00.
What do I missing?
Kind regards
Thomas
All text controls use light text color under dark theme except for JEditorPane
The headline says it all: Is there a smooth scrolling feature which comes with the FlatLaf out of the box? When I use NetBeans with a nb-darcula theme for example the scrolling jumps to a specific number of rows. It is fixed. This features was implemented into NetBeans (one specific LaF) out of the box. It would be nice, if the FlatLaF will have it, if not :)
Cheers
Chris
Current implementation of smooth scrolling (issue #27) works only with trackpads or when the mouse (driver) supports high-resolution wheels. Otherwise the scroll area "jumps" some lines up or down.
The buttons don't seem to have real transparency at the corners and borders. Instead of the content behind them the panel color can be seen - this is only OK in simple cases when a button is on a panel.
In the following zoomed-in picture the red arrows indicate the problem areas. Here two buttons are placed on top of each other using a JLayeredPane in order to indicate the foreground and background colors that can be chosen. Such opaque areas don't appear when using Nimbus. Also the Intellij widgets have real transparency, this can be seen if you set a background picture in Idea.
Using 0.16 and FlatDarculaLaf, buttons have a grey color when the mouse is over them, which is OK when there is no background color set for the button, but looks quite strange (sudden large color changes) when there is an explicitly set background color.
Instead the rollover color should be derived from the background color (if there is one), for example using a lighter or darker version of it (or leaving it as it is). java.awt.Color has brighter() and darker() methods for easily deriving such colors at runtime.
import com.formdev.flatlaf.FlatDarculaLaf;
import javax.swing.*;
import java.awt.Color;
import java.awt.FlowLayout;
public class ColoredButtonProblem {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> buildGUI());
}
private static void buildGUI() {
try {
// UIManager.setLookAndFeel(new javax.swing.plaf.nimbus.NimbusLookAndFeel());
UIManager.setLookAndFeel(new FlatDarculaLaf());
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setLayout(new FlowLayout());
JButton blueButton = new JButton("Blue");
blueButton.setBackground(new Color(13, 67, 159));
f.add(blueButton);
JButton uncoloredButton = new JButton("No color, no problem");
f.add(uncoloredButton);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
...for people who have eyesight deficiency
A Java security policy file would be helpful for those who want to give the demo program a quick try but are reluctant to run software from outside their normal trusted sources. The security policy lets you run the demo under the Java Security Manager with each permission granted explicitly.
The security policy that works for the demo program is:
grant codeBase "file:///${user.home}/Downloads/flatlaf-demo-0.18.jar" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.swing";
permission java.lang.RuntimePermission "getenv.KDE_FULL_SESSION";
permission java.lang.RuntimePermission "preferences";
permission java.util.PropertyPermission "apple.awt.graphics.UseQuartz", "read";
permission java.util.PropertyPermission "flatlaf.uiScale", "read";
permission java.util.PropertyPermission "hidpi", "read";
permission java.util.PropertyPermission "sun.java2d.uiScale", "read";
};
You can run the demo under the Security Manager with a command like the following:
$ java -Djava.security.manager -Djava.security.policy=flatlaf.policy \
-jar flatlaf-demo-0.18.jar
I suggest providing the file in the repository so that people can use it if they want. Otherwise, it's tedious to create because you have to go through each security exception one by one.
I am using version 0.13 from Maven. The following code illustrates the problem:
public class HTMLProblem {
public static void main(String[] args) {
SwingUtilities.invokeLater(HTMLProblem::runOnEDT);
}
private static void runOnEDT() {
try {
// UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
UIManager.setLookAndFeel("com.formdev.flatlaf.FlatDarculaLaf");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
String msg = "<html>I like <b>bold</b>,"
+ "<br> and I like <i>italic</i>,"
+ "<br> and I like to have"
+ "<br> many lines."
+ "<br> Lots of lines.";
JOptionPane.showMessageDialog(null, msg);
}
}
Here's the result, notice how at the end HTML tags are not interpreted anymore:
While playing with the demo application and choosing some Intellij Themes the following errors were print on the terminal:
Failed to parse: 'MenuBar.borderColor=##1a1721'
invalid color '##1a1721'
Failed to parse: 'CheckBoxMenuItem.disabledBackground=#darkBackground'
invalid color '#darkBackground'
Failed to parse: 'CompletionPopup.matchForeground=#42A5F52'
invalid color '#42A5F52'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#42A5F52'
invalid color '#42A5F52'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#2979ff2'
invalid color '#2979ff2'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#2979ff2'
invalid color '#2979ff2'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#2979ff2'
invalid color '#2979ff2'
Failed to parse: 'List.selectionInactiveBackground=#DBDBDC8025'
invalid color '#DBDBDC8025'
Failed to parse: 'Table.selectionInactiveBackground=#DBDBDC8025'
invalid color '#DBDBDC8025'
Failed to parse: 'Tree.selectionInactiveBackground=#DBDBDC8025'
invalid color '#DBDBDC8025'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#2979ff2'
invalid color '#2979ff2'
Failed to parse: 'List.selectionInactiveBackground=#DBDBDC8025'
invalid color '#DBDBDC8025'
Failed to parse: 'Table.selectionInactiveBackground=#DBDBDC8025'
invalid color '#DBDBDC8025'
Failed to parse: 'Tree.selectionInactiveBackground=#DBDBDC8025'
invalid color '#DBDBDC8025'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#FF79C52'
invalid color '#FF79C52'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#FF79C52'
invalid color '#FF79C52'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#79CB602'
invalid color '#79CB602'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#79CB602'
invalid color '#79CB602'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#2693862'
invalid color '#2693862'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
Failed to parse: 'CompletionPopup.matchForeground=#d336822'
invalid color '#d336822'
Failed to parse: 'Viewport.foreground=#%fc'
invalid color '#%fc'
It seems the included *.theme.json
files contain wrong color definitions or missing color references.
I understand that maybe these should be reported to the original authors of the themes.
Under FlatLaf, components change style on mouse hover: buttons get a different border, tabs get a gray background, etc. It makes the application feel "alive" too.
Menus do not react and feel "dead". I think they should get a gray background, like tabs.
I also wonder if an "tab" style would be appropriate, like toggle buttons.
Simple test case of a menu bar:
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(new FlatLightLaf());
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
JMenu menu1 = new JMenu("Menu 1");
menu1.setMnemonic('m');
JMenuItem subMenu1_1 = new JMenuItem("Sub Menu 1.1");
subMenu1_1.setMnemonic('s');
menu1.add(subMenu1_1);
menuBar.add(menu1);
JMenu menu2 = new JMenu("Menu 2");
menu2.setMnemonic('n');
JMenuItem subMenu2_1 = new JMenuItem("Sub Menu 2.1");
subMenu2_1.setMnemonic('u');
menu2.add(subMenu2_1);
menuBar.add(menu2);
frame.setJMenuBar(menuBar);
frame.setContentPane(new JScrollPane(new JTextArea()));
frame.setSize(400, 300);
frame.setVisible(true);
}
I am using version 0.13 from Maven. The following code throws StackOverflowError apparently because of an infinite loop. As I explained in the comments, this can be reproduced only if pack is not called.
import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatIntelliJLaf;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Window;
public class UpdateComponentTreeProblem {
public static void main(String[] args) {
SwingUtilities.invokeLater(UpdateComponentTreeProblem::runOnEDT);
}
private static void runOnEDT() {
setLaf(new FlatDarculaLaf());
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setLayout(new BorderLayout());
JComboBox<String> themeChooser = new JComboBox<>(new String[]{"Light", "Dark"});
themeChooser.setName("themeChooser");
themeChooser.setSelectedItem("Dark");
themeChooser.addActionListener(e -> {
String themeName = (String) themeChooser.getSelectedItem();
if(themeName.equals("Light")) {
setLaf(new FlatIntelliJLaf());
}
});
f.add(themeChooser, BorderLayout.NORTH);
f.add(new JLabel("Change the theme to \"Light\"!"));
// In order to reproduce the problem,
// it is crucial NOT to call pack().
// In a real app the window size could be read
// from the saved preferences and set manually.
// f.pack();
f.setSize(600, 400);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static void setLaf(LookAndFeel laf) {
try {
UIManager.setLookAndFeel(laf);
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
Window[] windows = Window.getWindows();
for (Window window : windows) {
SwingUtilities.updateComponentTreeUI(window);
}
}
}
I am subclassing BasicTreeUI and calling setUI on JTree very simply with no change to the default cell renderer.
(Kotlin)
override fun paintRow(
g: Graphics, clipBounds: Rectangle, insets: Insets, bounds: Rectangle,
path: TreePath, row: Int, isExpanded: Boolean, hasBeenExpanded: Boolean, isLeaf: Boolean
) {
if (tree.isRowSelected(row)) {
g.color = if (tree.hasFocus()) ColorUtil.hex2Rgb("#2f65ca") else ColorUtil.hex2Rgb("#0d293e")
g.fillRect(0, row * tree.rowHeight, tree.width, tree.rowHeight)
}
super.paintRow(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf)
super.paintExpandControl(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf)
}
I see you have a UIDefault "Tree.wideSelection", but its not selecting the entire row for me (maybe I did something wrong) so Im not sure if thats what its intent was.
Is there any way to bake this in to the L&F? Its a common thing, its not hard to do with subclassing but could save folks some time.
Mnemonics on Mac are very unusual and should be hidden by default.
IntelliJ/Darcula LaFs hide mnemonics on all platforms and show them only when Alt is pressed.
(bug report split from issue #11)
Internal frame decorations are not correct for FlatLaf.
Here is a simple test case:
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(new FlatLightLaf());
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JDesktopPane desktopPane = new JDesktopPane();
JInternalFrame internalFrame = new JInternalFrame("Test", true, true, true, true);
internalFrame.setLocation(50, 30);
internalFrame.setSize(300, 200);
desktopPane.add(internalFrame);
frame.getContentPane().add(desktopPane);
frame.setSize(400, 300);
frame.setVisible(true);
internalFrame.setVisible(true);
}
Hi,
I have a toggle button on which the background and foreground colors are forced, but it paints as if these were not set. It seems the code in Flat*ButtonUI does not get the background from the component even though they were explicitly set.
Am I missing something?
PS: very good work, I am impressed by the quality of FlatLaf!
besides the currently used triangle arrows, also support chevron arrows
When resizing the table column automatically (i.e. not AUTO_RESIZE_OFF), you do not paint the last column separator of the table header. This is a good thing I think.
Now, if we display the table vertical lines, the cells do paint the last vertical line, which is odd.
Here is a test case:
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(new FlatLightLaf());
UIDefaults defaults = UIManager.getDefaults();
defaults.put("Table.showVerticalLines", Boolean.TRUE);
defaults.put("Table.showHorizontalLines", Boolean.TRUE);
defaults.put("Table.intercellSpacing", new Dimension(1, 1));
defaults.put("Table.gridColor", new Color(0xd9d9d9));
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel centerPane = new JPanel(new BorderLayout());
centerPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JTable table = new JTable(new Object[][] { { "Cell 1_1", "Cell 1_2" }, { "Cell 2_1", "Cell 2_2" } }, new String[] { "Column1", "Column2" });
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
JScrollPane scrollPane = new JScrollPane(table);
centerPane.add(scrollPane);
frame.getContentPane().add(centerPane);
frame.setSize(400, 300);
frame.setVisible(true);
}
It would be very nice, if we can have a config, which makes more fun for me as a frontend developer to style all the components easily by my own via CSS or maybe with a JSON config file. We are talking about stuff, that are already stylable like borders (color, width, style, shadow, etc.) inputs (color, size, margin, padding, etc.) and and and. Maybe with CSS it will be a bit hard to map the correct values to the correct fields but with a json config file, it would be nice to have smth like this:
CompletionPopup: {
"matchForeground": "#fff",
"disabledBackground": "#ccc"
}
That is first just fun to do that and very easy to create new look and feels and second, I hope it will be easy of switchting look and feels in Netbeans without a restart. Just guessing, beacuse it is just switchting properties and swing needs to updates it.
Add module-info.class
(compile with Java 9), but compile the main part for Java 8.
With the system L&F (Windows 10), mnemonics are not displayed in menus unless I press the Alt key. With FlatLaf, mnemonics are always displayed.
I see that the FlatLaf code triggers repainting on the hierarchy when Alt is pressed or released, but this has no visual impact.
Unless I am mistaken, FlatMenuUI extends BasicMenuUI, and BasicMenuUI always paints the mnemonic. WindowsMenuItemUI (for system L&F) also extends BasicMenuItemUI but overrides paintText to have the mnemonic show/hide logic.
Please, let me know if I did something wrong ๐
In a FileChooser with native look and feel on Windows (my reference), using the scroll bar or the wheel mouse scrolls by block, always with the file names aligned on the left. With FlatLaf, file names can be anywhere which makes it quite hard to find a file in big folders.
This is not seen in the demo app since it doesn't have secondary level menus.
You'll need a couple of primary items that open secondary content, each one with different texts and icons. As you roll over the primary items, the newly opened secondary menu shows the old content (from the previously opened secondary menu) for a split second, and then shows the correct content.
default i dont have any JSplitPane arrow buttons on my divider.
Is there extra customization i have to do or am i missing something?
regards
Nils G.
Using toggle buttons that look like tabs is great for the L&F harmony of the application. This allows to create task bar buttons for example.
Now, depending on the context, the buttons will be adjusted in different ways (important bar may have bigger buttons, bold font, etc.). The problem is that the size of the underline and its related attributes are global. If I am not mistaken, there are no client properties to have a per-instance definition.
Hi,
It is common to tweak default behaviors by creating wrappers that delegate to the original renderer.
When we do this with table headers in FlatLaf, then borders and separators are not painted anymore.
Here is sample code showing two tables, one standard and one with delegate:
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(new FlatLightLaf());
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel centerPane = new JPanel(new GridLayout(2, 1));
JTable table1 = new JTable(new Object[][] {{"Data_1_1", "Data_1_2"}, {"Data_2_1", "Data_2_2"}}, new String[] {"Col1", "Col2"});
centerPane.add(new JScrollPane(table1));
JTable table2 = new JTable(new Object[][] {{"Data_1_1", "Data_1_2"}, {"Data_2_1", "Data_2_2"}}, new String[] {"Col1", "Col2"});
JTableHeader tableHeader = table2.getTableHeader();
TableCellRenderer defaultRenderer = tableHeader.getDefaultRenderer();
tableHeader.setDefaultRenderer(new TableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
return defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
});
centerPane.add(new JScrollPane(table2));
frame.getContentPane().add(centerPane);
frame.setSize(400, 300);
frame.setVisible(true);
}
And here is a screenshot of the result:
The problem is because of magic code in "FlatTableHeaderUI.paint(g, c)" based on renderer class names.
It is quite hard to follow the values of a given item (row) when tables have no lines at all.
Generally, tables in Flat design have, or allow activation of, horizontal lines (but not necessarily vertical lines). I did not find any way to do it with FlatLaf, so sadly I have to show all lines using:
UIDefaults defaults = UIManager.getDefaults();
defaults.put("Table.showGrid", Boolean.TRUE);
defaults.put("Table.intercellSpacing", 1);
Am I missing something? Is there a way to activate horizontal lines only, and that as a global L&F setting (not per table instance like the setShowHorizontalLines(b)
method)?
When a button is placed in a toolbar, the appearance of its border changes. I found that the border is replaced when parenting to the toolbar, while it should be the same instance with a different painting logic. Otherwise, compounding the default border with another border does not work.
Here is a simple test case to illustrate:
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(new FlatLightLaf());
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JToolBar toolBar = new JToolBar();
JButton button1 = new JButton(new FlatFileViewFloppyDriveIcon());
toolBar.add(button1);
JButton button2 = new JButton(new FlatFileViewFloppyDriveIcon());
button2.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10), button2.getBorder()));
toolBar.add(button2);
panel.add(toolBar);
frame.getContentPane().add(panel);
frame.setSize(400, 300);
frame.setVisible(true);
}
Here is a screenshot of the result:
Notice that the second button has a border that is painted, which it should not have.
Hi ! I'm having difficulties with getting a colored background for a JButton or a JToggleButton depending on its state (red/green). I also just saw that version 0.22 changed this a little, but I feel we might need a way to specify a background color. I've tried many different combinations of opaque/etc but it seems hard. What do you think ?
I have a question on customizing JTabbedPane. Can I customize the selectedBackground?
I am using FlatIntelliJLaf and do the following:
FlatIntelliJLaf.install();
UIManager.put("TabbedPane.selectedBackground", Color.BLUE);
// UI initialization here
This does not seem to have any effect. I see that the property is actually respected:
https://github.com/JFormDesigner/FlatLaf/blob/master/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java
However, no luck. Am I doing something wrong?
Add support for some widely used SwingX components.
Hi,
With system L&F on Windows 10, the sort icon for tables is placed at the top of the header text.
This is actually very useful, because it does not change the minimum necessary width of the column to display the header text and thus allows more compact columns.
Here is a screenshot showing the behavior on Windows 10 L&F and with FlatLaf for comparison:
Do you think it would be possible to implement a position attribute to specify left/right/top/bottom ? Note that I don't know if that would fit with right-to-left logic but you get the idea ๐
Hi, is there a way or option to have the scrollbar prev/next button showing ?
I have a heavily customized JTable where in that case the prev < and > next button of the scrollbar were used to move by a specific amount.
I'm still trying to see if I have my own border and options interfering with this control, but would an official addon for this component make it look better ?
(split from issue #39)
Modern applications that use flat widgets may want their frame decorations also to be flat.
Here is a test case of the current situation:
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(new FlatLightLaf());
JFrame frame = new JFrame("JFrame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
JDesktopPane desktopPane = new JDesktopPane();
JInternalFrame internalFrame1 = new JInternalFrame("JInternalFrame1", true, true, true, true);
internalFrame1.setLocation(50, 30);
internalFrame1.setSize(300, 200);
desktopPane.add(internalFrame1);
JInternalFrame internalFrame2 = new JInternalFrame("JInternalFrame2", true, true, true, true);
internalFrame2.setLocation(60, 40);
internalFrame2.setSize(300, 200);
desktopPane.add(internalFrame2);
frame.getContentPane().add(desktopPane);
frame.setSize(400, 300);
frame.setVisible(true);
internalFrame1.setVisible(true);
internalFrame2.setVisible(true);
internalFrame2.setIcon(true);
}
@DevCharly said:
Window decoration style looks similar to internal frames, but it seems that the implementation has nothing to do with internal frames. It is implemented in javax.swing.plaf.metal.MetalRootPaneUIand javax.swing.plaf.metal.MetalTitlePane.
This is a hefty endeavor in general, as core look-and-feels vary greatly in how well they support RTL orientation across the core Swing components. For example, an RTL combobox should have:
Aqua only gets 4 right
Nimbus gets 1, 2, 3 right
Metal gets only 2 right
FlatLaf only gets 2 right at the present moment (but this goes well beyond JComboBox in general)
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable t) {
t.printStackTrace(System.err);
}
JComboBox comboHebrew = new JComboBox(new Object[] { "\u05e8\u05d0\u05e9\u05d9 1",
"\u05e8\u05d0\u05e9\u05d9 2", "\u05e8\u05d0\u05e9\u05d9 3",
"\u05e8\u05d0\u05e9\u05d9 4", "\u05e8\u05d0\u05e9\u05d9 5",
"\u05e8\u05d0\u05e9\u05d9 6", "\u05e8\u05d0\u05e9\u05d9 7",
"\u05e8\u05d0\u05e9\u05d9 8", "\u05e8\u05d0\u05e9\u05d9 9" });
comboHebrew.setToolTipText("RTL combo");
comboHebrew.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
comboHebrew.setMaximumRowCount(6);
JComboBox comboRegular = new JComboBox(new Object[] { "item 1",
"item 2", "item 3",
"item 4", "item 5",
"item 6", "item 7",
"item 8", "item 9" });
comboRegular.setToolTipText("LTR combo");
comboRegular.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
comboRegular.setMaximumRowCount(6);
JButton toFlat = new JButton("Set FlatDark!");
toFlat.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel("com.formdev.flatlaf.FlatDarkLaf");
for (Window w : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
});
}
});
JButton toNimbus = new JButton("Set Nimbus!");
toNimbus.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(new NimbusLookAndFeel());
for (Window w : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
});
}
});
JButton toMetal = new JButton("Set Metal!");
toMetal.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(new MetalLookAndFeel());
for (Window w : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
});
}
});
JFrame frame = new JFrame("Combo test");
frame.setLayout(new BorderLayout());
JPanel flow = new JPanel(new FlowLayout());
comboRegular.setPreferredSize(new Dimension(comboRegular.getPreferredSize().width + 50,
comboRegular.getPreferredSize().height));
flow.add(comboRegular);
comboHebrew.setPreferredSize(new Dimension(comboHebrew.getPreferredSize().width + 50,
comboHebrew.getPreferredSize().height));
flow.add(comboHebrew);
frame.add(flow, BorderLayout.NORTH);
JPanel flowButtons = new JPanel(new FlowLayout());
flowButtons.add(toNimbus);
flowButtons.add(toMetal);
flowButtons.add(toFlat);
frame.add(flowButtons, BorderLayout.SOUTH);
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(new NimbusLookAndFeel());
} catch (Throwable t) {
t.printStackTrace(System.err);
}
JComboBox comboColors = new JComboBox<>(new Color[] {new Color(255, 128, 128),
new Color(128, 255, 128), new Color(128, 128, 255), new Color(255, 255, 128),
new Color(255, 128, 255), new Color(128, 255, 255)});
comboColors.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected,
boolean cellHasFocus) {
Color color = (Color) value;
Component result = super.getListCellRendererComponent(list,
color.getRed() + ":" + color.getGreen() + ":" + color.getBlue(),
index, isSelected, cellHasFocus);
result.setBackground(color);
return result;
}
});
JButton toFlat = new JButton("Set FlatDark!");
toFlat.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel("com.formdev.flatlaf.FlatDarkLaf");
for (Window w : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
});
}
});
JFrame frame = new JFrame("Combo test");
frame.setLayout(new BorderLayout());
frame.add(comboColors, BorderLayout.NORTH);
frame.add(toFlat, BorderLayout.SOUTH);
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Click the "Set FlatDark!" button and then click the combo at the top. Result:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at java.desktop/javax.swing.plaf.basic.BasicComboPopup.getPopupHeightForRowCount(BasicComboPopup.java:1283)
at java.desktop/javax.swing.plaf.basic.BasicComboPopup.getPopupLocation(BasicComboPopup.java:1369)
at java.desktop/javax.swing.plaf.basic.BasicComboPopup.show(BasicComboPopup.java:234)
at java.desktop/javax.swing.plaf.basic.BasicComboPopup.togglePopup(BasicComboPopup.java:1218)
at java.desktop/javax.swing.plaf.basic.BasicComboPopup$Handler.mousePressed(BasicComboPopup.java:897)
at java.desktop/java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:287)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6633)
This is on 0.14
See how the background behind the arrows is darker than the rest of the combobox fill.
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable t) {
t.printStackTrace(System.err);
}
JComboBox comboHebrew = new JComboBox(new Object[] { "\u05e8\u05d0\u05e9\u05d9 1",
"\u05e8\u05d0\u05e9\u05d9 2", "\u05e8\u05d0\u05e9\u05d9 3",
"\u05e8\u05d0\u05e9\u05d9 4", "\u05e8\u05d0\u05e9\u05d9 5",
"\u05e8\u05d0\u05e9\u05d9 6", "\u05e8\u05d0\u05e9\u05d9 7",
"\u05e8\u05d0\u05e9\u05d9 8", "\u05e8\u05d0\u05e9\u05d9 9" });
comboHebrew.setToolTipText("RTL combo");
comboHebrew.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
comboHebrew.setMaximumRowCount(6);
JComboBox comboRegular = new JComboBox(new Object[] { "item 1",
"item 2", "item 3",
"item 4", "item 5",
"item 6", "item 7",
"item 8", "item 9" });
comboRegular.setToolTipText("LTR combo");
comboRegular.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
comboRegular.setMaximumRowCount(6);
JButton toFlat = new JButton("Set FlatDark!");
toFlat.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel("com.formdev.flatlaf.FlatDarkLaf");
for (Window w : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
});
}
});
JButton toNimbus = new JButton("Set Nimbus!");
toNimbus.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(new NimbusLookAndFeel());
for (Window w : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
});
}
});
JButton toMetal = new JButton("Set Metal!");
toMetal.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(new MetalLookAndFeel());
for (Window w : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(w);
}
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
});
}
});
JFrame frame = new JFrame("Combo test");
frame.setLayout(new BorderLayout());
JPanel flow = new JPanel(new FlowLayout());
comboRegular.setPreferredSize(new Dimension(comboRegular.getPreferredSize().width + 50,
comboRegular.getPreferredSize().height));
flow.add(comboRegular);
comboHebrew.setPreferredSize(new Dimension(comboHebrew.getPreferredSize().width + 50,
comboHebrew.getPreferredSize().height));
flow.add(comboHebrew);
frame.add(flow, BorderLayout.NORTH);
JPanel flowButtons = new JPanel(new FlowLayout());
flowButtons.add(toNimbus);
flowButtons.add(toMetal);
flowButtons.add(toFlat);
frame.add(flowButtons, BorderLayout.SOUTH);
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Is this offset of a submenu normal? This is in a JPopupMenu on macos.
I was expecting the submenu to be top aligned with its parent but its a few pixels higher. If there were cascading submenus this would keep going higher and higher I would think. Can this offset be removed?
I see theres not much custom code in the L&F menu UI so I guess maybe theres nothing to be done here.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.