JToolbar doesn't show on Ubuntu if set to BasicToolBarUI - java

I've decided to have my own custom UI of JToolBar by
subclassing BasicToolBarUI, as part of my Swing program.
It works great under OS X (10.6) and Windows (7), but
when it comes to Linux, problem occurs:
If the swing component is
Using SystemLookAndFeel (With Java LAF it is shown)
Using UI BasicToolBarUI (To simplify the problem. With this it already doesn't work)
running under Linux (Ubuntu 10.10)
the whole JToolBar doesn't appear anymore.
Can anyone give a hand on this? How to make it appear again on Linux? Thank you in advance.
(I've done the custom UI in order to
let user still able to move the toolbar to other edges
of the window, but prevent it from going to floating state.)
Cheers,
Shuo
My SSCCE:
// Set the system look and feel:
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
// Create frame
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200, 100));
// Create toolbar
JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL);
toolbar.add(new JButton("Foo"));
// With this line toolbar doesn't appear any more (only) on Linux.
toolbar.setUI(new BasicToolBarUI());
// Show UI
panel.add(toolbar);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);

You may not see it because you haven't added anything to it (actions, buttons etc). Empty toolbar usually has height of 1-2 pixels.
UPDATE:
From what I can tell by looking at BasicToolBarUI it doesn't really do anything - you have to implement size calculations and painting yourself to get proper results

Related

How can i get my JFrame to open centre screen? [duplicate]

While working with Java, I find it hard to position my main window in the center of the screen when I start the application.
Is there any way I can do that?
It doesn't have to be vertically centered, horizontal alignment is the more important goal for me. But vertical alignment is also welcome.
Use setLocationRelativeTo(null)
This method has a special effect when you pass it a null. According to the Javadoc:
If the component is null, or the GraphicsConfiguration associated with this component is null, the window is placed in the center of the screen.
This should be done after setting the size or calling pack(), but before setting it visible, like this:
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
I always did it in this way:
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2);
where this is the JFrame involved.
You can call JFrame.setLocationRelativeTo(null) to center the window. Make sure to put this before JFrame.setVisible(true)
Just click on form and go to JFrame properties, then Code tab and check Generate Center.
As simple as this...
setSize(220, 400);
setLocationRelativeTo(null);
or if you are using a frame then set the frame to
frame.setSize(220, 400);
frame.setLocationRelativeTo(null);
For clarification, from the docs:
If the component is null, or the GraphicsConfiguration associated with this component is null, the window is placed in the center of the screen.
i am using NetBeans IDE 7.2.1 as my developer environmental and there you have an option to configure the JForm properties.
in the JForm Properties go to the 'Code' tab and configure the 'Generate Center'.
you will need first to set the Form Size Policy to 'Generate Resize Code'.
I am using NetBeans IDE 7.3 and this is how I go about centralizing my JFrame
Make sure you click on the JFrame Panel and go to your JFrame property bar,click on the Code bar and select Generate Center check box.
If you use NetBeans, simply click on the frame on the design view, then the code tab on its properties. Next, check 'Generate Center'. That will get the job done.
If you explicitly setPreferredSize(new Dimension(X, Y)); then it is better to use:
setLocation(dim.width/2-this.getPreferredSize().width/2, dim.height/2-this.getPreferredSize().height/2);
You can use this method, which allows the JFrame to be centered and full screen at the same time.
yourframe.setExtendedState(JFrame.MAXIMIZED_BOTH);
In Net Beans GUI -
go to jframe (right click on jFrame in Navigator) properties, under code, form size policy property select Generate Resize Code. In the same window, Untick Generate Position and tick Generate Size and Center.
Enjoy programming.
Ramana
I will provide 3 methods to your question :
You can either use the simplest method to center it, relative to your viewport, which is :
setLocationRelativeTo(null);
The second one, is to use :
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(dim.width/2 - frame.getSize().width/2, dim.height/2 - frame.getSize().height/2);
And the third one, the most customizable one, is a bit more complicated, but is the most useful. (in my opinion) :
1.) You create a JButton and add it to your panel.
2.) You add an ActionListener event to it.
3.) On your button click, you invoke the method :
frame.getLocationOnScreen(); which you need to save to a Point
variable => Point location = frame.getLocationOnScreen;
4.) After that, you invoke : System.out.println(location);, so that you can get the location on the screen that you want to put your frame
to - it will print it to the console.
5.) You delete the button and ActionListener, after you've got the x, y coordinates.
6.) You invoke : frame.setLocation(x, y);
That's it.
The code looks like this :
JButton button = new JButton();
button.setText("Get Location");
panel.add(button);
ActionListener onButton = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Point location = frame.getLocationOnScreen();
System.out.println(location);
}
};
button.addActionListener(onButton);
After you have the location, do this :
frame.setLocation(445, 195);
Hope I was helpful. ^

