Help coderanch get a
new server
by contributing to the fundraiser
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Devaka Cooray
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • paul wheaton
  • Henry Wong
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Tim Moores
  • Carey Brown
  • Mikalai Zaikin
Bartenders:
  • Lou Hamers
  • Piet Souris
  • Frits Walraven

Can't change look and feel on Windows.

 
Ranch Hand
Posts: 146
Mac OS X IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have been developing my java GUI on MacOS for a while now. (The entire GUI is done, it just needed bug fixing).
I stopped making the project for a while and in between transitioned to Windows. I wanted to complete all my unfinished projects so I moved it over from MacOS to Windows. Upon opening the java GUI, it looked like this:

Not entirely what I was expecting to be honest.

Anyway I continued on with it for while. I then remembered you could change look and feel so I used this little bit of code:

However this doesn't work. It throws every error that the function can throw:

I've done a lot of looking around and this seems to be the only way to change look and feel in an application. This also should work on Windows according to many posts. Does anyone know why it isn't working?
I'm sure it's probably a simple fix but I just can't seem to fix it. (It doesn't matter what I put into the .setLookAndFeel function it always throws those errors)
 
Saloon Keeper
Posts: 15705
367
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Are those the exceptions that are actually thrown, or is the compiler complaining that you're not handling them?

You can just do something like this in your main method:
 
Bod McLeon
Ranch Hand
Posts: 146
Mac OS X IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:Are those the exceptions that are actually thrown, or is the compiler complaining that you're not handling them?

You can just do something like this in your main method:


I think you're right - it might just be the compiler complaining. I do normally have it in a try catch.
Unfortunately it doesn't seem to change the look and feel. Do I have to call it right at the beginning of the application?
 
Stephan van Hulst
Saloon Keeper
Posts: 15705
367
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes. Technically it doesn't have to be at the very start of the application, but it must be before the AWT Toolkit is initialized, which happens as soon as you touch anything related to AWT or Swing.
 
Stephan van Hulst
Saloon Keeper
Posts: 15705
367
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think you're confused though. The cross-platform look-and-feel (Metal) is the one that Java uses by default. Going by the screenshot you posted, you're already using the cross-platform look-and-feel.

Instead, try using the system look-and-feel with UIManager.getSystemLookAndFeelClassName(). This will give your application a look-and-feel that is more native to the platform it is running on.
 
Bod McLeon
Ranch Hand
Posts: 146
Mac OS X IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:Yes. Technically it doesn't have to be at the very start of the application, but it must be before the AWT Toolkit is initialized, which happens as soon as you touch anything related to AWT or Swing.



Technically I did have it at the beginning of the GUI, before anything had be drawn, but it wasn't before the GUI was initialized. I have now moved it to the very beginning.

Stephan van Hulst wrote:I think you're confused though. The cross-platform look-and-feel (Metal) is the one that Java uses by default. Going by the screenshot you posted, you're already using the cross-platform look-and-feel.

Instead, try using the system look-and-feel with UIManager.getSystemLookAndFeelClassName(). This will give your application a look-and-feel that is more native to the platform it is running on.



I see, OK.
I tried out the UIManager.getSystemLookAndFeelClassName() and that indeed did change along the look (along with moving the code) however that hasn't gotten rid of the white fill around the different widgets. It seems that java (on Windows) is filling the bounding boxes with white. I thought this was because of the look and feel but I guess not. I'll see if I can fix it.

Thank you!
 
Bod McLeon
Ranch Hand
Posts: 146
Mac OS X IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have fixed the weird fill issue by just using .setBackground(new Color(0,0,0,0));

This has actually introduced a very odd issue however:

As you can see, tehre is some weird artifacting around some of the widgets. What is common between all those widgets? I set their background opacity to 0.
To fix this, do I have to put the .setBackground's in some kind of loop to continually draw the opacity over and over again?
 
Saloon Keeper
Posts: 10879
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You are setting the alpha value in your Color to '0' which means 'transparent', I think you wanted '255' which would be 'opaque'.
 
