JFrame looks different depending on how its loaded - java

I have a JFrame:
public class Help extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Help frame = new Help();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Help() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
}
}
If i run this in Eclipse i get the following:
Now if call this from the ActionListener of a JButton within another JFrame using:
btnHelp.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Help frame = new Help();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
});
Then the JFrame loads looking like this:
This looks ugly to me. Why isn't the first style loading when i initialize the JFrame from within another JFrames JButton ActionListener? It seems to me like i'm running exactly the same code with both methods of loading it.

This particular segment of code:
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable e) {
e.printStackTrace();
}
Changes what we call the look & feel of the JFrame. This includes everything from button graphics, animations to sizes and proportions of default sized components in the frame. The look and feel must be set before the JFrame is drawn onto the screen and changing it around mid-program can be quite tricky. As such, I believe your second invocation from the actionListener happens either without the presence of the look at feel code or happens before the setting of the look and feel.
Since it is a "global" attribute (that is, it affects all frames in the running program) I personally put it as the first statement in my main() method as to protect against any sort of potential accidental creations of frames before the statement is invoked.
Please note though, without setting the look and feel, java assumes a default cross-platform view which stays constant across all operating systems. UIManager.getSystemLookAndFeelClassName() changes this behavior to allow for a system-specific L&F. You may need to take this in mind when distributing the program across OSes as with a system-specific L&F, fine-tuned layouts may be destroyed due to differing component sizes.

In your second example, the new JFrame will have the same look and feel as the other JFrames in the application.
Your comments indicate that you are not setting the look and feel for that application.
Use a line similar to the one in your first example to do this.

Related

How to set window always on top of any other applications

I have a JFrame which needs to be always on top of the other application. For this I am using setAlwaysOnTop() method of Window class.
Here is my code :
class Test1 extends JFrame {
public Test1() {
initComponents();
setTitle("Top Window");
setAlwaysOnTop(true);
}
private void initComponents() {
jLabel1 = new JLabel();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jLabel1.setHorizontalAlignment(SwingConstants.CENTER);
jLabel1.setText("I am a top most window");
getContentPane().add(jLabel1, BorderLayout.CENTER);
pack();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Test1().setVisible(true);
}
});
}
private javax.swing.JLabel jLabel1;
}
This works fine with some of the other application such as notepad, explorer etc, i.e. when my application is above notepad everything works fine.
But when my java application goes above any application that is already on top such as task manager. Then the method setAlwaysOnTop() doesn't works.
What I need is any way through which I can make my application always on top.
I have also searched many other related posts on stackoverflow but none seems to answer my question. I have also tried other ways such as overriding the windowDeactivated(WindowEvent e) method
addWindowListener(new WindowAdapter(){
#Override
public void windowDeactivated(WindowEvent e) {
toFront();
//requestFocus();
//requestFocusInWindow();
}
});
but this also doesn't worked.
Is there any other way through which I can may my JFrame always on top of every other application except in case of full screen applications.
It depends on the operating system. In general, you can't guarantee that your window will always be on top when it comes to native windows, nor should you. The task manager is always-on-top for good reasons.
I remember that some versions of Vista and older Windows systems allowed that and the native and Java windows ended up fighting for focus.

Changing variable values in GUI Eclipse

I wrote a game with a lot of classes,and it works fine.But it is too exhausting to change the values of the variables from source code every time I want to test something.So I researched how can I enter the values of the variable without using window.The behaviour I want is that when I run the program a panel will be openned and it will ask me the values of variables.I tried to use JInternal frame,eclipse creates a default JInternal Frame for you.
import java.awt.EventQueue;
import javax.swing.JInternalFrame;
public class Test extends JInternalFrame {
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
BoardConstructor frame = new BoardConstructor();
frame.setTitle("Monopoly");
frame.setSize(1500,750);
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.getContentPane().add(new MyShape());
Test frame1 = new Test();
frame1.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Test() {
setBounds(100, 100, 450, 300);
}}
I wrote my main function into this which simply creates my game.Now what I think should work is that this class should access the variables in other classes and change them but I have no idea how it works in reality.How can I accomplish that?
If you try live debugging in Eclipse than if you have a pause feature, you can easily change the variable values in the code. If that's not what you're looking for let me know

Refresh java program with Button