How to set a JPanel to a different one [duplicate]

To put it simple, there's a simple java swing app that consists of JFrame with some components in it. One of the components is a JPanel that is meant to be replaced by another JPanel on user action.
So, what's the correct way of doing such a thing? I've tried
panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();
but this won't work. What would you suggest?
Your use case, seems perfect for CardLayout.
In card layout you can add multiple panels in the same place, but then show or hide, one panel at a time.
1) Setting the first Panel:
JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());
2)Replacing the panel:
frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());
Also notice that you must do this in the Event's Thread, to ensure this use the SwingUtilities.invokeLater or the SwingWorker
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.
Remember, Java use 'copy reference by value' argument passing. So changing a variable wont change copies of the reference passed to other methods.
Also note JFrame is very confusing in the name of usability. Adding a component or setting a layout (usually) performs the operation on the content pane. Oddly enough, getting the layout really does give you the frame's layout manager.
Hope this piece of code give you an idea of changing jPanels inside a JFrame.
public class PanelTest extends JFrame {
Container contentPane;
public PanelTest() {
super("Changing JPanel inside a JFrame");
contentPane=getContentPane();
}
public void createChangePanel() {
contentPane.removeAll();
JPanel newPanel=new JPanel();
contentPane.add(newPanel);
System.out.println("new panel created");//for debugging purposes
validate();
setVisible(true);
}
}
On the user action:
// you have to do something along the lines of
myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()
myJFrame.getContentPane().add(newContentPanel)
myJFrame.getContentPane().revalidate()
Then you can resize your wndow as needed.
Game game = new Game();
getContentPane().removeAll();
setContentPane(game);
getContentPane().revalidate(); //IMPORTANT
getContentPane().repaint(); //IMPORTANT
It all depends on how its going to be used. If you will want to switch back and forth between these two panels then use a CardLayout. If you are only switching from the first to the second once and (and not going back) then I would use telcontars suggestion and just replace it. Though if the JPanel isn't the only thing in your frame I would use
remove(java.awt.Component) instead of removeAll.
If you are somewhere in between these two cases its basically a time-space tradeoff. The CardLayout will save you time but take up more memory by having to keep this whole other panel in memory at all times. But if you just replace the panel when needed and construct it on demand, you don't have to keep that meory around but it takes more time to switch.
Also you can try a JTabbedPane to use tabs instead (its even easier than CardLayout because it handles the showing/hiding automitically)
The other individuals answered the question. I want to suggest you use a JTabbedPane instead of replacing content. As a general rule, it is bad to have visual elements of your application disappear or be replaced by other content. Certainly there are exceptions to every rule, and only you and your user community can decide the best approach.
Problem: My component does not appear after I have added it to the container.
You need to invoke revalidate and repaint after adding a component before it will show up in your container.
Source: http://docs.oracle.com/javase/tutorial/uiswing/layout/problems.html
I was having exactly the same problem!! Increadible!! The solution I found was:
Adding all the components (JPanels) to the container;
Using the setVisible(false) method to all of them;
On user action, setting setVisible(true) to the panel I wanted to
show.
// Hiding all components (JPanels) added to a container (ex: another JPanel)
for (Component component : this.container.getComponents()) {
component.setVisible(false);
}
// Showing only the selected JPanel, the one user wants to see
panel.setVisible(true);
No revalidate(), no validate(), no CardLayout needed.
The layout.replace() answer only exists/works on the GroupLayout Manager.
Other LayoutManagers (CardLayout, BoxLayout etc) do NOT support this feature, but require you to first RemoveLayoutComponent( and then AddLayoutComponent( back again. :-) [Just setting the record straight]
I suggest you to add both panel at frame creation, then change the visible panel by calling setVisible(true/false) on both.
When calling setVisible, the parent will be notified and asked to repaint itself.
class Frame1 extends javax.swing.JFrame {
remove(previouspanel); //or getContentPane().removeAll();
add(newpanel); //or setContentPane(newpanel);
invalidate(); validate(); // or ((JComponent) getContentPane()).revalidate();
repaint(); //DO NOT FORGET REPAINT
}
Sometimes you can do the work without using the revalidation and sometimes without using the repaint.My advise use both.
Just call the method pack() after setting the ContentPane, (java 1.7, maybe older) like this:
JFrame frame = new JFrame();
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
....
frame.setContentPane(panel1);
frame.pack();
...
frame.setContentPane(panel2);
frame.pack();
...

LWJGL Display.setWidth/Height?

Similar to what you can do with a Java's Canvas class, I am currently trying to write a method to set an LWJGL Display's maximum size. The only problem I have run into is that LWJGL's Display class doesn't have a setWidth or setHeight method, and I can't think of an way I could write my own. My first thought was to somehow get the instance of the JFrame that the window was using, but there's no method for this either so I feel like I am SOL. I also tried using DisplayMode and just resetting the size through that, but it closes the window and reopens it every time it resizes. I am trying to write a method that'd simply resize the window as if the user was dragging it to enlarge it. Does anybody know how I could/should go about doing this? Is it even possible to get this smooth max-size effect I am looking for, considering that the display doesn't even update until you let go after dragging/resizing it manually?
If you need more control over your window, you can try using an AWT Frame as a parent to an LWJGL Canvas. This would allow your code to take advantage of default window methods, including setWidth() and setHeight() found in the Java standard libraries, prevent and control window behavior, and add listeners to run code for certain events.
First, import java.awt.* and then set up code that looks something like this:
Create a Frame and Canvas:
Frame frame = new Frame("LWJGL Game Window");
frame.setLayout(new BorderLayout());
Canvas canvas = new Canvas();
Add the Canvas to the Frame:
frame.add(canvas, BorderLayout.CENTER);
Setup LWJGL and apply it to the Canvas:
try {
Display.setParent(canvas);
frame.setPreferredSize(new Dimension(1024, 786));
frame.setMinimumSize(new Dimension(800, 600));
frame.pack();
frame.setVisible(true);
Display.create();
while(!Display.isCloseRequested() && !closeRequested)
{
// main code or call to code goes here
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
Display.update();
}
Display.destroy();
frame.dispose();
System.exit(0);
} catch (LWJGLException e) {
e.printStackTrace();
}
Not sure how much you know about Java, but from here, you could add an ActionListerner or ComponentListerner that does something if the window is resized.
Also check out the LWJGL wiki for AWT Frames. This should, at least, help to point you in the right direction.

How to set JFrame to appear centered, regardless of monitor resolution?

While working with Java, I find it hard to position my main window in the center of the screen when I start the application.
Is there any way I can do that?
It doesn't have to be vertically centered, horizontal alignment is the more important goal for me. But vertical alignment is also welcome.
Use setLocationRelativeTo(null)
This method has a special effect when you pass it a null. According to the Javadoc:
If the component is null, or the GraphicsConfiguration associated with this component is null, the window is placed in the center of the screen.
This should be done after setting the size or calling pack(), but before setting it visible, like this:
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
I always did it in this way:
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2);
where this is the JFrame involved.
You can call JFrame.setLocationRelativeTo(null) to center the window. Make sure to put this before JFrame.setVisible(true)
Just click on form and go to JFrame properties, then Code tab and check Generate Center.
As simple as this...
setSize(220, 400);
setLocationRelativeTo(null);
or if you are using a frame then set the frame to
frame.setSize(220, 400);
frame.setLocationRelativeTo(null);
For clarification, from the docs:
If the component is null, or the GraphicsConfiguration associated with this component is null, the window is placed in the center of the screen.
i am using NetBeans IDE 7.2.1 as my developer environmental and there you have an option to configure the JForm properties.
in the JForm Properties go to the 'Code' tab and configure the 'Generate Center'.
you will need first to set the Form Size Policy to 'Generate Resize Code'.
I am using NetBeans IDE 7.3 and this is how I go about centralizing my JFrame
Make sure you click on the JFrame Panel and go to your JFrame property bar,click on the Code bar and select Generate Center check box.
If you use NetBeans, simply click on the frame on the design view, then the code tab on its properties. Next, check 'Generate Center'. That will get the job done.
If you explicitly setPreferredSize(new Dimension(X, Y)); then it is better to use:
setLocation(dim.width/2-this.getPreferredSize().width/2, dim.height/2-this.getPreferredSize().height/2);
You can use this method, which allows the JFrame to be centered and full screen at the same time.
yourframe.setExtendedState(JFrame.MAXIMIZED_BOTH);
In Net Beans GUI -
go to jframe (right click on jFrame in Navigator) properties, under code, form size policy property select Generate Resize Code. In the same window, Untick Generate Position and tick Generate Size and Center.
Enjoy programming.
Ramana
I will provide 3 methods to your question :
You can either use the simplest method to center it, relative to your viewport, which is :
setLocationRelativeTo(null);
The second one, is to use :
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(dim.width/2 - frame.getSize().width/2, dim.height/2 - frame.getSize().height/2);
And the third one, the most customizable one, is a bit more complicated, but is the most useful. (in my opinion) :
1.) You create a JButton and add it to your panel.
2.) You add an ActionListener event to it.
3.) On your button click, you invoke the method :
frame.getLocationOnScreen(); which you need to save to a Point
variable => Point location = frame.getLocationOnScreen;
4.) After that, you invoke : System.out.println(location);, so that you can get the location on the screen that you want to put your frame
to - it will print it to the console.
5.) You delete the button and ActionListener, after you've got the x, y coordinates.
6.) You invoke : frame.setLocation(x, y);
That's it.
The code looks like this :
JButton button = new JButton();
button.setText("Get Location");
panel.add(button);
ActionListener onButton = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Point location = frame.getLocationOnScreen();
System.out.println(location);
}
};
button.addActionListener(onButton);
After you have the location, do this :
frame.setLocation(445, 195);
Hope I was helpful. ^

