I've been trying to find a solution to coding Look and Feel
effectively so it doesn't bug or anything. So far it seemed to work with JMenuBar
, but I stopped at JMenu
.
The problem is that I can't change the color of it when it's clicked. Also sometimes the text doesn't display in an unclicked JMenu
, but it might be just me doing it in a wrong way. The thing I tried was to make a custom method for JMenu
by creating a class that extends JMenu
. I tried searching for the original JMenu
source code in hopes there are some methods i can override. Not sure if that's how it should be done, though. I read some stuff about UIManager
but haven't tried it. Could it be a better option?
If you know something about Look and Feel
, please feel free to give me some advice on how to work on it effectively. I'm posting my code underneath:
MAIN CLASS
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Main {
public static void main(String[] args) {
// JFRAME
JFrame frame = new JFrame();
frame.setTitle("Test App");
frame.setResizable(true);
frame.setSize(800,600);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// JMENUBAR
CustomMenuBar menuBar = new CustomMenuBar();
menuBar.setColor(Color.BLUE);
// JMENU
JMenu menu = new JMenu("Language");
menu.setForeground(Color.pink);
// menu.addMenuListener();
// JMENUITEM
JMenuItem eng = new JMenuItem("English");
menu.add(eng);
menuBar.add(menu);
frame.setJMenuBar(menuBar);
frame.setVisible(true);
}
}
CUSTOMMENUBAR CLASS
import javax.swing.*;
import java.awt.*;
public class CustomMenuBar extends JMenuBar {
Color menuBarBgc = Color.RED;
public void setColor(Color color) {
menuBarBgc = color;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(menuBarBgc);
g2d.fillRect(0,0,getWidth() -1, getHeight() -1);
}
}
CUSTOMMENU CLASS
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class CustomMenu extends JMenu {
Color menuBgc = Color.RED;
public void setColor(Color color) {
menuBgc = color;
// setOpaque(true);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(menuBgc);
g2d.fillRect(0,0,getWidth() -1, getHeight() -1);
}
}
SCREENSHOTS
How the app looks like:
How it looks like after clicking the JMenu
"Language":
How I want it to look like (after JMenu
has been clicked, the background changed color to a brighter blue, text color stays pink and the JMenuItem
underneath is blue with a pink text, just as the JMenuBar
before clicking anything):
I've been trying to find a solution to coding Look and Feel
effectively so it doesn't bug or anything. So far it seemed to work with JMenuBar
, but I stopped at JMenu
.
The problem is that I can't change the color of it when it's clicked. Also sometimes the text doesn't display in an unclicked JMenu
, but it might be just me doing it in a wrong way. The thing I tried was to make a custom method for JMenu
by creating a class that extends JMenu
. I tried searching for the original JMenu
source code in hopes there are some methods i can override. Not sure if that's how it should be done, though. I read some stuff about UIManager
but haven't tried it. Could it be a better option?
If you know something about Look and Feel
, please feel free to give me some advice on how to work on it effectively. I'm posting my code underneath:
MAIN CLASS
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Main {
public static void main(String[] args) {
// JFRAME
JFrame frame = new JFrame();
frame.setTitle("Test App");
frame.setResizable(true);
frame.setSize(800,600);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// JMENUBAR
CustomMenuBar menuBar = new CustomMenuBar();
menuBar.setColor(Color.BLUE);
// JMENU
JMenu menu = new JMenu("Language");
menu.setForeground(Color.pink);
// menu.addMenuListener();
// JMENUITEM
JMenuItem eng = new JMenuItem("English");
menu.add(eng);
menuBar.add(menu);
frame.setJMenuBar(menuBar);
frame.setVisible(true);
}
}
CUSTOMMENUBAR CLASS
import javax.swing.*;
import java.awt.*;
public class CustomMenuBar extends JMenuBar {
Color menuBarBgc = Color.RED;
public void setColor(Color color) {
menuBarBgc = color;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(menuBarBgc);
g2d.fillRect(0,0,getWidth() -1, getHeight() -1);
}
}
CUSTOMMENU CLASS
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class CustomMenu extends JMenu {
Color menuBgc = Color.RED;
public void setColor(Color color) {
menuBgc = color;
// setOpaque(true);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(menuBgc);
g2d.fillRect(0,0,getWidth() -1, getHeight() -1);
}
}
SCREENSHOTS
How the app looks like:
How it looks like after clicking the JMenu
"Language":
How I want it to look like (after JMenu
has been clicked, the background changed color to a brighter blue, text color stays pink and the JMenuItem
underneath is blue with a pink text, just as the JMenuBar
before clicking anything):
1 Answer
Reset to default 1Let's start with the fixes:
In the main method, we create a Main object with which we invoke the init method, and we pass it as a parameter to the invokeLater() static method of the SwingUtilities class. This way, we ensure that the GUI is created on the event thread, thus avoiding concurrency issues ("sometimes the text doesn't display in an unclicked...").
In init, we add an actionListener to eng that will trigger the changes, within the created class, we modify the required colors, with setForeground we modify the color of the text, and with setBackground the background color.
In the last editon, add the mouse listener to the JMenu, and using the mouseEntered and mouseExited methods we handle the color change.
public class Main {
public static void main( String[] args ) {
SwingUtilities.invokeLater( new Main()::init );
}
public void init() {
// JFRAME
JFrame frame = new JFrame();
frame.setTitle( "Test App" );
frame.setResizable( true );
frame.setSize( 800, 600 );
frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
// JMENUBAR
CustomMenuBar menuBar = new CustomMenuBar();
menuBar.setColor( Color.BLUE );
// JMENU
JMenu menu = new JMenu( "Language" );
// JMENUITEM
JMenuItem eng = new JMenuItem( "English" );
menu.add( eng );
menuBar.add( menu );
frame.setJMenuBar( menuBar );
frame.setVisible( true );
// If you want the changes to be made when you
// hover over the **JMenu** you use:
menu.addMouseListener( new MouseAdapter() {
// if the mouse enters the limits of the ** **JMenu**
@Override
public void mouseEntered( MouseEvent e ) {
menu.setForeground( Color.pink );
}
// if the mouse goes outside the limits of the **JMenu**
@Override
public void mouseExited( MouseEvent e ) {
menu.setForeground( Color.white );
}
} );
// if you want the changes to be made when doing
// something with the **JMenuItem** you use:
eng.addActionListener( ( e ) -> {
// call your method
menuBar.setColor( Color.darkGray );
menu.setForeground( Color.pink );
eng.setForeground( Color.white );
eng.setBackground( Color.black );
} );
// if you need it to run when clicking on the **JMenu**
menu.addMenuListener( new MenuListener() {
@Override
public void menuSelected( MenuEvent e ) {
menu.setForeground( Color.pink );
menuBar.setColor( Color.darkGray );
// menuBar.setBackground( Color.yellow );
eng.setForeground( Color.white );
eng.setBackground( Color.black );
}
// these two methods must be implemented, since in the "parent" they are abstract.
@Override
public void menuDeselected( MenuEvent e ) {
}
@Override
public void menuCanceled( MenuEvent e ) {
}
} );
}
}