When I run the below code, I am unable to see the background color as red. It's showing default one. Is there anything that I have to add to these lines?
import java.awt.*;
import java.awt.Graphics;
import javax.swing.*;
public class gfix extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(80, 100, 150, 75);
}
public static void main(String[] args){
gfix gg=new gfix();
JFrame frame = new JFrame("RISK");
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(null);
frame.add(panel);
JButton button = new JButton("test");
button.setBounds(100, 100, 150, 150);
panel.add(button);
frame.setVisible(true);
}
}
Your are overriding painGraphics() in gfix class so add gfix class object into your frame not Java provided JPanel class object.
gfix gg=new gfix();
JFrame frame = new JFrame("RISK");
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JPanel panel = new JPanel(); Not needed
//panel.setLayout(null);
frame.add(gg);
JButton button = new JButton("test");
button.setBounds(100, 100, 150, 150);
gg.add(button);
frame.setVisible(true);
for g.fillRect(80, 100, 150, 75); give proper panel bounds to fill complete panel background. OR use int width = getWidth();
int height = getHeight(); in paintGraphics to get actual height and width.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class gfix {
public static void main(String[] args) {
JFrame frame = new JFrame("RISK");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBackground(Color.RED);
frame.add(panel);
JButton button = new JButton("test");
// adjust numbers as needed
button.setMargin(new Insets(20,40,20,40));
panel.add(button);
// adjust numbers as needed
panel.setBorder(new EmptyBorder(10,40,50,200));
frame.pack();
frame.setVisible(true);
}
}
Other tips:
Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or combinations of them along with layout padding and borders for white space.
Provide ASCII art or a simple drawing of the intended layout of the GUI at minimum size, and if resizable, with more width and height - to show how the extra space should be used.
Please learn common Java nomenclature (naming conventions - e.g. EachWordUpperCaseClass, firstWordLowerCaseMethod(), firstWordLowerCaseAttribute unless it is an UPPER_CASE_CONSTANT) and use it consistently.
Related
The problem is that I can't position the button where I want to. So I wrote this code to set again the location:
button.setLocation(new Point(100, 60));
import javax.swing.*;
import java.awt.*;
public class gui {
public static void main(String [] args){
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setBackground(Color.ORANGE);
frame.add(panel);
JButton button = new JButton("Button");
button.setPreferredSize(new Dimension(200,25));
button.setLocation(new Point(100, 60));
panel.add(button);
frame.setSize(new Dimension(500,400));
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("GUI App");
frame.setResizable(false);
frame.setVisible(true);
}
}
You have to use the method setBounds()! This method requires 4 parameters: The x & y coordinate and the width and height your button should have. Also you have to set the Layout to null... So try this:
button.setBounds(100, 60, 100, 50) //just an example
frame.setLayout(null)
add below to your component:
//JPanel layout
panel.setLayout(null);
// postioning
button.setLocation(100,60);
As panel.setLayout(null) set your content panel to use absolute layout. Which you'd always have to set your component's bounds explicitly by using setBounds method.
Better to choose here the most suitable layout than using absolute layout.
ex:panel.setLayout(new FlowLayout());
I am designing a Java app with Swing, and I have trouble designing the GUI without a layout.
My purpose is to design a GUI with one JPanel and four JButtons. I've done the math to set buttons and panel on the right place and coded like the following:
import java.awt.*;
import javax.swing.*;
public class MainFrame extends JFrame {
public MainFrame() {
this.setTitle("Example Frame");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
JPanel randomPanel = new JPanel();
randomPanel.setOpaque(true);
randomPanel.setBackground(Color.RED);
randomPanel.setBounds(10, 10, 430, 530);
JButton addButton = new JButton("Add");
addButton.setBounds(10, 550, 100, 40);
addButton.setBackground(Color.GRAY);
JButton deleteButton = new JButton("Delete");
deleteButton.setBounds(120, 550, 100, 40);
deleteButton.setBackground(Color.GRAY);
JButton refreshButton = new JButton("Refresh");
refreshButton.setBounds(230, 550, 100, 40);
refreshButton.setBackground(Color.GRAY);
JButton devButton = new JButton("Developer");
devButton.setBounds(340, 550, 100, 40);
devButton.setBackground(Color.GRAY);
this.add(randomPanel);
this.add(addButton);
this.add(deleteButton);
this.add(refreshButton);
this.add(devButton);
this.setSize(900, 600);
this.setResizable(false);
this.setVisible(true);
}
public static void main(String[] args) {
new MainFrame();
}
}
Following to the code, the components are expected to be placed as following:
However, the actual form was displayed as following:
The components exceed the form, which does not match with the expected look.
What is the problem of this and what should be done for an accurate placement of components?
There are two main problems...
setLayout(null)
setSize
What you've not taken into account is the fact that the amount of space available to the content of the window, is the size of the window MINUS the frame decorations.
Pixel perfect layouts are an illusion in modern UI development and are best avoided.
You could have a look at:
What's wrong with the Null Layout in Java?
Why is it frowned upon to use a null layout in Swing?
Why null layout and absolute positions are bad practice in Java Swing?
for more details.
A better solution is to make use one or more available layout managers. The example below simply makes use of BorderLayout and GridLayout with the help of EmptyBorder to provide some padding
See Laying Out Components Within a Container for more details
Benefits
Adaptable layout:
The example uses pack to "pack" the window around the content, automatically, without you having to adapt your code to the currently running OS (or frame decorations provided by different look and feels)
The user can change the size of the window and the content will resize automatically - bonus to the user.
The layout will adapt to the user's system settings, so if they are using a font larger then you've designed for, it won't completely blow up in your face
Want to add more buttons? No worries, knock yourself out, just add more buttons, the layout will adapt automatically, no need to "pixel push" ever component on the screen
Runnable example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
add(new SizablePane(430, 530));
JPanel buttonPane = new JPanel(new GridLayout(1, 3, 20, 0));
buttonPane.setBorder(new EmptyBorder(10, 0, 0, 0));
buttonPane.add(new JButton("Add"));
buttonPane.add(new JButton("Delete"));
buttonPane.add(new JButton("Refresh"));
buttonPane.add(new JButton("Developer"));
add(buttonPane, BorderLayout.SOUTH);
}
}
public class SizablePane extends JPanel {
private Dimension size;
public SizablePane(int width, int height) {
size = new Dimension(width, height);
setBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return size;
}
}
}
Need to add more buttons? Easy...
JPanel buttonPane = new JPanel(new GridLayout(1, 0, 20, 0));
buttonPane.setBorder(new EmptyBorder(10, 0, 0, 0));
buttonPane.add(new JButton("Add"));
buttonPane.add(new JButton("Delete"));
buttonPane.add(new JButton("Refresh"));
buttonPane.add(new JButton("Developer"));
buttonPane.add(new JButton("Some"));
buttonPane.add(new JButton("More"));
buttonPane.add(new JButton("Buttons"));
I'm quite late, I don't think this will be helpful to OP anymore... But to anyone else in the same situation.
As others mentioned, when you setSize on a JFrame, that includes the title bar and borders. There's a way to get the size values for those, but... If you want to lay things out manually in your content pane, why not prepare a content pane first, then add it to the JFrame?
class MainPanel extends JPanel {
public MainPanel() {
setLayout(null);
setPreferredSize(new Dimension(900, 600));
// JFrame will have some layouting going on,
// it won't listen to setSize
JPanel randomPanel = new JPanel();
randomPanel.setOpaque(true);
randomPanel.setBackground(Color.RED);
randomPanel.setBounds(10, 10, 430, 530);
JButton addButton = new JButton("Add");
addButton.setBounds(10, 550, 100, 40);
addButton.setBackground(Color.GRAY);
JButton deleteButton = new JButton("Delete");
deleteButton.setBounds(120, 550, 100, 40);
deleteButton.setBackground(Color.GRAY);
JButton refreshButton = new JButton("Refresh");
refreshButton.setBounds(230, 550, 100, 40);
refreshButton.setBackground(Color.GRAY);
JButton devButton = new JButton("Developer");
devButton.setBounds(340, 550, 100, 40);
devButton.setBackground(Color.GRAY);
this.add(randomPanel);
this.add(addButton);
this.add(deleteButton);
this.add(refreshButton);
this.add(devButton);
}
public static void main(String[] args) {
JFrame mainFrame = new JFrame();
mainFrame.setTitle("Example Frame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setContentPane(new MainPanel());
mainFrame.pack();
mainFrame.setResizable(false);
mainFrame.setVisible(true);
}
}
If you mess with JFrame directly you're sort of bypassing the component system. Whereas this way, you're doing components just fine! Now, you have a JFrame fit to a single child panel, which has some things laid out manually.
This is how I normally do things, in such a situation.
P.S. "Don't lay things out manually, just use layout managers" is not something you can apply everywhere. You may need custom components sometimes, especially for something like a video game, where you have a game screen that you're custom rendering. Inside the game screen, you would be doing manual layout. They can coexist just fine, as long as you know which is which.
You need to override the getInsets() method of the underlying JFrame.
#Override
public Insets getInsets() {
return new Insets(0, 0, 0, 0);
}
Take a look at this question for more information.
I want to make an overlay window that has a transparent frame with non transparent children. I was successful when making the transparent window and even was successful when adding a test child to see if it work. But as soon as I replace that test code with my paintComponent... I get a white background. Anyone know why?
package blahh;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;;
public class LoadingFrame {
public static void main(String[] args) {
LoadingFrame Class = new LoadingFrame();
Class.frameChar();
}
public void frameChar(){
JFrame frame = new JFrame();
B b = new B();
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setAlwaysOnTop(true);
frame.setPreferredSize(new Dimension(500, 500));
frame.getContentPane().setLayout(new java.awt.BorderLayout());
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//frame.getContentPane().add(new JLabel("test code");
frame.add(b);
frame.pack();
}
public class B extends JPanel{
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawRect(0, 0, 100, 100);
}
}
}
JPanel is opaque by default, combined with BorderLayout, this will make it cover the entire frame, making it appear opaque. You need to call setOpaque(false) on it to make it see through
JFrame frame = new JFrame();
B b = new B();
b.setOpaque(false);
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setAlwaysOnTop(true);
// I'd prefer to override getPreferredSize of B
frame.setPreferredSize(new Dimension(500, 500));
frame.setLocationRelativeTo(null);
frame.add(b);
frame.pack();
frame.setVisible(true);
ps- You should also call setVisible last where possible, it just reduces the possibility of your components not showing up randomly
i am writing simple code with GUI that should have one text area which should be scrollable. So far so good.
I created my frame and the text area and i can write in it ok. Next I created my ScrollPane and added the TextArea in it, then added the ScrollPane to the frame but nothing shows.
Here is the code i have at this point:
JFrame frame = new JFrame();
frame.setBounds(100, 100, 325, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
//textArea
JTextArea textArea = new JTextArea();
textArea.setEnabled(true);
textArea.setEditable(true);
JScrollPane scroll = new JScrollPane(textArea,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
textArea.setBounds(10, 101, 272, 149);
textArea.setWrapStyleWord(true);
frame.getContentPane().add(scroll);
change
frame.getContentPane().setLayout(null);
to
frame.getContentPane().setLayout(new BorderLayout());
and you are done
You have to set the bounds to the component that is being added to the content pane of the frame. In this case, it should be: scroll.setBounds(10,101,271,149).
However, I strongly recommend to not use null layout. Use a layout manager of your choice, BorderLayout for instance. In this case you don't have to worry about the bounds, it will fit the frame size (it will resize when you change the size of the frame). Here's your example, tweaked a little bit:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setBounds(100, 100, 325, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
// textArea
JTextArea textArea = new JTextArea();
textArea.setEnabled(true);
textArea.setEditable(true);
JScrollPane scroll = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
textArea.setWrapStyleWord(true);
frame.getContentPane().add(scroll, BorderLayout.CENTER);
frame.setVisible(true);
}
}
I'm still learning however by looking at this case.
I have couple of issues:
There is issue with setting bounds of textArea
Layout of frame/container should not be set to null.
I have removed this sentence, and I tried this code, it displays desired textArea.
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/*
* Tester class
*/
public class GuiTester extends JFrame{
public static void main(String[] args) {
// create new instance of JFrame
GuiTester s = new GuiTester();
// set the frame to be visible
s.setVisible(true);
}
/**
* Tester constructor calling method which initialise all widgets.
*/
GuiTester() {
//
invokeWidget();
}
/*
* This code is yours, just removed setting up the values of container and did that straight on the frame.
*/
void invokeWidget() {
setBounds(100, 100, 325, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JTextArea textArea = new JTextArea();
textArea.setEnabled(true);
textArea.setEditable(true);
JScrollPane scroll = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
textArea.setWrapStyleWord(true);
add(scroll);
}
}
This is the line that was causing issues, as well as setting layout Manager to null.
// textArea.setBounds(10, 101, 272, 149);
I hope I helped, and if I'm wrong please correct me as well.
So I set the setSize(500,500).. add some panels, the sum of panels Y is 500 like the JFrame but executing it shows an count Y of 525 am I missing something?
JPanel panel = new JPanel();
panel.setLayout(null);
getContentPane().add(panel);
//--------------------
JPanel top_panel = new JPanel();
top_panel.setLayout(null);
top_panel.setBackground(Color.blue);
top_panel.setBounds(0, 0, 500, 40);
panel.add(top_panel);
//------------------------------
JPanel middle_panel = new JPanel();
middle_panel.setLayout(null);
middle_panel.setBackground(Color.yellow);
middle_panel.setBounds(0, 40, 500, 385);
panel.add(middle_panel);
//-----------------------------
JPanel bottom_panel = new JPanel();
bottom_panel.setLayout(null);
bottom_panel.setBackground(Color.black);
bottom_panel.setBounds(0, 425, 500, 75);
panel.add(bottom_panel);
setSize(500,500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setLocationRelativeTo(null);
40+385+75 = 500 but to show all the panels i must
setSize(500,525);
then it fits
here's an image:
The frame size is the light blue rectangle outside bounds including the title bar. Your panels are appearing in the inner bounds which is frame size less than the frame border and frame title bar. Do you see how your marked space at the bottom is strangely the same height as the title bar?
After adding your panels/component to the frame and just before calling frame.setVisible(true), call frame.pack().
It would be also preferable if you embrace a layout manager (such as FlowLayout) and when necessary call setPreferredSize and let the layout manager do the layout. Normally one would call setPreferredSize over setBound, setSize, setMininumSize, setMaximumSize.
import javax.swing.*;
import java.awt.*;
public class FrameSize {
private JFrame frame;
FrameSize create() {
frame = createFrame();
frame.getContentPane().add(createContent());
return this;
}
private JFrame createFrame() {
JFrame frame = new JFrame(getClass().getName());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
return frame;
}
void show() {
// frame.setSize(500, 500);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
private Component createContent() {
JPanel panel = new JPanel(null);
JPanel topPanel = new JPanel(null);
topPanel.setBackground(Color.blue);
topPanel.setBounds(0, 0, 500, 40);
panel.add(topPanel);
JPanel middlePanel = new JPanel(null);
middlePanel.setBackground(Color.yellow);
middlePanel.setBounds(0, 40, 500, 385);
panel.add(middlePanel);
JPanel bottomPanel = new JPanel(null);
bottomPanel.setBackground(Color.black);
bottomPanel.setBounds(0, 425, 500, 75);
panel.add(bottomPanel);
panel.setPreferredSize(new Dimension(500, topPanel.getBounds().height + middlePanel.getBounds().height + bottomPanel.getBounds().height));
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new FrameSize().create().show();
}
});
}
}
You shouldn't be setting size or calling setSize(...) or setBounds(...) as that's setting you up for similar problems in the future, or worse problems when you try to show your GUI on a different platform. Instead let the preferredSizes of your components and the layout managers do this work for you. If you absolutely must set the size of a component, then override getPreferredSize() and return a Dimension that is calculated to work for you. And yes, as per javajon, you should call pack() on the JFrame before displaying it.
For more discussions on the null layout, please read what one of the best Swing experts on this site, MadProgrammer, has to say in his answer here.