The problem is, I am unable to make it a dimension with 800x600. In other words, when I run the program, the frame is so small that I can not do anything with it.
How can I make the frame larger?
I have set the preferred size already ans set the canvas bounds.
Then what is the problem?
public class GameCanvas extends Canvas
{
private BufferStrategy buffer = null;
public GameCanvas()
{
setBounds(0, 0, 800, 600);
setIgnoreRepaint(true);
addKeyListener(new KeyInputHandler());
requestFocus();
}
public void addNotify()
{
super.addNotify();
this.createBufferStrategy(2);
buffer = this.getBufferStrategy();
setBounds(0, 0, 800, 600);
}
}
public class GameGuiFrame extends JFrame
{
private JPanel panel = new JPanel();
private GameCanvas canvas = new GameCanvas();
public GameGuiFrame()
{
this.setName("My Game");
this.pack();
this.setResizable(false);
this.setVisible(true);
panel = (JPanel) this.getContentPane();
panel.setPreferredSize(new Dimension(750,500));
panel.setLayout(null);
panel.add(canvas);
}
}
public class GameManager
{
public static void runGameLoop()
{
GameGuiFrame container = new GameGuiFrame();
container.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
}
public class Main
{
public static void main(String [] args)
{
GameManager.runGameLoop();
}
}
Try packing the Frame after you set the preferred size of the content pane.
Not related to your question but based on the code you posted it looks like you've copied some old AWT code and are trying to use it in a Swing application.
I would suggest you only use Swing components. There is no need to use a Canvas with a BufferStrategy. Just use a JPanel it is double buffered by default. The code snippet you copied is old and that is not the way it is done in Swing.
Don't use a null layout. Swing was designed to be using with layout managers. Then the pack() method will be able to do its job properly.
There is no need to use a WindowListener to close the frame. These days people just use:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Also, the frame should be made visible AFTER components have been added to the frame.
Generally you should be use Key Bindings, not a KeyListener to listen for key events in a Swing application.
I suggest you look at the Swing tutorial for more information about the above concepts.
You call to pack() will set the frame (and components within it) to their preferred size. However, you haven't specified a preferred size. I would suggest removing your two calls to setBounds() and calling setBounds() within the main method instead of pack().
Related
I'm curious is there a way to resize window from JPanel object. I'm looking for solution for a while. Maybe I'm missing something?
I want to resize window when use changeSize() method (f.e. on button, I deleted lot code).
I've tried different methods like setSize, setPreferredSize and setBorders.
public class MAIN{
public static void main(String[] args) {
new Okno(new Panel_Saper());
}
}
public class Okno extends JFrame{
protected Okno(Panel panel) {
setResizable(true);
getContentPane();
Container cp = getContentPane();
cp.add(panel);
pack();
setDefaultCloseOperation(panel.getClose());//2 - JFrame.DISPOSE_ON_CLOSE, 3 - JFrame.EXIT_ON_CLOSE
setVisible(true);
}
}
public abstract class Panel extends JPanel {
protected int getClose() {return 2;} //2 - JFrame.DISPOSE_ON_CLOSE
}//needed for override in other place
public class Panel_Saper extends Panel {
Panel_Saper() {
setLayout(null);
setPreferredSize(new Dimension(400,400));
}
public void changeSize() {//DOESN'T WORK
SetSize(new Dimension(600,600));
setBounds(0, 0, 600, 600);
repaint();
}
}
For your custom panel it is preferred that you override the getPreferredSize() method. Every Swing component is responsible for knowing its preferred size.
If you want to change the preferred size from 400 to 600 you must have a reason for doing this. So you should have a property for your panel that you can modify.
Then your implementation of the getPreferredSize() method will check this property and return the appropriate size depending on the current state of your panel.
I made work around by closing and reopening window
Now that your component has implemented the getPreferredSize() correctly you can simple invoke pack() on the JFrame.
I want to use a JLabel in a very simple environment but I'm wondering why I have to set the location on every repaint.
Code:
public class Example {
public static void main(String[] args) {
JFrame frame = buildFrame();
TestPane pane = new TestPane();
frame.add(pane);
while (true) {
pane.repaint();
frame.setVisible(true);
}
}
private static JFrame buildFrame() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(480, 272);
frame.setVisible(true);
return frame;
}
}
public class TestPane extends JPanel {
JLabel testLabel = new JLabel("TEST");
TestPane() {
super();
add(testLabel);
testLabel.setLocation(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
testLabel.setLocation(200, 200); // without this line, the label will always be at the top center
}
}
The loop-based layout comes from various animations with images I'm doing. Why does the repaint always reset the location of all labels so I have to setLocation on every paintComponent?
why I have to set the location on every repaint.
You don't. Actually, you should never set the position or any kind of constraint of a component inside paintComponent method. paintComponent method is only for painting, not for orientation or anything else.
When you jpanel.add(myComponent, constraints) component's position will be decided by container's current LayoutManager. (When you jpanel.add(myComponent); without any constraints, the default constraints will take place, with every layout manager having its own default).
The label is placed at the top of the panel because you do not set the layout of the panel, so it has its default, which is FlowLayout. In order to change it you will have to use another layout manager with the proper constraints.
For example, in order to place it at the center of the panel, you must do:
jpanel.setLayout(new BorderLayout());
jpanel.add(myLabel,BorderLayout.CENTER);
Finally doing while(true) inside the Thread where you GUI is running, it will hang the thread, means that the GUI will be "frozen" since events cannot take place.
This is my first java project and I am trying to draw a simple rectangle on my JPanel inside my JFrame. Been trying to solve this issue with the help of the same topics on stackoverflow but still no success.
The exception I get when I run the program is java.lang.NullPointerException. From my understanding I can not draw on the JPanel itself? which is created in mainWindow.
Main:
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GameBoard game = new GameBoard();
mainWindow view = new mainWindow(game);
mainModel model = new mainModel();
mainController cont = new mainController(model, view, game);
cont.controllerInit();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
View:
public class mainWindow{
public JFrame frame;
public JPanel panel;
GameBoard game = new GameBoard();
frame = new JFrame();
frame.getContentPane().setBackground(SystemColor.control);
frame.setBounds(100, 100, 728, 435);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(game);
frame.getContentPane().setLayout(null);
panel = new JPanel();
FlowLayout flowLayout = (FlowLayout) panel.getLayout();
panel.setBounds(166, 44, 550, 349);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
Game:
public class GameBoard extends JPanel{
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawRect(200, 200, 200, 200);
}
}
Never, ever call paintComponent directly, no external source has any reason to do so. Also, what do you thing would happen if you passed it null?
You should start by having a look at Performing Custom Painting and Painting in AWT and Swing to get a better understand of how paint in Swing works.
The Swing API basically uses a delegate model, where the system delegates responsibility of the paint of each component to the component. This is achieved by the system calling the components paint method, which in-turn calls (among a few others) paintComponent.
Swing also uses a passive rendering approaching, meaning that painting occurs at the discretion of the paint system. You component is notified of the need when its paint method is called. This may occur at any time.
In order for a component to be painted, it must first be added to container which is realised on the screen (has a native peer), in most cases, this means that the component hierarchy needs to resolve to some kind of window based class, like JFrame.
So, the answer to your question is:
Read the above documentation (and get a better understanding of how the API works)
Add your GameBoard to a container which can be resolved to a window based class
Never call paint or paintComponent directly
Reflection....
private mainWindow view;
private mainModel model;
public GameBoard(mainModel m, mainWindow v)
{
view = v;
model = m;
}
To me, this makes no sense. There is no reasonable reason why GameBoard needs a reference to mainWindow. GameBoard is, in of itself, a "view". If anything, the only thing you "should" be passing to GameBoard (assuming you're trying to use a MVC) is a controller
I have tried several ways, but still havent found the solution. I have a jgraph in a frame and I want to add a Jbutton in that frame also in a specific location. However I only get one of them when i run the program, because they expand to the whole window. Any ideas how to fix this?
Thanks in advance.
public class GUIquery extends JFrame {
JFrame frame;
static JGraph jgraph;
final mxGraph graph = new mxGraph();
final mxGraphComponent graphComponent = new mxGraphComponent(graph);
public GUIquery() {
super("Test");
GraphD();
imgbtn();
}
public void GraphD() {
Object parent = graph.getDefaultParent();
graph.getModel().beginUpdate();
try {
........
}catch {
........
} finally {
graph.getModel().endUpdate();
}
getContentPane().add(graphComponent);
}
public void imgbtn() {
JPanel jpanel = new JPanel();
jpanel.setSize(100, 100);
jpanel.setLocation(1200, 60);
JButton imgbtn = new JButton("Export as Image");
imgbtn.setSize(100, 100);
imgbtn.setLocation(1200, 60);
jpanel.add(imgbtn);
add(jpanel);
}
public static void main(String[] args) {
GUIquery frame = new GUIquery();
frame.setLayout(null);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 320);
frame.setVisible(true);
}
}
Don't use null layouts. They inevitably result in trouble.
From your code snippet it is impossible to tell where you want them to be relative to each other, the following puts the button below the graph.
The content pane uses BorderLayout by default. For BorderLayout, you need to use place components at different positions:
// the default position, but it does not hurt to be explicit
add(graph, BorderLayout.CENTER);
...
// and the panel
add(jpanel, BorderLayout.SOUTH);
If the positioning is not what you want, take a look at the visual guide to layout managers to pick the layout manager that suits your needs best.
In the button panel the setLocation() and setSize() calls are useless. The layout manager of the panel is responsible for setting the button's bounds. If the default FlowLayout is not what you want for it, use the guide to pick another for the panel too.
I want to paint the contents of a JFrame onto another frame. Currently, I only get it to work if the JFrame is visible.Is there a way to paint a hidden JFrame?
Additional info:In my project I need to be able to rotate and scale windows. I do not want to write my own window-api, so I thought I might be able to just paint JFrames or similar container classes in a rotated way (which the Graphics2D-API supports perfectly well). It would be awesome to be able to use standard JFrames for that, but a custom frame extending a JFrame would also be OK..
public class JFTest extends JFrame {
private JFrame frameToPaint = null;
public static void main (String[] args) {
new JFTest ();
}
public JFTest () {
// some basic initialization
super ("Container");
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setExtendedState (JFrame.MAXIMIZED_BOTH);
add (new JPanel () {
#Override public void paintComponent (Graphics g) {
super.paintComponent (g);
// painting the child frame's contents onto this frame
if (frameToPaint != null) frameToPaint.getRootPane().paintAll (g);
}
});
setVisible (true);
// initializing some test-frame that will get painted onto the container
frameToPaint = new JFrame ("child");
frameToPaint.setSize (200, 100);
frameToPaint.add (new JLabel ("test"));
frameToPaint.addComponentListener (new ComponentAdapter() {
#Override public void componentResized (ComponentEvent e) { repaint (); }
#Override public void componentHidden (ComponentEvent e) { repaint (); }
});
// magic line. an invisible frame will not get painted! why??
frameToPaint.setVisible (true);
}
}
Hint 1: JFrame's setDefaultLookAndFeelDecorated(false)/setUndecorated(true) might be of use for a window without caption and borders;
Hint 2: as setGlassPane/setLayeredPane/setOpaque(false) might be of use for a second "layer".
I want to get the graphical contents of a frame without having to make the frame visible for the user
The Screen Image class should help. Although I think it will only work for the "content pane" of the frame and not the entire frame (with the title bar and borders) unless you use a decorated frame.
1) you have to use proper LayoutManager, not setSize() or setBounds()
2) if is there null LayoutManager used then Container returns any size after setVisible(true);
3) if is there used proper LayoutManager, then Container return its Size after call pack();, in other hands this container couldn't be visible on the screen ( meaning setVisible(true); )
4) JComponents must to returns PrefferedSize for example