1

I am fairly new to coding and I am working on a desktop application where I want to implement a dark and light mode. The problem is that I want to switch back and forth between the two, in the main class I have an instantiation of a class that represents my main view of the app if I pass and if I add an action that switches to dark/light mode it only affects the popups because the function is called after the instantiation of the main view it has the same effect if I call the function before the instantiation. I tried all sorts of solutions but I can't figure it out. If anybody has an idea thanks in advance. Here is the code.

import view.MainFrame;

public class Main {
    public static void main(String[] args) {
        MainFrame mainFrame = MainFrame.getInstance();
    }
}
import controller.ActionManager;
import lombok.Getter;
import lombok.Setter;
import javax.swing.*;
import java.awt.*;

@Getter
@Setter
public class MainFrame extends JFrame {

    private static MainFrame instance = null;
    private MenuBar RuMenuBar;
    private ToolBar toolBar;
    private ActionManager actionManager;

    private MainFrame(){ }

    private void initialiseActionManager() {
        actionManager = new ActionManager();
    }


    private void initialiseGUI() {
        Toolkit tk = Toolkit.getDefaultToolkit();
        Dimension sc = tk.getScreenSize();
        int height = sc.height;
        int width = sc.width;
        setSize(width, height);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setTitle("Dokru");
        
        
        RuMenuBar = new MenuBar();
        setJMenuBar(RuMenuBar);
      
        toolBar = new ToolBar();

        add(toolBar,BorderLayout.NORTH);

        JPanel treePanel = new JPanel();

       // JScrollPane scrollPane = new JScrollPane(treePanel); todo scroll
        JPanel workspacePanel = new JPanel();
        JSplitPane splitPane = new 
        JSplitPane(JSplitPane.HORIZONTAL_SPLIT,treePanel,workspacePanel);
        splitPane.setOneTouchExpandable(true);
        splitPane.setDividerLocation(300);
        getContentPane().add(splitPane, BorderLayout.CENTER);

        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static MainFrame getInstance() {
        if(instance == null) {
            instance = new MainFrame();
            instance.initialiseActionManager();
            instance.initialiseGUI();
        }
        return instance;
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Waycoff
  • 11
  • 2
  • 1
    For dark mode you want to apply dark look-and-feel (LAF). See this [question](https://stackoverflow.com/questions/15049020/getting-a-dark-look-and-feel) – c0der Nov 02 '21 at 18:27
  • 1
    Changing the look and feel after the GUI is visible can be tricky. Check [this answer](https://stackoverflow.com/a/5630271/418556) which shows how to do it. – Andrew Thompson Nov 03 '21 at 00:14

2 Answers2

1

Happy to add more content in this section, this looks like a modern question for a very old framework like a swing.

However, there are opportunities to support this change in Java Swing, there are libraries like FlatLaf or material-ui-swing that give the possibility to implement different style in your app.

I'm the author of material-ui-swing so I will describe it, In particular, because It implements a concept of Material Theme (Since 2019) like the modern framework such as Flutter or Compose.

In fact, you can implement a custom theme as Jar and include it inside an external library, and an example can be DarkStackOverflowTheme.

To support the Dark mode and lite mode on your app, you can basically use the UI Manager to switch the Material theme in the MaterialUISwing(dark or lite theme).

Your question is a generic question but did some demo that include also the switch of the theme in the JMenuBar, you can take a look to DemoSwingRatio

vincenzopalazzo
  • 1,487
  • 2
  • 7
  • 35
-1

Use the system look and feel, you should get this automatically.

try {
    // Set System L&F
     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (UnsupportedLookAndFeelException e) {
    // handle exception
}
Charlie
  • 8,530
  • 2
  • 55
  • 53
  • 1
    *"The problem is that I want to switch back and forth between the two"* This does not address the problem. – Andrew Thompson Nov 03 '21 at 00:16
  • Oh no, I didn't see that. That sounds like a trap; The system L&F is the only one you should ever use. Maybe there's a way to intercept or override it's check for dark mode. – Charlie Nov 03 '21 at 01:44
  • *"The system L&F is the only one you should ever use."* Minus one. That's just nonsense. – Andrew Thompson Nov 03 '21 at 01:57
  • The question doesn’t specify whether switching should happen when the desktop itself is switched to dark mode, or whether only this one application should be individually switchable. In the absence of that information, this answer can be considered correct; using the system look-and-feel should pick up system switches to and from dark mode, high contrast mode, etc. – VGR Nov 04 '21 at 18:08
  • @AndrewThompson Can you explain why it's nonsense? System look and feel (at least Windows and Mac) are the most consistent, most reliable, and are the least tacky/cheap looking. They require zero added dependencies and zero cost. – Charlie Nov 04 '21 at 22:15
  • Check my answer, I develop one of my library to fix this problem of witch, like flutter or compose – vincenzopalazzo Nov 14 '21 at 09:31