How would you make a JComponent (panel, frame, window, etc.) fullscreen, so that it also overlaps everything on the screen including the windows start bar?
I don't want to change the resolution or anything with the graphics device like bitdepth etc, I just want to overlap everything else.
Check out this tutorial describing Java's Full-Screen mode API.
Example code (taken from the tutorial). Note that the code operates on a Window so you would need to embed your JPanel with a Window (e.g. JFrame) in order to do this.
GraphicsDevice myDevice;
Window myWindow;
try {
myDevice.setFullScreenWindow(myWindow);
...
} finally {
myDevice.setFullScreenWindow(null);
}
You can try some of the codes in this page, allowing a container to fill the screen (so it is not a solution for an individual component, but for a set of components within a container like a JFrame)
public class MainWindow extends JFrame
{
public MainWindow()
{
super("Fullscreen");
getContentPane().setPreferredSize( Toolkit.getDefaultToolkit().getScreenSize());
pack();
setResizable(false);
show();
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
Point p = new Point(0, 0);
SwingUtilities.convertPointToScreen(p, getContentPane());
Point l = getLocation();
l.x -= p.x;
l.y -= p.y;
setLocation(l);
}
});
}
...
}
You need to use the following API: http://java.sun.com/docs/books/tutorial/extra/fullscreen/index.html
Going full screen isn't as simple as making a large panel, you need to look into the underlying OS graphics. But your JPanel code should translate just fine.
I needed to search a lot, to do the same. Here is completely a working version of it by steps, so that i can find it later also, and use it.
Step 1: create a file called fullscreen.java
Step 2: copy this code and paste it as it is:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class fullscreen extends Window
{
private Button button;
public fullscreen()
{
super(new Frame());
button = new Button("Close");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
setLayout(new FlowLayout());
add(button);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(0,0,screenSize.width, screenSize.height);
}
public static void main(String[] args)
{
// This will take over your whole screen tested and works in my:
// Fedora 12/13/14
// CentOS 5.0
// if this works for you, in other platforms, please leave a comments which OS it worked.
// happy coding!
new fullscreen().setVisible(true);
}
}
Step 3: compile the code and run
Done.
If I were you I would try to make Java not draw the border of the Jframe, then make it take all the screen.
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import javax.swing.JFrame;
public class FenNoBorder extends JFrame {
public FenNoBorder () {
setUndecorated(true);
setVisible(true);
GraphicsEnvironment graphicsEnvironment=GraphicsEnvironment.getLocalGraphicsEnvironment();
Rectangle maximumWindowBounds=graphicsEnvironment.getMaximumWindowBounds();
setBounds(maximumWindowBounds);
}
}
Related
my program create a jframe > set the content pane to a jpanel > use repaint() one or more time > set the content pane to another jpanel > use some repaint() again > etc...
(note: for reasons i have to create the jframe then add the jpanel later)
but only calling setContentPane(newjpanel) doesnt allow me to use repaint() afterward and the only thing that i know will unlock it is resizing the window manually
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyJFrame extends JFrame {
private static final long serialVersionUID = 1L;
public MyJFrame() {
// default panel for visual feedback
JPanel pan = new JPanel();
pan.setBackground(Color.green);
this.setContentPane(pan);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // TODO
this.setSize(400, 400);
// other unrelated configuration stuff
// ...
this.setVisible(true);
}
public void switchPanel(JPanel pan) {
this.setContentPane(pan);
// pan.setVisible(true); doesnt work
// pan.revalidate(); neither
}
public static void main(String[] args) {
MyJFrame frame = new MyJFrame();
//...
JPanel mypan = new MyJPanel();
// there i have an IO operation to get an image, without this delay this code work just fine
// so i put this thread.sleep to simulate this delay
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
frame.switchPanel(mypan);
while (true) {
// this repaint wont work unless i change the window size
mypan.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
public static class MyJPanel extends JPanel {
private static final long serialVersionUID = 1L;
public Point pos = new Point(0, 0);
public synchronized void paintComponent(Graphics g) {
super.paintComponent(g);
// i made the square move for visual feedback
pos.x += 1;
g.fillRect(pos.x, pos.y, 10, 10);
}
}
}
this code should show a square going in direction of +x
instead it wont until the window is resized
another option i know is setting visibility of the jframe to false changing the pane then setting it to true but it is really visualy unpleasant
so my question is, how could i make it possible to add/remove jpanels at run time? (adding code in switchPanel, adding container, really anything)
(2nd note: i would like to if possible REALLY add/remove jpanels at run time, im aware of using for example a card layout and turning off and on panels visibility in it but in cant do that there)
When components are created they have a size of 0, so there is nothing to paint.
When you dynamically add a component to a visible frame, the you need to revalidate() the parent container you add the component to. This will invoke the layout manager on the parent container and the child components will be given a size/location.
Normally this would mean you revalidate() the JPanel you add the component to. However, in this case, since you are replacing the content pane, the easiest way to do that is to revalidate() the frame:
public void switchPanel(JPanel pan) {
this.setContentPane(pan);
revalidate();
}
here's a dirty fix that i found (work both for the mre and my main code)
public void switchPanel(JPanel pan) {
this.setContentPane(pan);
Dimension dim = this.getSize();
int y = dim.height;
int x = dim.width;
this.setSize(x+1,y);
this.setSize(x, y);
}
tho it seem to be the equivalent of shutting down your pc to close a window, so not very appropriate.
As for testing-reasons I tried to open a JDialog window with the panel and its contents of the main application frame. As I already had anything in there I wanted to see if I could simply set the JDialogs contentPane to the one I passed over. So in simplyfied form this came together:
testsforSO.java :
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
testsforSO frame = new testsforSO();
frame.setSize(300, 300);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("I am the Frame");
getContentPane().setLayout(new BorderLayout(0, 0));
JPanel panel = new JPanel();
panel.setLayout(null);
JButton btnRestart = new JButton("Restart");
btnRestart.setBounds(10, 10, 50, 50);
btnRestart.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
testsforSO.main(null);
dispose();
}
});
panel.add(btnRestart);
getContentPane().add(panel);
repaint();
// -----------DELETE These comments-------------
// JDialog myDialg = new JDialog(this);
// myDialg.setContentPane(panel);
// myDialg.setVisible(true);
// myDialg.setSize(300,300);
// myDialg.setLocation(new Point(250, 250));
// myDialg.setTitle("I am Dialog from within the script");
myDialog.main(panel);
}
}
and myDialog.java :
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.JDialog;
public class myDialog extends JDialog {
private static final long serialVersionUID = 7079322237622743228L;
public static void main(Container myContainer) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
myDialog frame = new myDialog(myContainer);
frame.setVisible(true);
frame.setContentPane(myContainer);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public myDialog(Container myContainer) {
setContentPane(myContainer);
getContentPane().setLayout(null);
setBounds(200,200,200,200);
}
}
When starting the main frame I assumed it would contain the restarting button as well as the dialog does. But interestingly it was only the dialog with the button.
However when hitting it, the main frame properly restarted, a second dialog was set up and it contained the button again. This time however the main frame had the button as well, just without any function. Clicking on it does absolutely nothing.
Then I tried further and checked if that behaviour would change if I added the dialog directly into the main applications code (see the commented lines) and, starting the application once again only the dialog in its own class showed the button. Even hitting this one now restarted properly but the button won't show up on any other window except the lonely declared dialog.
What am I missing here and how could I refactor my code to work properly if even at all in this manner?
Understand that Swing components can only be present in one container, and while you may see the visual residue of a component in a container, the actual component is only present in the last container added to.
Myself, if I wanted dialog and jframe to have the same content pane components, I'd create a factory method to create the contentPane, and then use it to create two unique but identical contentPanes.
Also, I'd be remiss if I didn't mention something about your use of null layouts. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
For instance, when I ran your code, this is the dialog that I saw:
You hard coded the button's size to be too small to show its text on my platform. If you had used layout managers, and called pack() on the top-level window, the button would show appropriately.
Maybe i have encountered a bug or more probably doing something wrong ;)
I try to translate the content of a user drawn JPanel using a JScrollPanel. Inside the panel the drawing i would like to access the visible area through the Graphics class getClipBounds method to improve rendering performance.
Searching on SO brings a lot results referring to JScrollPane but none is mentioning a problem with the clip bounds. Google the same.
user drawn panel
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Content extends JPanel {
#Override
protected void paintChildren(Graphics g) {
super.paintChildren(g);
// intense clip bounds dependent rendering here
System.out.println(g.getClipBounds());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(2000,2000);
}
}
main frame setup
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
public class ClipBoundsIssue {
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ClipBoundsIssue window = new ClipBoundsIssue();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public ClipBoundsIssue() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane();
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
Content content = new Content();
scrollPane.setViewportView(content);
}
}
to reproduce
Just run the code, move one of the scrollbars and inspect the console output of System.out. The following picture depicted scrolling the bar on the x axis.
actual System.out result
Which produced the following results
java.awt.Rectangle[x=0,y=0,width=416,height=244]
java.awt.Rectangle[x=416,y=0,width=16,height=244]
java.awt.Rectangle[x=432,y=0,width=15,height=244]
java.awt.Rectangle[x=447,y=0,width=16,height=244]
java.awt.Rectangle[x=463,y=0,width=15,height=244]
expected result
I would have expected to have the width of the bounds to keep the same. But it changes from 416 to 16.
The question now is
Does anybody know why this happens, or how it can be avoided??
discared WAs
A possible workaround would be to lookup the view port's view bounds. But if possible i would like to avoid the Content class making any such lookup. Another alternative would be to pass the information into the Content class, but this i would like to avoid as well.
I would have expected to have the width of the bounds to keep the same.
Why? It is so simple that it is hard to explain, but let me try.
When you scrolling, only small new portion if the JPanel is appearing if you scroll slowly.
The produced output is absolutely correct:
java.awt.Rectangle[x=0,y=0,width=416,height=244] Control is shown first time, you need to redraw it completely
java.awt.Rectangle[x=416,y=0,width=16,height=244] You scrolled to the right by 16 pixels, so only narrow strip of you control must be redrawn.
You must understand that these coordinates are related to your control which has size set to 2000x2000 pixels.
Try to scroll the window created with this code and you will see what I am talking about:
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class ScrollPaneRepaintDemo extends JPanel {
public ScrollPaneRepaintDemo() {
setPreferredSize(new Dimension(2000,2000));
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new JScrollPane(new ScrollPaneRepaintDemo()));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
#Override protected void paintComponent(Graphics g) {
Rectangle clip = g.getClipBounds();
g.setColor(new Color(new Random().nextInt()));
g.fillRect(clip.x, clip.y, clip.width, clip.height);
}
}
By the way - it works so because of JPanel's internal implementation. If you extend JComponent instead, the whole viewport will be clipped. I add also that JPanel repaints completely when resizing, its optimizations are only for scrolling.
I'm working on a project, there are JInternalFrames in the mainframe. Now, we need to let them to be JFrame. I'm considering using a JFrame to hold on JInternalFrame. The problem is that the titlebar of Internalframe is there, and user can drag it around.
Is there any way to make the Internal frame work like a pane in the JFrame?
After searching on the Internet, I found somebody removes the titlepane.
Do you have any good idea on this?
Thanks you!
update:
Maybe I was on the wrong track. The real problem is the JInternal frame can not get out of the main Frame, or any way to make it look like it's out side of the frame?
Is there any way to make the Internal frame work like a pane in the
JFrame
Im not sure by what you mean by pane, but I guess like a JPanel? Of course you can but why, would be my question, unless you want some sort of quick floating panel, but than you say you dont want it draggable? So Im bit unsure of your motives and makes me weary to answer....
The problem is that the titlebar of Internalframe is there
Well Here is code to remove the titlepane (found it here):
//remove title pane http://www.coderanch.com/t/505683/GUI/java/JInternalframe-decoration
BasicInternalFrameTitlePane titlePane =(BasicInternalFrameTitlePane)((BasicInternalFrameUI)jInternalFrame.getUI()).getNorthPane();
jInternalFrame.remove(titlePane);
and user can drag it around.
And I found this to make JInternalFrame unmovable by removing the MouseListeners which make it movable, but it is important to note its not necessary to remove the MouseListeners as the method used to make it undraggable will remove the NorthPane which the MouseListener is added too thus its unnecessary for us to remove it ourselves.:
//remove the listeners from UI which make the frame move
BasicInternalFrameUI basicInternalFrameUI = ((javax.swing.plaf.basic.BasicInternalFrameUI) jInternalFrame.getUI());
for (MouseListener listener : basicInternalFrameUI.getNorthPane().getMouseListeners()) {
basicInternalFrameUI.getNorthPane().removeMouseListener(listener);
}
And as per your title:
how to make JInternalFrame fill the Container
Simply call setSize(int width,int height) on JInternalFrame with parameters of the JDesktopPanes width and height (JDesktopPane will be sized via overriding getPreferredSize()).
Which will give us this:
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.event.MouseListener;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import javax.swing.plaf.basic.BasicInternalFrameUI;
/**
*
* #author David
*/
public class Test {
public Test() {
createAndShowGUI();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void createAndShowGUI() throws HeadlessException {
JFrame frame = new JFrame();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
final JDesktopPane jdp = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
frame.setContentPane(jdp);
frame.pack();
createAndAddInternalFrame(jdp);
frame.setVisible(true);
}
private void createAndAddInternalFrame(final JDesktopPane jdp) {
JInternalFrame jInternalFrame = new JInternalFrame("Test", false, false, false, false);
jInternalFrame.setLocation(0, 0);
jInternalFrame.setSize(jdp.getWidth(), jdp.getHeight());
//remove title pane http://www.coderanch.com/t/505683/GUI/java/JInternalframe-decoration
BasicInternalFrameTitlePane titlePane = (BasicInternalFrameTitlePane) ((BasicInternalFrameUI) jInternalFrame.getUI()).getNorthPane();
jInternalFrame.remove(titlePane);
/*
//remove the listeners from UI which make the frame move
BasicInternalFrameUI basicInternalFrameUI = ((javax.swing.plaf.basic.BasicInternalFrameUI) jInternalFrame.getUI());
for (MouseListener listener : basicInternalFrameUI.getNorthPane().getMouseListeners()) {
basicInternalFrameUI.getNorthPane().removeMouseListener(listener);
}
*/
jInternalFrame.setVisible(true);
jdp.add(jInternalFrame);
}
}
Given your requirements, I suggest you just use a simple JPanel inside your JFrame content pane.
I'm doing a project where i need some custom swing components. So far I have made a new button with a series of images (the Java Metal look doesn't fit with my UI at all). Ive implemented MouseListener on this new component and this is where my problem arises. My widget changes image on hover, click etc except my MouseListener picks up mouse entry into a the entire GridLayout container instead of into the image. So I have an image of about 200*100 and the surrounding container is about 400*200 and the mouseEntered method is fired when it enters that GridLayout section (even blank space parts of it) instead of over the image. How can I make it so that it is only fired when I hover over the image? Ive tried setting size and bounds and other attributes to no avail.
EDIT: Here's a demonstration of my issue. As you can see (sort of, colors are very similar) the bottom right button is highlighted just by entering its section of the GridlLayout. I only want it highlighted when I'm over the image actual, not the GridLayout section.
I Won't add the MouseListener methods because they just involve switching the displayed image.
public customWidget()
{
this.setLayout(new FlowLayout());
try {
imageDef=ImageIO.read(new File("/home/x101/Desktop/buttonDef.png"));
imageClick=ImageIO.read(new File("/home/x101/Desktop/buttonClick.png"));
imageHover=ImageIO.read(new File("/home/x101/Desktop/buttonHover.png"));
current=imageDef;
} catch (IOException e)
{
e.printStackTrace();
}
this.addMouseListener(this);
}
protected void paintComponent(Graphics g)
{
super.paintComponents(g);
g.drawImage(current, 0, 0, current.getWidth(), current.getHeight(), null);
}
EDIT: added code section
As an alternative, consider the The Button API, which includes the method setRolloverIcon() "to make the button display the specified icon when the cursor passes over it."
Addendum: For example,
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ButtonIconTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
private static void createAndShowGui() {
String base = "http://download.oracle.com/"
+ "javase/tutorial/uiswing/examples/components/"
+ "RadioButtonDemoProject/src/components/images/";
ImageIcon dog = null;
ImageIcon pig = null;
try {
dog = new ImageIcon(new URL(base + "Dog.gif"));
pig = new ImageIcon(new URL(base + "Pig.gif"));
} catch (MalformedURLException ex) {
ex.printStackTrace(System.err);
return;
}
JFrame frame = new JFrame("Rollover Test");
JPanel panel = new JPanel();
panel.add(new JLabel(dog));
panel.add(new JLabel(pig));
JButton button = new JButton(dog);
button.setRolloverIcon(pig);
panel.add(button);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
I assume your image contains ONLY 4 'customWidget' objects (in a 2x2 grid).
Your code is working as I would expect. Your MouseListener methods are responding to MouseEvents for 'customWidget' (not the image drawn in 'customWidget'), which is sized to take up 1/4 of the image, so they will respond when it enters the enlarged area. The error is actually in your Test program, because you are allowing the custom button widget to be larger than the image.
If you want a Test program that provides an image similar to yours, you should create a larger grid (say 4x4), and then only place your buttons in every other grid node. Place an empty component into the gaps.
Although I won't answer to your particular question, I hope this helps:
If the components just look wrong maybe you should reuse Swing components and just write a custom Look&Feel or theme.
It would certainly help ensuring the look of the application is consistent and at least you are using the right tool for the task you want to accomplish.
As a sidenote, be aware that Java comes with multiple Look&feels, including Look&Feels made to mimic the native OS theme.
See: http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html