I am trying to re-size my JFrame in only one dimension (width in this case) and I found this question JFrame re-sizable height ONLY which gave me a good answer for doing so;
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
setSize(new Dimension(preferredWidth, getHeight()));
super.componentResized(e);
}
});
and I edited it slightly so that instead of locking width it locked height to a certain size and allowed width to be re-sizable.
import java.awt.*;
import java.awt.event.*;
import java.awt.Dimension;
import java.awt.Component;
import javax.swing.*;
import java.io.*;
import java.lang.*;
public class mcve
{
JFrame numberConversionWindow = new JFrame("Number Conversion");
public void numberConvertGUI()
{
numberConversionWindow.setBounds(10, 10, 420, 300);
numberConversionWindow.addComponentListener(new ComponentAdapter()
{
#Override
public void componentResized(ComponentEvent e)
{
numberConversionWindow.setSize(new Dimension(numberConversionWindow.getWidth(), 300));
super.componentResized(e);
numberConversionWindow.repaint();
}
});
numberConversionWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
numberConversionWindow.setLayout(new GridLayout(1,1));
numberConversionWindow.setVisible(true);
}
public static void main(String[] args)
{
mcve mc = new mcve();
mc.numberConvertGUI();
}
}
However there is a problem with this code. It often glitches. As I start to re-size it to make it wider there is a black line which flickers just before the frame re-sizes.
The next glitches are caused when re-sizing the height. It may just leave a large black area instead of snapping back to 300, and sometimes it will not snap back at all.
So my question is how can I improve this code to prevent these glitches from happening and instead of just having a height which it will snap back to can I disable the ability to re-size the height? If I can disable this ability, how would I do so?
Edit
I have also tried the following code
numberConversionWindow.setMinimumSize(new Dimension(420, 300));
numberConversionWindow.setMaximumSize(new Dimension(numberConversionWindow.getWidth(), 300));
However this still lets me re-size the height of the JFrame.
Any Help would be greatly appreciated
Edit 2
I have attempted to try and use another answer from JFrame re-sizable height ONLY. My problem for this attempt is a can't find symbol question.
I have the code
public class NumberConverter
{
...
static
{
if (System.getProperty("sun.arch.data.model").equals("32"))
{ // 32-bit JVM
System.loadLibrary("my32bitdll");
System.out.println("Running 32-bit JVM");
}
else
{
// 64-bit JVM
System.loadLibrary("my64bitdll");
System.out.println("Running 64-bit JVM");
}
}
//public static native int getComponentHWND(numberConversionWindow);
//public static native int setMinMaxResizeBoundaries(getComponentHWND, 420, 300, numberConversionWindow.getWidth(), 300);
public void numberConvertGUI()
{
numberConversionWindow.setBounds(10, 10, 420, 300);
int hwndForJFrame = getComponentHWND(numberConversionWindow);
numberConversionWindow.setMinMaxResizeBoundaries(hwndForJFrame, 420, 300, numberConversionWindow.getWidth(), 300);
...
}
public static void main(String[] args)
{
NumberConverter nC = new NumberConverter();
nC.numberConvertGUI();
}
}
When I compile I get the errors cannot find symbol - method setMinMaxResizeBoundaries(int,int,int,int,int) and cannot find symbol - getComponentHWND(numberConversionWindow). I would greatly appreciate someone explaining to me how I am meant to use setMinMaxResizeBoundaries & getComponentHWND properly, and how I am meant to input it in my code. As in wether I am meant to use the public static native int or I am meant to put it in the void numberConvertGUI()
The original answer on JFrame re-sizable height ONLY is
static {
if (System.getProperty("sun.arch.data.model").equals("32"))
{ // 32-bit JVM
System.loadLibrary("my32bitdll");
System.out.println("Running 32-bit JVM");
} else {
// 64-bit JVM
System.loadLibrary("my64bitdll");
System.out.println("Running 64-bit JVM");
}
}
// Sets a window to never be resized above or below these minimum widths/heights
public static native int setMinMaxResizeBoundaries(int hwnd, int minWidth, int minHeight, int maxWidth, int maxHeight);
Extra bit of code
// Returns the HWND for the specified component, or -1 if does not exist
public static native int getComponentHWND(Component c);
The short answer is you can't. In Swing all events go to your Java code, then update the on screen graphics... except for resizing windows. The window itself is a native control. Events go to the window first, then to the Java side. Your original code works on the Java side so the window has already resized by the time you size it back. That's what causes the glitchy behavior.
The only way around this (short of digging into C++ native code) is to disable native window decorations and render your own resize handles. Then your code would receive the resize events before the native window does and the glitches would go away. Not a trivial amount of work, but it might be feasible depending on your use case.
Related
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.
public static void main(String args[]){
JFrame frame = new JFrame();
frame.setExtendedState(JFrame.MAXIMISED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
I've used this code to maximise a JFrame, but instead of actually maximising the frame, it just sets the window size to that of the screen, without actually changing the state, so clicking the maximize button doesn't actually downscale it again.
Am I using the wrong command or something?
You have an error in frame.setExtendedState(JFrame.MAXIMISED_BOTH);
You should write frame.setExtendedState(JFrame.MAXIMIZED_BOTH); instead
Have you tried this?
f.setExtendedState(f.getExtendedState() | JFrame.MAXIMIZED_BOTH);
Based on your provided example and run on Windows 7...
"Maximised" state (this is cropped version of window as the original is quite large)
"Normal" state
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ExtendedFrame {
public static void main(String[] args) {
new ExtendedFrame();
}
public ExtendedFrame() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
// frame.setExtendedState(JFrame.MAXIMISED_BOTH);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
You must want it maximized by default. Because the maximize button works out-of-the-box.
frame.setExtendedState(JFrame.MAXIMIZED_BOTH) works on Linux x64. Here's the program I tested with:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test implements ActionListener {
public static void main(String... args) {
new Test();
}
private JFrame frame;
public Test() {
frame = new JFrame();
frame.add(new JLabel("Hi!"), BorderLayout.CENTER);
JButton button = new JButton("maximize");
button.addActionListener(this);
frame.add(button, BorderLayout.SOUTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
This worked for me:
We need to combine the setSize () and setExtendedState together
JFrame frame=new JFrame();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH); // aligns itself with windows task bar
// set maximum screen
frame.setSize((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(), (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight());
You should use this when applying changes
frame.setResizable(true);
Seven years late is better than never, right?
The question does not provide an SSCCE presumably because this is not all of the code involved. The tiny fragment of code provided work as it is, so practically all previous answers are saying "works for me". So, the problem certainly lies with the rest of the code, which is not shown.
We cannot be sure what the rest of the code does, but I suspect that it tries to persist the state and bounds of the frame, and to restore that state and bounds later, and that is what fails. The OP did not receive an answer 7 years ago because they did not explain what the actual problem was, but this question will be viewed by many more, so here it goes:
In theory, persisting the state and bounds of a frame should be piece of cake, but in practice it is not.
This is a very common problem in GUI applications, and it is basically due to a common mistake on behalf of the programmer. However, it should be noted that various widely used GUI frameworks (and certainly both Swing and SWT in the Java world) operate in a specific perverse way which makes it a very easy mistake to make.
The problem begins with the fact that these frameworks do not support a 'maximized' event, (duh!) so the only way you can detect that your frame has been maximized is to listen to the 'resized' event. So, you are presumably persisting the state and dimensions of your frame from within your 'resized' event handler.
The problem is further compounded by the fact that once the 'resized' event has occurred as a result of maximizing the frame, the frame bounds are the maximized bounds of your frame, which are irrelevant, and you will be shooting yourself in the foot if you make the mistake of persisting them.
So, the solution is to manually keep track of the "normal state" bounds of your frame, and only persist those. This can be accomplished as follows:
addComponentListener( new ComponentAdapter()
{
#Override public void componentResized( ComponentEvent e )
{
if( (getExtendedState() & MAXIMIZED_HORIZ) == 0 )
normalStateBounds.width = getWidth();
if( (getExtendedState() & MAXIMIZED_VERT) == 0 )
normalStateBounds.height = getHeight();
stateAndOrSizeChanged();
}
#Override public void componentMoved( ComponentEvent e )
{
if( (getExtendedState() & MAXIMIZED_HORIZ) == 0 )
normalStateBounds.x = getX();
if( (getExtendedState() & MAXIMIZED_VERT) == 0 )
normalStateBounds.y = getY();
stateAndOrSizeChanged();
}
} );
...where:
normalStateBounds is defined as private final Rectangle normalStateBounds = new Rectangle(); and contains the bounds of your component when in the "normal" (i.e. not minimized, nor maximized) state
stateAndOrSizeChanged() is your function which handles persisting the state and bounds of your frame, being careful to only persist normalStateBounds instead of the values returned by getX(), getY(), getWidth(), and getHeight().
When loading the state and bounds from persistence, you can simply invoke setBounds() followed by setExtendedState(), and you should do that before invoking setVisible( true ) to avoid the possibility of your frame appearing restored for a blink of an eye before maximizing. The call to setBounds() will set the non-maximized bounds, and the call to setExtendedState() might maximize your frame, but if you then restore it, it will assume the non-maximized bounds that you have set.
It works for me running Java 7 on a WinXP machine.
For the record, this is what an SSCCE should look like:
import javax.swing.*;
public class JFrameExtendedDemo
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
// Then:
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
});
}
}
In Java, is there a way to have a window that is "Always on top" regardless if the user switches focus to another application? I've searched the web, and all of the solutions lean to some sort of JNI interface with native bindings. Truly this can't be the only way to do it?.. or is it?
Try this method of the Window class:
Window.setAlwaysOnTop(boolean)
It works the same way as the default in the Windows TaskManager: switch to another app but it shows always on top.
This was added in Java 1.5
Sample code:
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Annoying {
public static void main(String[] args) {
JFrame frame = new JFrame("Hello!!");
// Set's the window to be "always on top"
frame.setAlwaysOnTop( true );
frame.setLocationByPlatform( true );
frame.add( new JLabel(" Isn't this annoying?") );
frame.pack();
frame.setVisible( true );
}
}
Window remains on top even when is not active
From my observation I found that AlwaysOnTop privilege is given to the latest process which requested to be always on top.
So, if you have an application which setAlwaysOnTop(true) and later another application uses this option, the privilege is given to the second application. In order to work around this I have set the setAlwaysOnTop(false) and again setAlwaysOnTop(true) whenever any window comes on top of the current window.
I've checked it with wordweb in windows. WordWeb is one of the applications which uses AlwaysOnTop option from the OS
I'm not sure about if it works properly with your game scenario.
Warning: I'm not aware of the side effects.
Here is the code example:
import java.awt.event.*;
import javax.swing.*;
public class MainWindow extends JFrame implements WindowFocusListener
{
public MainWindow()
{
addWindowFocusListener(this);
setAlwaysOnTop(true);
this.setFocusable(true);
// this.setFocusableWindowState(true);
panel = new JPanel();
//setSize(WIDTH,HEIGHT);
setUndecorated(true);
setLocation(X,Y);
setExtendedState(MAXIMIZED_BOTH);
setVisible(true);
}
public void windowGainedFocus(WindowEvent e){}
public void windowLostFocus(WindowEvent e)
{
if(e.getNewState()!=e.WINDOW_CLOSED){
//toFront();
//requestFocus();
setAlwaysOnTop(false);
setAlwaysOnTop(true);
//requestFocusInWindow();
System.out.println("focus lost");
}
}
private JPanel panel;
private static final int WIDTH = 200;
private static final int HEIGHT = 200;
private static final int X = 100;
private static final int Y = 100;
public static void main(String args[]){
new MainWindow();}
}
dont use setFullScreenWindow,just get the screen size and then setSize, and everything will be fine.
I am making a simple Java Swing GUI chessboard where the player can drag and drop pieces. The problem is that, because of the border around the frame (with the title on top, maximize/minimize/close buttons, etc), the coordinates are skewed off - (0, 0) is the upper-left-hand corner of the frame, that is, a little above the X button, but the GUI starts building itself right below the title bar, so the GUI doesn't align with the coordinates, and things do not end up working the way they should. Additionally, when I set the size of the frame to, for instance, 100 x 100, the lower part and some of the right-hand part of my GUI is cut off because the frame doesn't compensate for its border. When I run it as an applet, I don't have this problem, but I don't want to do that. How can I either get rid of that border around my frame window so I can just have the plain GUI, or have the coordinates set themselves up properly?
sscce:
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
public class class1 extends JFrame{
public class1(){
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent evt){
System.out.print(evt.getPoint());
}
});
}
public static void main(String[] args){
class1 c = new class1();
c.setTitle("Test");
c.setSize(320, 320);
c.setLocationRelativeTo(null);
c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
c.setVisible(true);
}
}
It's hard to know what is wrong with your code without the code, but I do know that if you go the easy way by using various layout managers, and let these managers do the laying out of components for you and the sizing of things as well, including calling pack() on the JFrame, usually things fall easily and well into place. So again, don't set the size of anything, but rather let the components' preferred sizes and the layout managers do this for you.
If this advice doesn't help, please give us more information and code, preferably an sscce, a small compilable and runnable program that doesn't do anything other than demonstrate your problem.
Edit: I am assuming that this is a Swing GUI. Please verify if this is so.
Edit 2: One problem you're having is that you're setting the size of a JFrame not taking into account its "decorations" including the menu bar, the resize/maximize/close icon. Again, you shouldn't be setting sizes directly, but if you must better override the getPreferredSize() method of the JPanel that holds your grid.
Edit 3: For example:
import java.awt.*;
import javax.swing.*;
public class Grid extends JPanel {
public static final Color DARK_COLOR = Color.red.darker().darker().darker();
public static final Color LIGHT_COLOR = Color.lightGray.brighter();
public static final int SQUARE_SIDE = 60;
private static final int ROW_COUNT = 8;
#Override
public Dimension getPreferredSize() {
return new Dimension(ROW_COUNT * SQUARE_SIDE, ROW_COUNT * SQUARE_SIDE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < ROW_COUNT; i++) {
for (int j = 0; j < ROW_COUNT; j++) {
Color c = (i % 2 == j % 2) ? LIGHT_COLOR : DARK_COLOR;
g.setColor(c);
int x = i * SQUARE_SIDE;
int y = j * SQUARE_SIDE;
g.fillRect(x, y, SQUARE_SIDE, SQUARE_SIDE);
}
}
}
public Grid() {
// TODO Auto-generated constructor stub
}
private static void createAndShowGui() {
Grid mainPanel = new Grid();
JFrame frame = new JFrame("Grid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
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);
}
}