Bod McLeon
Ranch Hand
Posts: 146
Mac OS X IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Carey Brown wrote:You are setting the alpha value in your Color to '0' which means 'transparent', I think you wanted '255' which would be 'opaque'.


But surely if it was transparent, you would just see the gray frame beneath it? I wanted it to be transparent so I didn't have to specify an exact colour to match up with the background.
 
Stephan van Hulst
Saloon Keeper
Posts: 15705
367
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Bod McLeon wrote:But surely if it was transparent, you would just see the gray frame beneath it? I wanted it to be transparent so I didn't have to specify an exact colour to match up with the background.


No. JPanel.isOpaque() returns true by default. That means that the container that holds the panel assumes that the panel will completely paint all of its contents and so they will not paint whatever is 'underneath'. If you want to use transparency in your panel, you must first call setOpaque(false).

However, I think the real problem is that you are fighting the look-and-feel by using your own custom colors, borders, and maybe even layout manager. Instead of fighting it, rely on the look-and-feel to get it right.

Can you show us your code so we might give you some advice on how to continue?
 
Carey Brown
Saloon Keeper
Posts: 10879
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If you must match the desktop color you can get it with AWT's Robot.getPixelColor(x,y), then use the color with alpha set to 255.

I think Stephan is right though.
 
Bod McLeon
Ranch Hand
Posts: 146
Mac OS X IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:

Bod McLeon wrote:But surely if it was transparent, you would just see the gray frame beneath it? I wanted it to be transparent so I didn't have to specify an exact colour to match up with the background.


No. JPanel.isOpaque() returns true by default. That means that the container that holds the panel assumes that the panel will completely paint all of its contents and so they will not paint whatever is 'underneath'. If you want to use transparency in your panel, you must first call setOpaque(false).

However, I think the real problem is that you are fighting the look-and-feel by using your own custom colors, borders, and maybe even layout manager. Instead of fighting it, rely on the look-and-feel to get it right.

Can you show us your code so we might give you some advice on how to continue?



It's quite long so, for now, I'll post snippets of code but hopefully they will give you an idea of the whole thing.
Also, I needed a quick and dirty GUI so I used Eclipse's Windows Builder hence why there is a lot of repeated, messy and probably totally stupid code.. but hey, it works ¯\_(ツ)_/¯.

My main GUI script starts by calling the GUI like this:

There are two functions there, 'SubredditSelection' and 'SubredditOptions'. Both of these follow this style:

As you can see, I do 'cm.<some_component>'. This is because code gets repeated a lot I thought to neaten it up, I could just create a file which creates the widgets for me, to save from repeating code. It looks like this:

And it's that repeated over and over for every component I use (not great, I know).
There's many more functions that for instance, check for text in the text box, or functions that create swing worker threads but since they don't add to the GUI I didn't think it was worth including them.

And again, I know this is a very bad way of doing things (null layout etc etc...) and I want to rewrite the GUI in something like JS or even better, Python, but I don't have the time or motivation. The only thing making me finish this is the fact that I hate having unfinished projects.
 
Stephan van Hulst
Saloon Keeper
Posts: 15705
367
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Bod McLeon wrote:Also, I needed a quick and dirty GUI so I used Eclipse's Windows Builder hence why there is a lot of repeated, messy and probably totally stupid code.. but hey, it works ¯\_(ツ)_/¯.


Does it though? :P

Anyway, your code confirms my suspicions. You're setting custom colors and borders all over the place. As you've seen, this doesn't work well when running the application on a different platform.

A better option is to get rid of all this custom skinning and find a custom cross-platform look-and-feel that you like. It seems like you're going for a slick dark theme; a simple Google search for "Java dark look and feel" yielded FlatLaf, which looks promising.
 
Stephan van Hulst
Saloon Keeper
Posts: 15705
367
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Carey Brown wrote:If you must match the desktop color you can get it with AWT's Robot.getPixelColor(x,y), then use the color with alpha set to 255.