I am trying to make a refresh button that will essentially restart the program when ever I click the button. I don't know how I should go about doing this.
I've place the Graphical User Interface i decided to use do complete this action. Any and all help would be greatly appreciated.
package pdfView;
import javax.swing.*;
import java.awt.*;
public class View extends JFrame {
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
JButton ReFresh = new JButton("ReFresh");
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel(
"com.sun.java.squing.plaf.nimbus.NimbusLookAndFeel"
);
} catch (Exception exc){
}
}
public static void main(String[] args) {
View pdf = new View();
}
}
What do you mean by refresh or restart?
Do you mean:
Let the application be as it is, just update what it's showing?
Really restart the application?
Updating what the application is showing
You first need to decide what actually should cause your application to refresh. You already talked about a Button. The mechanism for activating something like a button is called Action. You can do that stuff manually, using an ActionListener, or you could extend AbstractAction, which is what I recommend. Extending AbstractAction allows you to use the same logical action something in more than one location on the UI. Look at typical applications, they offer Cut/Copy/Paste through menu, toolbar, popupmenu and keyboard shortcuts. The simplest way to achieve this in Java is using Action by extending AbstractAction.
The methods you need to call to update your application are invalidate(), validate() or repaint().
Restarting an application
So you want to run through main() again? That should actually not be required, unless you have an application that supports updating itself. Even then it can sometimes be avoided by smart usage of a ClassLoader.
Some more notes on your code
Usage by extension anti-pattern
I wouldn't extend JFrame just to display a window on the screen. Usage by extension is an anti-pattern. You don't need to extend JFrame to get a JFrame displayed on the screen and do what you want.
Referring static members
I would refer to constants via their original declaration. I.e. I'd refer to EXIT_ON_CLOSE via WindowConstants.EXIT_ON_CLOSE, not JFrame.EXIT_ON_CLOSE.
Typo
You have a typo in your UIManager.setLookAndFeel() code. Search for swing and you will see the typo.
Exception information
You might actually want to print the exception to stderr using exc.printStackTrace() instead of ignoring it completely, because when you have a typo in the LaF class name, as you do, and you don't print the exception, you might actually not come to know what's going wrong.
Sequence of widget construction and UIManager.setLookAndFeel()
The sequence of UIManager.setLookAndFeel() and the effective new JFrame() via super(...) does not guarantee you that the whole UI will be in Nimbus, parts of it might still be in Metal. I recommend to set the LaF before even constructing the first widget, to be on the safe side. As far as I remember, it's not guaranteed that changing the LaF after component construction has an effect, unless you tell the UIManager to update the LaF. See also this quote from the documentation of UIManager:
Once the look and feel has been changed it is imperative to invoke updateUI on all JComponents. The method SwingUtilities.updateComponentTreeUI(java.awt.Component) makes it easy to apply updateUI to a containment hierarchy. Refer to it for details. The exact behavior of not invoking updateUI after changing the look and feel is unspecified. It is very possible to receive unexpected exceptions, painting problems, or worse.
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
setSize() vs. pack() with a little help of Insets and Border
Instead of setting the size manually, you might want to play with Insets or Border and JFrame.pack() in order to get a decent layout of your window. Setting the size manually assumes that you know a lot about the screen resolution and the font size of the user.
The pack() method performs automatic size calculation based on the contents. Insets and Border allow you to create some space and borders, even with some designs or labels, around components so they wouldn't be cramped tightly in a window but be nicely spaced.
First you have to assign an actionListener to the ReFresh Jbutton.
You can either implement the interface ActionListener to the class, and override the actionPerformed() method like this
public class View extends JFrame implements ActionListener{
private JButton ReFresh;
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
ReFresh = new JButton("ReFresh");
ReFresh.addActionListener(this);
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() { //right way for nimbus: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/nimbus.html
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.equals(ReFresh))
{
super.repaint();
}
}}
public static void main(String[] args) {
View pdf = new View();
}
Or you can do inline assignment to addActionListener, like this
ReFresh.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
super.repaint();
}
});
You can try these methods to refresh/reload the JFrame,
invalidate();
validate();
repaint();
you can also use dispose(); and then new View(); to create the new JFrame, but in this sequence it will close the window and create new one.
or you can even try setVisible(false); then setVisible(true);
I recommend the first 3.

Applying new UI to JInternalFrame title

