I want to create menu buttons in Screen class and add menu to frame then. I don't know what is wrong with it. How to create buttons in other class and add it to to the frame?
My frame class:
import java.awt.*;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Start extends JFrame {
public static String title = "Bozenka";
public static Dimension size = new Dimension(700,500);
public static String backgroundPath = "/home/alpha_coder/Eclipse/Bozenka/images/bg.jpg";
public Start(){
setTitle(title);
setSize(size);
setLayout(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setLayout(null);
setResizable(false);
initialization();
}
public void initialization(){
Screen screen = new Screen();
screen.setBounds(20, 20, 660, 60);
add(screen);
try {
setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File(backgroundPath)))));
setBackground(Color.WHITE);
} catch (IOException e) {
System.out.println("Image doesn't exist");
}
setVisible(true);
}
public static void main(String[] args){
Start start = new Start();
}
}
The class where I want to create a menu:
import java.awt.*;
import javax.swing.*;
public class Screen extends JPanel{
public JButton test;
public Screen(){
setBackground(Color.pink);
test = new JButton("test");
test.setBounds(2, 2, 40, 10);
}
}
Most important: get rid of setLayout(null) and setBounds(...) as that will lead to an extremely difficult to create and adjust GUI. Learn and use the layout managers.
Create your JButtons in your new class, Screen
add them to this, the Screen JPanel but first give it a decent layout manager, such as a GridLayout,
In another class, create an instance of your JFrame class and an instance of the Screen object, and add the Screen JPanel to your JFrame's contentPane in whatever desired location you want, be it BorderLayout.CENTER or one of the other locations.
Again, most important: google and study the layout manager tutorial. Here's the link.
Note, a major problem with your current code is that you add your JButton to nothing. It needs to be added to Screen, to this for your code to work in any way.
Related
I have been practicing my code with Java Swing and have gotten decent on controlling where to place some items, such as labels and or buttons, but I was wondering if you can do the same with classes? I have just a simple class with enough code to put a button in it and that's it, that I am trying to create an instance of the class and then control for to put on the left and right side but when I do, all it does is create two separate windows with the button in the middle and that's it. Am I doing something wrong, or can you not do classes the same way?
The code:
import java.awt.Color;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Fun extends JFrame
{
private final int WIDTH = 500;
private final int HEIGHT = 400;
public Fun()
{
setTitle("Fun Management");
setSize(WIDTH, HEIGHT);
BuildPanel west = new BuildPanel(); /// BuildPanel is the name of the class that has just a button in it.
BuildPanel east = new BuildPanel(); ///
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(west, BorderLayout.WEST); /// I am doing the same thing with the instances as I would with buttons or labesl
add(east, BorderLayout.EAST);
setVisible(true);
}
public static void main(String[] args)
{
new Fun();
}
}
I took your code and created the following GUI.
Oracle has a rad tutorial, Creating a GUI With Swing, that will show you how to create Swing GUIs. Skip the Netbeans section.
Always start your Swing application with a call to the SwingUtilities invokeLater method. This method ensures that your Swing components are created and executed on the Event Dispatch Thread.
Use Swing components. Don't extend a Swing component unless you want to override one or more of the component methods.
The JFrame methods must be called in a specific order. This is the order I recommend for most Swing applications. Use the JFrame pack method and let the components size the JFrame.
I created a BuildPanel class to build a JPanel. There are good reasons to do this, but be careful. You have to manage each instance of the class you create. As an example, what if you want the text of the two buttons to be different? What if you want to assign two different ActionListener classes, one to each button?
Here's the complete runnable code. I made the BuildPanel class an inner class so I can post the code as one block.
import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TwoPanelExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TwoPanelExample());
}
#Override
public void run() {
JFrame frame = new JFrame("Fun Management");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BuildPanel west = new BuildPanel();
BuildPanel east = new BuildPanel();
frame.add(west.getPanel(), BorderLayout.WEST);
frame.add(east.getPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class BuildPanel {
private final JPanel panel;
public BuildPanel() {
this.panel = createMainPanel();
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(5, 30, 5, 30));
JButton button = new JButton("Click Me");
panel.add(button);
return panel;
}
public JPanel getPanel() {
return panel;
}
}
}
What I am trying to do is when I click the button the rectangle needs to be drawn.
But I am having some confusions.
Here is the code :
package painting;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
public class Painting {
JFrame jf ;
public static void main(String[] args) {
Painting p = new Painting();
p.runn();
}
public void runn(){
jf = new JFrame("Try");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocationRelativeTo(null);
jf.setSize(400,400);
jf.setVisible(true);
JButton jb = new JButton("Click");
jb.setBounds(200,200,100,60);
jf.add(jb);
//jf.add(jb,BorderLayout.SOUTH);
//jf.setLayout(null);
Handler handle = new Handler();
jb.addActionListener(handle);
}
private class Handler implements ActionListener{
#Override
public void actionPerformed(ActionEvent ae)
{
Mainting maint = new Mainting();
jf.add(maint);
}
}
}
and the other class:
package painting;
import java.awt.*;
import javax.swing.*;
public class Mainting extends JPanel {
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillRect(0,0,30,30);
}
}
Now, the problem is when I run this code a button appears covering up the entire screen and when I click on that, nothing happens.
I found out that that is because of layout manager is not defined, and when I try to set the Layout Manger to null, the button appears fine but when I click on that the rectangle does not appear (also that is because we can't use null layout manager to draw graphics).
And finally, when I try to set a layout manager, say - border layout - the button appears as it should but how compiler says it needs int parameters to be drawn and not directions!
Please help!
use JPanel and then add button to it. setBounds() does not work good with Swing.Something Like this-
JButton button = new JButton(...);
JPanel wrapper = new JPanel();
wrapper.add(button);
frame.add(wrapper, BorderLayout.PAGE_START);
I've made a JFrame with Diferent JButtons and i'd like to get an image from another class. Any ideas? Or how draw on the same class but on the action performed?
Because it doesnt let me to do any drawings...my complier always gives me error messages
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.*;
public class red extends JFrame {
public JButton b;
public JButton b1;
public JButton b2;
public JButton b3;
public JButton b4;
public static Image p;
public static Graphics g;
public red() throws IOException {
gui1 x = new gui1();
setTitle(" ");
setSize(1200,700);
setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
b= new JButton("click");
b1= new JButton();
b.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e0){
b1.setBounds(0, 0, 200, 200);
b.show(false);
add(x);
}
});
b.setBounds(0, 0, 100, 100);
add(b1);
add(b);
setVisible(true);
}
public static void main(String[] args) throws IOException {
red k = new red();
}
}
import java.awt.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class gui1 extends Canvas {
public static Image p;
public void paint(Graphics g){
g.drawImage(p, 700, 200, 100, 100, this);
}
{
try {
p= ImageIO.read(new File("Lighthouse.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Phew! I see A LOT of errors in your code (even after I corrected the compilation errors):
You're not following the Java naming conventions:
Class names should be nouns, in mixed case with the first letter of each internal word capitalized
while red is a noun it should be more descriptive and be capitalized. The same goes for gui1
You're extending JFrame which in plain english would say: red is a JFrame, you should really avoid this and create your GUI based on JPanels instead... see Java Swing using extends JFrame vs callint it inside of class
You're setting size (a REAAAAAAALLY big one window for the JButton sizes you're using), instead use pack()
You're using null-layout, while pixel-perfect GUIs might seem like the easiest way to create complex GUIs for Swing newbies, the more you use them the more problems related to this you'll find in the future, they are hard to maintain and cause random problems, they don't resize, etc. Please read Null layout is evil and Why is it frowned upon to use a null layout in Swing? for more information about why you should avoid its use and why you should change your GUI to work with Layout Managers along with Empty Borders for extra spacing between components.
You're making use of a deprecated method JFrame#show() you should be using JFrame#setVisible(...) instead.
Related to point #4, you shouldn't be calling setBounds(...) method, but let that calculations to the layout managers.
You're not placing your program on the Event Dispatch Thread (EDT), Swing is not thread safe, you can fix this by changing your main() method as follows:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//Your constructor here
}
});
}
You're mixing AWT and Swing components, instead of using AWT's Canvas use Swing's JPanel which has more functionality and support.
Images will become embedded resources once they're packaged in a JAR file, so it's wise to start treating them as if they already were, not as external files as shown in the embedded-resource tag.
Once you change from Canvas to JPanel you should override its paintComponent(...) method and not paint(...) and call it's super.paintComponent(g) method as the first line, also don't forget to add the #Overrides annotation. See the tutorial on Swing custom painting.
You're abusing the use of static keyword, see how does the static keyword works?
After seeing all the above errors I recommend you to go back and Learn the basics of the language before starting with a graphical environment which will only add more difficulty to your learning.
From what I understand you want to draw an image on a button click, if that's the case then you can wrap your image in a JLabel and add that JLabel to a JPanel which then is added to a parent JPanel which is later added to the JFrame:
As you can see in the GIF above, the icon is displayed after user presses the button.
Obviously this can be improved for the GUI to be more "attractive" with combinations of layout managers and empty borders as stated before.
This was done with the following code:
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
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 ImageDrawingFromOneClassToAnother {
private JFrame frame;
private JPanel pane;
private JPanel leftPane;
private JPanel rightPane;
private ImageIcon icon;
private JButton button;
private JLabel label;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ImageDrawingFromOneClassToAnother().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
icon = new ImageIcon(this.getClass().getResource("king.png")); //Read images as if they were already embedded resources
button = new JButton("Draw image");
label = new JLabel(""); //Create an empty label
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setIcon(icon); //On button click, we set the icon for the empty label
}
});
pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200); //Set a size for the main panel
}
};
pane.setLayout(new GridLayout(1, 2)); //The main panel
leftPane = new JPanel(); //The button panel
leftPane.setLayout(new BoxLayout(leftPane, BoxLayout.PAGE_AXIS));
leftPane.add(button);
rightPane = new JPanel(); //The panel where the image will be drawn
rightPane.add(label);
//We add both (button and image) panels to the main panel
pane.add(leftPane);
pane.add(rightPane);
frame.add(pane); //Add the main panel to the frame
frame.pack(); //Calculate its preferred size
frame.setVisible(true); //Set it to be visible
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I'm having trouble adding a JPanel class I created to my container class. To be honest, I'm not sure if this is even the best method to go about creating my menu. I've asked professors, and TA's and they all tell me different things.
EDIT: To clarify, the problem is that the main menu made in the JPanel class isn't shown. I think I added it properly within the container class, but I'm not entirely sure.
This is my JPanel class that I'm trying to add to the container:
package.model;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class MainMenu extends JPanel {
private static MainMenu instance;
private JPanel mainMenu;
private JButton btnSinglePlayer, btnMultiPlayer, btnScoreBoard, btnQuit;
private MainMenu() {
mainMenu();
singlePlayer();
multiPlayer();
scoreBoard();
quit();
}
public static MainMenu getMenuInstance() {
if (instance == null) {
instance = new MainMenu();
}
return instance;
}
public void construct() {
mainMenu();
singlePlayer();
multiPlayer();
scoreBoard();
quit();
}
private JPanel mainMenu() {
mainMenu = new JPanel();
mainMenu.setLayout(null);
return mainMenu;
}
private JButton singlePlayer() {
btnSinglePlayer = new JButton("SinglePlayer");
btnSinglePlayer.setBounds(365, 210, 170, 55);
mainMenu.add(btnSinglePlayer);
return btnSinglePlayer;
}
private JButton multiPlayer() {
btnMultiPlayer = new JButton("MultiPlayer");
btnMultiPlayer.setBounds(365, 300, 170, 55);
mainMenu.add(btnMultiPlayer);
return btnMultiPlayer;
}
private JButton scoreBoard() {
btnScoreBoard = new JButton("ScoreBoards");
btnScoreBoard.setBounds(365, 411, 170, 55);
mainMenu.add(btnScoreBoard);
return btnScoreBoard;
}
private JButton quit() {
btnQuit = new JButton("Quit");
btnQuit.setBounds(365, 500, 170, 55);
mainMenu.add(btnQuit);
return btnQuit;
}
}
And here is my container class:
package view;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import model.MainMenu;
#SuppressWarnings("serial")
public class MainFrame extends JFrame {
private static JFrame mainContainer = new JFrame("Checkers");
private JPanel card = new JPanel(new CardLayout());
private CardLayout cardLayout = (CardLayout) (card.getLayout());
private JPanel homeCard, singlePlayerCard, multiPlayerCard, scoreBoardCard;
private JPanel mainMenu = MainMenu.getMenuInstance();
public MainFrame() {
}
private void addComponentToPane(Container pane) {
//mainMenu.construct();
homeCard = new JPanel();
singlePlayerCard = new JPanel();
multiPlayerCard = new JPanel();
scoreBoardCard = new JPanel();
homeCard.add(mainMenu);
card.add(homeCard, "homeCard");
cardLayout.show(card, "homeCard");
pane.add(card);
}
public static void createAndShowGUI() {
MainFrame frame = new MainFrame();
frame.addComponentToPane(mainContainer.getContentPane());
mainContainer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainContainer.pack();
mainContainer.setSize(920, 650);
mainContainer.setVisible(true);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
mainContainer.setLocation(dim.width / 2 - mainContainer.getSize().width
/ 2, dim.height / 2 - mainContainer.getSize().height / 2);
}
}
The reason I want to have a JPanel class, and I'll have more than one btw, is because I want that class to launch my game thread. And I don't wish to launch the game thread through the view. If this is a bad design please let me know.
I do btw, have a launcher class, which I think is irrelevant to post. I know I did it right though, the error which I and abut 3-4 TA's at my university can't seem to find.
JFrame has a few side-effects that exist outside of the Java program space, like the frame decorators that the operating system provides (usually edge handles, close buttons, and os driven drop down menus to hide / show / etc.)
As such, typically you cannot use classical composition and inheritance for driving JFrames at the same time.
If you inherit, you can call the class's own getContentPane() to get the container which then can be used such as
getContentPane().add(jpanel);
If you perfer composition, then you basically do the same thing, but with your member variable holding the JFrame.
frame.getContentPane().add(jpanel);
Note that unlike many containers, JFrame only supports adding one item. So, if you want to add multiple items, you need to add a JPanel, and the add the interior items to the JPanel.
private JPanel mainMenu = MainMenu.getMenuInstance(); in MainFrame gets the MainMenu instance variable from the MainMenu Class.
The constructor or construct() method in MainMenu add components to the mainMenu JPanel in MainMenu which is never referred to again.
Also, it is bad practice to set a JPanel's layout to null as you did in MainMenu's mainMenu() method. It sets the size of the JPanel component to 0x0 pixels and you won't see the components inside of the JPanel when you add them.
I could mention another thing or two about refactoring your code properly into methods and ask questions about how the rest of the project works, but this post is 8 years old at the time of this writing. I'm writing these statements to point people in the right direction if they are still curious about why the code doesn't work.
I would like to create a simple GUI in Java. I know the basics of creating JLabel, etc. However, I cannot find why my JLabel is not displayed on the screen. Here is my code:
package test;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class A1Panel extends JPanel implements ActionListener {
JLabel firstInt;
public void init() {
makeComponents();
makeLayout();
}
private void makeComponents() {
firstInt = new JLabel("First argument");
firstInt.setFont(new Font("Helvetica", Font.BOLD, 16));
firstInt.setBackground(Color.lightGray);
firstInt.setVisible(true);
firstInt.setHorizontalAlignment(SwingConstants.CENTER);
}
private void makeLayout() {
add(firstInt);
}
public void actionPerformed(ActionEvent e) {
}
}
I then add my JPanel to my JFrame using a different class called GUI:
import test.A1Panel;
public class GUI {
public static void main(String[] args) {
JFrame frame = new JFrame("Testing GUI");
frame.setLayout( new GridLayout(1,3));
JPanel panel = new A1Panel();
panel.setBorder( BorderFactory.createRaisedBevelBorder() );
frame.add( panel);
frame.setSize(800,600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
}
When I hit compile, what I get is a simple frame with three empty panels. I do not understand why my JLabel is not in the first panel since I have added it to my frame. Am I missing something?
The frame is not empty, the panel is. Nowhere in your code do I see a call to the methods init() or makeComponents(). In fact, I would turn your init() method into a constructor, like so:
public A1Panel() {
makeComponents();
makeLayout();
}
Another alternative to this would be to call panel.init() after declaring JPanel panel = new A1Panel()
After you instance A1Panel, you haven't called A1Panel.init()
I would suggest removing init() and adding all the code to the constructor of A1Panel. If, however, you wanted to keep the init() function, you would want to call it after JPanel panel = new A1Panel()
The code to add the label was not actually called in the main, was it? So look carefully, when is init actually called?
Look at the
private void makeLayout()
method.
If I replace public void init() by A1Panel(), it does the job. Thank you for your help.