Undecorate JInternalFrame on MacOS

I am trying to undecorate a JInternalFrame, i.e. remove the default titlebar using the following code;
BasicInternalFrameUI ui = (BasicInternalFrameUI)internalFrame.getUI();
ui.getNorthPane().setPrefrredSize(new Dimension(0,0));
I works on windows but the second line throws a NullPointerException on MacOS
Any ideas why and how to get round it?
On Mac, the JInternalFrame doesn't have a north pane. Only execute the code on none Mac OS platforms;
// only remove the northpanel for none Mac OS
if(!(System.getProperty("os.name").startsWith("Mac OS"))){
BasicInternalFrameUI ui = (BasicInternalFrameUI) getUI();
ui.getNorthPane().setPrefrredSize(new Dimension(0,0));
}
So much about cross platform :-(
I don't use a Mac so I don't know what is causing the problem.
A JInternalFrame without the title bar loses its ability to be dragged. You should be able to accomplish the same goal by just adding a JPanel to the desktop. You would need to set the bounds of the panel. You might also want to use one of the internal frame custom borders on the panel:
UIManager.getBorder("InternalFrame.paletteBorder");
UIManager.getBorder("InternalFrame.optionDialogBorder");
Or maybe another option is to use:
internalFrame.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE);
This will replace the title bar with a small palette that can be used to drag the internal frame without the buttons or title.

Categories