I've never done anything with UI's before and I've been tasked with getting our internal frame titles changed. We're using the Nimbus L&F and in our UI manager I've tried
UIManager.put("InternalFrameTitlePane.background", Color.RED);
just to try and get something to change. The didn't work for me and I found another post somewhere about creating a UI using the BasicInternalFrameTitlePane so I now have this code:
public class CFrameTitleUI extends BasicInternalFrameTitlePane {
public CFrameTitleUI(JInternalFrame f)
{
super(f);
}
#Override
public void paintTitleBackground(Graphics g)
{
g.setColor(Color.RED);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
But now that I have this I'm not sure what to do with it. I've tried setting the UI in the internal frame using it's setUI() method, but this is a title bar for it so I'm sure thats wrong. I next tried
UIManager.put("InternalFrameTitlePane.background", CFrameTitleUI.getClass().getName());
and
UIManager.put("InternalFrameTitlePane", CFrameTitleUI.getClass().getName());
but nothing. Do I need to tie it back to the nimbus L&F somehow? Some of the things we're setting say "nimbusSelection" etc..
Main questions are am I creating a custom UI for the internal frame titles correctly and how do I apply it, thanks.
Do you get the same?
public class InternalFrameTest extends JFrame {
public InternalFrameTest() {
JDesktopPane desktop = new JDesktopPane();
JInternalFrame frame = new JInternalFrame("AHHHH!!!!", true);
frame.setSize(300, 300);
frame.setVisible(true);
frame.setOpaque(false);
desktop.add(frame);
setContentPane(desktop);
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(NimbusLookAndFeel.class.getName());
} catch (ClassNotFoundException|InstantiationException
|IllegalAccessException|UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
UIManager.put("InternalFrame:InternalFrameTitlePane[Enabled].textForeground", Color.RED);
new InternalFrameTest();
}
}
When I run (without setting anything to it)
System.out.println(UIManager.getColor("InternalFrame:InternalFrameTitlePane[Enabled].textForeground"));
I get
"DerivedColor(color=142,143,145 parent=nimbusDisabledText offsets=0.0,0.0,0.0,0 pColor=142,143,145"
Do you get the same?

(Java) Appearing/Disappearing JLabel in a JPanel only disappears on resize

I'm working in Java, and I have a JPanel in a JFrame. In that JPanel, among other things, I have a JLabel that I want to make appear and disappear at will. I've tried setting visibility to true/false, adding and removing it from the JFrame and JPanel, and, having looked online, I tried validate()ing and revalidate()ing ad infinitum. What can be done here to solve this problem?
In general, calling the setVisible method is sufficient to make a Swing component to be shown or hidden.
Just to be sure that it works, I tried the following:
public class Visibility {
private void makeGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JLabel l = new JLabel("Hello");
final JButton b = new JButton("Hide Label");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
l.setVisible(false);
}
});
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(l, BorderLayout.CENTER);
f.getContentPane().add(b, BorderLayout.SOUTH);
f.setSize(200, 200);
f.setLocation(200, 200);
f.validate();
f.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Visibility().makeGUI();
}
});
}
}
The above program is able to affect the visibility by clicking on a JButton.
Could it be a Threading Issue?
My next suspicion was that perhaps a Thread that is not on the event dispatch thread (EDT) may not be affecting the display immediately, so I added the following after initializing the JLabel and JButton.
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
b.setVisible(!b.isVisible());
try {
Thread.sleep(100);
} catch (InterruptedException e) { /* Handle exception /* }
}
}
});
t.start();
With the new Thread running, it changed the toggled the visibility of the JLabel every 100 ms, and this also worked without a problem.
Calling a Swing component off the event dispatch thread (EDT) is a bad thing, as Swing is not thread-safe. I was a little surprised it worked, and the fact that it works may just be a fluke.
Repaint the JPanel?
If the JLabel's visibility is only being affected on resizing, it probably means that the JLabel is being drawn only when the JPanel is being repainted.
One thing to try is to call the JPanel's repaint method to see if the visibility of the JLabel will change.
But this method seems to be just a band-aid to a situation, if the main cause is due to a thread off the EDT is attempting to make changes to the GUI. (Just as a note, the repaint method is thread-safe, so it can be called by off-EDT threads, but relying on repaint is a workaround than a solution.)
Try using SwingUtilities.invokeLater
Finally, probably the thing I would try is the SwingUtilities.invokeLater method, which can be called (and should only be called) from a thread running separate from the EDT, if it wants to affect the GUI.
So, the earlier Thread example should be written as:
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
b.setVisible(!b.isVisible());
}
});
} catch (Exception e1) { /* Handle exception */ }
try {
Thread.sleep(100);
} catch (InterruptedException e) { /* Handle exception */ }
}
}
});
t.start();
If the change to the GUI is indeed occurring on a separate thread, then I would recommend reading Lesson: Concurrency in Swing from The Java Tutorials in order to find out more information on how to write well-behaving multi-threaded code using Swing.
setVisible() or removing it should work fine, make sure you are doing it from the event dispatch thread though. There are utility methods in EventQueue for running blocks in that thread.
http://helpdesk.objects.com.au/java/how-do-i-update-my-gui-from-any-thread
You would need to call revalidate() on the parent JPanel if you need its components to be re-laid out.
If you can post an example that demonstrates the problem I can have a look at it for you.

Categories