I've seen a few examples of this, and I've tried with the following code. I'm trying to change the content pane when portraitB is selected and then run the other class file.
//imported java libraries
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.UIManager;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.Dimension;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class birthdayCardGUI implements ActionListener
{
//Welcome Screen
JPanel welcomeP, welcomeImageP, portraitP, landscapeP, backP;
JLabel welcomeImageL;
JButton portraitB, landscapeB, backB;
//Portrait Screen
JTabbedPane tabbedPane;
JPanel portraitOne;
JLabel test;
public JFrame frame;
//Colours
int colourOne = Integer.parseInt( "c1c7f9", 16);
Color Blue = new Color( colourOne );
public birthdayCardGUI() throws Exception
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
JFrame frame = new JFrame("birthday Card Maker!");
frame.setExtendedState(frame.NORMAL);
frame.getContentPane().add(create_Content_Pane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 700); //Size of main window
frame.setVisible(true);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
//sets frame location
int fw = frame.getSize().width;
int fh = frame.getSize().height;
int fx = (dim.width-fw)/2;
int fy = (dim.height-fh)/2;
//moves the frame
frame.setLocation(fx, fy);
}
public JPanel create_Content_Pane() throws Exception
{
JPanel TotalGUI = new JPanel();
//TotalGUI.setBackground(Blue);
TotalGUI.setLayout(null);
//Welcome Panel
welcomeP = new JPanel();
Border etched = BorderFactory.createBevelBorder(10);
Border titled = BorderFactory.createTitledBorder(etched, "Welcome");
welcomeP.setBorder(titled);
welcomeP.setLayout(null);
welcomeP.setLocation(0,0);
welcomeP.setSize(485, 680);
welcomeP.setBackground(Blue);
TotalGUI.add(welcomeP);
welcomeImageP = new JPanel();
welcomeImageP.setLayout(null);
welcomeImageP.setLocation(88,20);
welcomeImageP.setSize(324, 225);
welcomeP.add(welcomeImageP);
String welcomeG = "Welcome Image.png";
ImageIcon WelcomeG = new ImageIcon(welcomeG);
welcomeImageL = new JLabel( WelcomeG, JLabel.CENTER);
welcomeImageL.setSize(324, 225);
welcomeImageL.setLocation(0,0);
welcomeImageP.add(welcomeImageL);
portraitB = new JButton("Portrait");
portraitB.setSize(100, 30);
portraitB.setLocation(200, 295);
portraitB.addActionListener(this);
welcomeP.add(portraitB);
landscapeB = new JButton("Landscape");
landscapeB.setSize(100, 30);
landscapeB.setLocation(200, 335);
landscapeB.addActionListener(this);
welcomeP.add(landscapeB);
TotalGUI.setOpaque(true);
return TotalGUI;
}
public void create_Portrait_Pane()
{
PortraitGUI portrait = new PortraitGUI();
getContentPane().removeAll();
getContentPane().add(portrait.PortraitGUI);
getContentPane().doLayout();
update(getGraphics());
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == portraitB)
{
create_Portrait_Pane();
}
}
//MAIN METHOD
public static void main(String[] args) throws Exception
{
birthdayCardGUI CGUI = new birthdayCardGUI();
}
}
And this is the PortraitGUI file that creates the new content pane.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class PortraitGUI extends JPanel implements ActionListener
{
JPanel frontPageP;
JLabel frontPageL;
//Color White;
int intValue = Integer.parseInt( "FFFFFF", 16);
Color White = new Color(intValue);
public JPanel PortraitGUI() throws Exception
{
JPanel PortraitGUI = new JPanel();
PortraitGUI.setLayout(null);
frontPageP = new JPanel();
frontPageP.setBackground(White);
frontPageP.setSize(350, 400);
frontPageP.setLocation(20, 70);
PortraitGUI.add(frontPageP);
frontPageL = new JLabel("Front Page");
frontPageL.setLocation(10, 5);
frontPageL.setSize(70, 30);
frontPageL.setHorizontalAlignment(JTextField.CENTER);
PortraitGUI.add(frontPageL);
PortraitGUI.setOpaque(true);
return PortraitGUI;
}
public void actionPerformed(ActionEvent e)
{
}
}
There are several problems in your code, but one of your main problems comes from your shadowing of the JFrame class field in your constructor leaving the class field null and non-usable. To fix this, don't redeclare this variable. Thus change this:
JFrame frame = new JFrame("birthday Card Maker!");
to this:
// this uses the JFrame variable declared in the class.
frame = new JFrame("birthday Card Maker!");
Then you can use this variable later on in a method where you swap contents of the contentPane:
public void create_Portrait_Pane() throws Exception {
PortraitGUI portrait = new PortraitGUI();
frame.getContentPane().removeAll(); // now you can use the frame variable
frame.getContentPane().add(portrait);
//!! getContentPane().doLayout();
//!! update(getGraphics()); // WTF?
((JPanel)frame.getContentPane()).revalidate();
frame.repaint();
}
Having said this, myself, I'd probably use a JPanel that uses CardLayout as my Container for swapping views (other JPanels).
Also, you appear to have a "pseudo" constructor here:
public JPanel PortraitGUI() throws Exception {
Why not just use a real constructor?:
public PortraitGUI() throws Exception {
setLayout(null);
frontPageP = new JPanel();
frontPageP.setBackground(White);
frontPageP.setSize(350, 400);
frontPageP.setLocation(20, 70);
add(frontPageP);
frontPageL = new JLabel("Front Page");
frontPageL.setLocation(10, 5);
frontPageL.setSize(70, 30);
frontPageL.setHorizontalAlignment(JTextField.CENTER);
add(frontPageL);
setOpaque(true);
}
Also for good programming practice you'll want to avoid using a plain-vanilla Exception class and instead throw or catch specific exceptions.
Next, you're going to want to get out of the habit of using absolute size and position and instead using the layout managers for doing what they do best.
Edit:
replies to your recent comments
The reason I used public "JPanel" PortraitGUI is because it was throwing the error or return type required,
This was fixing the wrong thing though as the better solution was to make it a true constructor, not to give it a return type.
and I coded the class the same as create_Content_Pane(); with returning a Panel. Also the return type required error came up a few times.
Again, it's important to know why the error is occurring rather than fixing the wrong thing.
The update(getGraphics()); was also a method I tried from code examples I found with the same problem.
Surely that didn't come from a Swing example but more likely an older AWT example. You don't do that sort of coding with Swing.
Related
As of late I've been developing a (very) small GUI application in Java. I'm extremely new to Swing and Java in general, but up until now I have been able to get everything to work the way I want it to. However, after cleaning up my code, when I run the program nothing but the border of the window appears. What am I doing wrong and how can I fix my code? Thanks ahead of time!
For the sake of saving space I've made Pastebin links to all of my classes (besides Main).
Main Class
package me.n3rdfall.ezserver.main;
public class Main {
public static GUI g = new GUI();
public static void main(String[] args) {
g.showWindow(800, 500);
}
}
GUI Class
http://pastebin.com/gDMipdp1
ButtonListener Class
http://pastebin.com/4XXm70AD
EDIT: It appears that calling removeAll() directly on 'frame' actually removed essential things other than what I had added. By calling removeAll() on getContentPane(), the issue was resolved.
Quick hack: Remove the removeAll() functions.
public void homePage() {
// frame.removeAll();
// mainpanel.removeAll();
// topbar.removeAll();
I'm not sure what you're trying to achieve, but that will at least show some items. If I were you I would rebuild this GUI by extending JFrame. It will make your code a little easier to read.
I also think what you are trying to achieve with the buttons is to switch layouts, you can do this in an easier way by using CardLayout
Example (has nothing to do with your code, but to demonstrate):
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame implements ActionListener {
private JButton leftButton;
private JButton rightButton;
private CardLayout cardLayout = new CardLayout();
JPanel cards = new JPanel(cardLayout);
final static String LEFTPANEL = "LEFTPANEL";
final static String RIGHTPANEL = "RIGHTPANEL";
JPanel card1;
JPanel card2;
public Example() {
JPanel topPanel = new JPanel();
addButtons(topPanel);
add(topPanel, BorderLayout.NORTH);
add(cards, BorderLayout.CENTER);
//Initiates the card panels
initCards();
setTitle("My Window");
setSize(300, 300);
setLocationRelativeTo(null);
setVisible(true);
}
private void initCards() {
card1 = new JPanel();
card2 = new JPanel();
card1.setBackground(Color.black);
card2.setBackground(Color.red);
cards.add(card1, LEFTPANEL);
cards.add(card2, RIGHTPANEL);
}
private void addButtons(Container con) {
leftButton = new JButton("Left Button");
leftButton.addActionListener(this);
rightButton = new JButton("Right Button");
rightButton.addActionListener(this);
con.add(leftButton, BorderLayout.WEST);
con.add(rightButton, BorderLayout.EAST);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(leftButton)) {
//Change cardlayout
cardLayout.show(cards, LEFTPANEL);
} else if(e.getSource().equals(rightButton)) {
//Change cardlayout
cardLayout.show(cards, RIGHTPANEL);
}
}
public static void main(String[] args) {
new Example();
}
}
I am trying to make a Wizard without using libraries that I Have seen to easily make wizards lol its for a project, I have done the layout and frames and panels, what am having trouble with is when I click the "-->" it does not go to panel2 , nothing happens, it does store the name but thatt is it. Could anybody help me out?
EDIT it works now :) now am having trouble displaying the second "panel2" it goes into nothing after i click the arrow. lol
package project4;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class WizardGUI extends JFrame implements ActionListener {
private JLabel enterName;
private JTextField name;
private JButton prev, fow;
private String storeName = "";
WizardGUI(){
super("Wizard");
name();
}
void name()
{
JPanel FPanel = new JPanel();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
// JLabel textLabel = new JLabel("lol");
//textLabel.setPreferredSize(new Dimension(300, 100));
// frame.getContentPane().add(textLabel);
//prev = new JButton("<--");
fow = new JButton ("-->");
this.add(FPanel);
enterName = new JLabel("Enter Your Name: ");
name = new JTextField(10);
enterName.setBounds(60, 30,120,30);
name.setBounds(80,60,130,30);
this.setSize(300,390); //set frame size
this.setVisible(true);
FPanel.add(enterName);
FPanel.add(name);
//FPanel.add(prev);
FPanel.add(fow);
fow.addActionListener(this);
}
void enter()
{
JPanel panel2 = new JPanel();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
//prev = new JButton("<--");
fow = new JButton ("-->");
this.add(panel2);
enterName = new JLabel("Enter Your Name: ");
name = new JTextField(10);
enterName.setBounds(60, 30,120,30);
name.setBounds(80,60,130,30);
this.setSize(300,390); //set frame size
this.setVisible(true);
panel2.add(enterName);
panel2.add(name);
//FPanel.add(prev);
panel2.add(fow);
fow.addActionListener(this);
this.getContentPane().removeAll();
validate();
repaint();
this.add(panel2);
}
void add()
{
}
void select()
{
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == fow) {
storeName = name.getText();
enter();
//JOptionPane.showMessageDialog(null, "hello " + storeName);
}
}
}
Thanks :)
You both extend JFrame and you create your own JFrame. This means you have two instances of JFrame. One is your WizardGUI class which I'm guessing is referenced in your main somewhere and the other is a local variable named frame.
In the constructor you are building everything in the frame instance. In the Sscreen method you are modifying the this instance so nothing that you've done to the frame instance is modified.
You should get rid of the local variable frame and replace all references to it with this.
Also, you should call super("Wizard") as your first line in the WizardGUI constructor. Calling parent constructors is important and everyone forgets to do that.
So I have a class called CalendarPanel that extends JPanel. It uses a null layout. How would I use CalendarPanel as a regular component? When I put it in another JPanel and then add it to a window, it disappears. It is only visible when I add it directly to a window.
EDIT:
And yes, I realize using a JPanel with a null layout is bad practice. CalendarPanel is actually someone else's code, and I'm trying to use it for my purposes without having to refactor it.
It is only visible when I add it directly to a window.
That is because a window uses a BorderLayout by default and will automatically resize the panel to fit in the window.
When I put it in another JPanel and then add it to a window, it disappears.
The is because a JPanel uses a FlowLayout by default and a flow layout respects the preferred size of the components added to it. Since you are using a null layout your panel doesn't have a preferred size so nothing gets painted.
That is why you should NOT use null layout. Instead use layout managers because they do all this extra work for you.
NOTE: it is a very bad idea in general to use a null layout. Use a LayoutManager instead.
If you insist on using a null layout, you're going to have to position the JPanel manually as mentioned in the documentation. Here's an example.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Test extends JFrame {
static int defaultX = 10;
static int defaultY = 10;
static int defaultW = 150;
static int defaultH = 50;
public Test() {
super("Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// here is the outer JPanel
final JPanel outer = new JPanel(new BorderLayout());
JPanel inner = new JPanel(new BorderLayout());
// here is the main component we want to see
// when the outer panel is added to the null layout
JButton mainComponent = new JButton("Test");
inner.add("Center", mainComponent);
outer.add("Center", inner);
JPanel c = (JPanel)getContentPane();
// This panel has a null layout!
final JPanel nullLayoutPanel = new JPanel();
nullLayoutPanel.setLayout(null);
c.add("Center", nullLayoutPanel);
// set the bounds of the outer panel manually
// when using the null layout!
nullLayoutPanel.add(outer);
outer.setBounds(defaultX, defaultY, defaultW, defaultH);
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
final JTextField x = new JTextField(""+defaultX, 3);
final JTextField y = new JTextField(""+defaultY, 3);
final JTextField w = new JTextField(""+defaultW, 3);
final JTextField h = new JTextField(""+defaultH, 3);
JButton b = new JButton("Resize");
b.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
outer.setBounds(
Integer.parseInt(x.getText()),
Integer.parseInt(y.getText()),
Integer.parseInt(w.getText()),
Integer.parseInt(h.getText())
);
outer.revalidate();
} catch(Exception ex) {}
}
}
);
controlPanel.add(x);
controlPanel.add(y);
controlPanel.add(w);
controlPanel.add(h);
controlPanel.add(b);
c.add("South", controlPanel);
}
public static void main(String[] argv) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Test p = new Test();
p.setSize(300, 200);
p.setVisible(true);
}
});
}
}
So, I've been working to redo my code so that the painting is all done in a JPanel instead of a JFrame so I can do some very much needed image buffering.
I've scoured StackOverflow and I've googled my fingers raw and I thought I had it set up right, but it's not working. I just get a blank white screen and some error script in the terminal. Any help is appreciated. Here is the code
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
public class RacerDoom extends JFrame {
private JPanel panel;
final int WIDTH = 900, HEIGHT = 640;
int counter = 0;
Rectangle left = new Rectangle(0,0,WIDTH/9,HEIGHT);
Rectangle right = new Rectangle((WIDTH/9)*8,0,WIDTH/9,HEIGHT);
Rectangle top = new Rectangle(0,0,WIDTH,HEIGHT/9);
Rectangle bottom = new Rectangle(0,(HEIGHT/9)*8,WIDTH,HEIGHT);
Rectangle center = new Rectangle((int)((WIDTH/9)*2.5),(int)((HEIGHT/9)*2.5),(int)((WIDTH/9)*4),(HEIGHT/9)*4);
Rectangle p1 = new Rectangle(WIDTH/9,HEIGHT/2,WIDTH/30,WIDTH/30);
Rectangle finishtop = new Rectangle(WIDTH/9,(HEIGHT/2)-HEIGHT/9,(int)((WIDTH/9)*1.5),HEIGHT/70);
//Starting lines
Rectangle startO = new Rectangle(WIDTH/9,HEIGHT/2,(int)((WIDTH/9)*1.5)/2,HEIGHT/140);
public RacerDoom() {
//create JFrame
super("Racer Doom Squared");
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
getContentPane().add(panel);
panel = new MainPanel();
panel.setBounds(0,0,WIDTH,HEIGHT);
this.getContentPane().add(panel);
//set up Game countdown timer
final Timer timer=new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(counter>=10) {
((Timer)e.getSource()).stop();
}
else{
counter++;
}
System.out.println(counter);
}
});
//start timer
timer.start();
}
private class MainPanel extends JPanel {
public MainPanel() {
super();
}
//draw graphics
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0,0,WIDTH,HEIGHT);
//boundaries
g.setColor(Color.LIGHT_GRAY);
g.fillRect(left.x,left.y,left.width,left.height);
g.fillRect(right.x,right.y,right.width,right.height);
g.fillRect(top.x,top.y,top.width,top.height);
g.fillRect(bottom.x,bottom.y,bottom.width,bottom.height);
g.fillRect(center.x,center.y,center.width,center.height);
//start line
g.setColor(Color.WHITE);
g.fillRect(startO.x,startO.y,startO.width,startO.height);
//finish line
g.setColor(Color.CYAN);
g.fillRect(finishtop.x,finishtop.y,finishtop.width,finishtop.height);
//p1
g.setColor(Color.BLUE);
g.fill3DRect(p1.x,p1.y,p1.width,p1.height,true);
//HUD
g.setColor(Color.WHITE);
Font f = new Font("Monospaced", Font.BOLD, 24);
g.setFont(f);
g.drawString("Boosts: "+p1Boost,(WIDTH-(WIDTH/6)),(HEIGHT-(int)(HEIGHT/1.1)));
g.drawString("Time: "+(10-counter),540,100);
}
}
public static void main (String [] args) {
new RacerDoom();
}
}
The error script:
Exception in thread "main" java.lang.NullPointerException
at java.awt.Container.addImpl(Unknown Source)
at java.awt.Container.add(Unknown Source)
at RacerDoom.(RacerDoom.java:46)
at RacerDoom.main(RacerDoom.java:232)
I'm quite sure I'm just an idiot and the answer is probably giving me the middle finger in the error message, but it's still Greek to me. But even (especially?) idiots need help.
Your error is pretty simple:
getContentPane().add(panel);
panel = new MainPanel();
panel.setBounds(0,0,WIDTH,HEIGHT);
You're adding the panel to the widow before the panel is actually created. Try rearranging it like this:
panel = new MainPanel();
panel.setBounds(0,0,WIDTH,HEIGHT);
getContentPane().add(panel);
I believe line 46 is:
getContentPane().add(panel);
At that point, you haven't created the panel yet, so it is null. You can't add a null component to a container. Remove that line; your later this.getContentPane().add(panel); is all you need.
The NullPointerException occurs because you try to add not initialized variable panel:
getContentPane().add(panel);
You have to first initialize this variable, and than add it to getContentPane()
I'm having a problem when setting the background colour of a JTextArea after I set its text. The code is as follows:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class Test extends JFrame {
private JTextArea area;
public Test() {
this.setLayout(new BorderLayout());
this.add(this.area = new JTextArea(), BorderLayout.CENTER);
this.add(new JButton(clickAction), BorderLayout.SOUTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(500, 200));
this.pack();
this.area.setText("this is just a test");
this.setVisible(true);
}
Action clickAction = new AbstractAction("Click") {
#Override
public void actionPerformed(ActionEvent e) {
area.setBackground(new Color(0, 0, 123, 138));
// repaint();
}
};
public static void main(String[] args) {
new Test();
}
}
If I click the button, the background of the JTextArea changes, but I also get some artifacts in the text area. The "repaint" seems to fix it, but in my application example, it doesn't help, so I was wondering whether there is a better solution to this.
You're just missing one text i think
Action clickAction = new AbstractAction("Click") {
#Override
public void actionPerformed(ActionEvent e) {
area.setBackground(new Color(0, 0, 123, 138));
area.repaint();
}
};
It's because you are using a partially transparent color for the component's background. Try setting your background color's alpha channel value to 255 and see if the artifacts still show up. The call to repaint() fixes the issue because it forces the underlying buffer to be filled with your background color prior to painting the text (I think).
I had the same issue with a project I worked on for school recently. You have to call repaint on the frame too (so I changed the ActionListener to take a JFrame in the constructor). I also rearranged the code to use the content pane of the JFrame. This seems to work for me:
public Test() {
this.area = new JTextArea();
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(area, BorderLayout.CENTER);
JButton button = new JButton(new MyClickAction(this));
button.setText("Click Me!");
this.getContentPane().add(button, BorderLayout.SOUTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(500, 200));
this.area.setText("this is just a test");
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
new Test();
}
private class MyClickAction extends AbstractAction
{
private JFrame frame;
public MyClickAction(JFrame frame) {
this.frame = frame;
}
#Override
public void actionPerformed(ActionEvent e) {
area.setBackground(new Color(0, 0, 123, 138));
frame.repaint();
}
}
I had similar problems and resolved them by using the validate() method on the component in question. So many things it could be... maybe I'll get slammed for this but - speaking as one who has just spent an entire year laboring with Swing - I say to you: RUN!! Swing is just about deprecated.
Learn JavaFx 2.0 and help bury Swing.