Note that if you want to get a default color from the look and feel, you can use UIManager.getColor(), for instance:

This is easier and more robust than using a robot.
 
Bod McLeon
Ranch Hand
Posts: 146
Mac OS X IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:

Bod McLeon wrote:Also, I needed a quick and dirty GUI so I used Eclipse's Windows Builder hence why there is a lot of repeated, messy and probably totally stupid code.. but hey, it works ¯\_(ツ)_/¯.


Does it though? :P

Anyway, your code confirms my suspicions. You're setting custom colors and borders all over the place. As you've seen, this doesn't work well when running the application on a different platform.

A better option is to get rid of all this custom skinning and find a custom cross-platform look-and-feel that you like. It seems like you're going for a slick dark theme; a simple Google search for "Java dark look and feel" yielded FlatLaf, which looks promising.


Thanks for the reply. I quite like FlatLaf, and it does fix the issues I have, so I think I'll stick with it. I'm going to check what it looks like on MacOS, but I don't expect it to be bad since the original UI was fine on there.


Thank you very much for the help so far! I have one more, sort of related question - I hope you don't mind me asking you. Of course, I don't want to milk this thread for all sorts of answers if they aren't really related, so I'm happy to open another thread if you think that's a better idea.

Anyway, the last issue I seems to have is with the progress bar. On Windows, .setEnabled(true) and .setEnabled(false) don't change the progress bar to look enabled/disabled.
On Mac, and enabled progress bar is a sort of aqua blue:

And when it's disabled, it goes gray (I coudn't find an image of it gray).
On Windows, it doesn't matter the look and feel, whether it's enabled or disabled... it still looks enabled. This (https://stackoverflow.com/questions/9232011/possible-to-disable-a-progress-bar-in-swing) stackoverflow post seems to be my exact issue. The answer to that post it to basically implement your own progress bar. Is there not a better way to fix this, or will it always look enabled no matter what?
 
Stephan van Hulst
Saloon Keeper
Posts: 15705
367
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't think Windows has the concept of a disabled progress bar. What does it mean for a progress bar to be disabled?

Again, you're fighting the native look and feel. Windows users are not used to disabled progress bars. Why force it on them? Can't you convey your information in a more meaningful way?
 
Bod McLeon
Ranch Hand
Posts: 146
Mac OS X IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:I don't think Windows has the concept of a disabled progress bar. What does it mean for a progress bar to be disabled?

Again, you're fighting the native look and feel. Windows users are not used to disabled progress bars. Why force it on them? Can't you convey your information in a more meaningful way?


Really, the only point of the progress bar is to show the user the program is running, and the GUI isn't frozen (which it can sometimes do). A disabled progress bar is just like any disabled component - it could go slightly gray, or just have no animation. Again, it's purely there as an indicator. I have no good way of being able to determine how long it's going to take to run the program, so I cant use the progress bar to show actual progress. I mean, I could suggest how much time it would take but running some timings on my computer, but i's heavily dependant on how much ram you have. I have 8GB and it probably takes about 15 minutes to run. Someone with 32GB might only be there for 5 minutes.

I was thinking of a bodge fix which could be:
Set the progress bar to non indeterminate (so it shows actual progress), and set the progress to 0. This is its sort of 'disabled' state.
Then when the 'run' button is hit, I just set the progress bar to indeterminate, so it then animates.
 
Stephan van Hulst
Saloon Keeper
Posts: 15705
367
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Your 'bodge fix' actually sounds pretty reasonable to me. If there's no process running, there is no progress. If the process *is* running but you don't know how far it is, the progress is indeterminate. Sounds legit.

It appears to me like your application processes lots of images. Can't you display a label showing the file name of the image it's processing? That way the user will see that *something* is happening, and they can also make a rough estimate how far the application has progressed.

Tell us more about what the application does. Maybe we can give you better ideas on how to indicate the progress.
 
reply
    Bookmark Topic Watch Topic
  • New Topic