Hello I am trying to solve the following problem: Write a program that prompts the user to enter the x- and y-positions of a center point and a radius, using text fields. When the user clicks a "Draw" button, draw a circle with that center and radius in a component. I do not see what is wrong in my code but something is because it doesnt seem like repaint() is invoking paintComponent() as message will change to TESTING 1 but not TESTING 2 and no drawing is made.
My Code:
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.applet.*;
import java.awt.geom.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class q3{
public static class cgPanel extends JPanel{
private static double x;
private static double y;
private static double r;
private static JTextField xField;
private static JTextField yField;
private static JTextField rField;
private static JButton draw;
private static JLabel message;
//This is all just Layout work.
public cgPanel(){
setLayout(new BorderLayout());
JPanel drawPanel = new JPanel();
drawPanel.setBackground(Color.WHITE);
add(drawPanel, BorderLayout.CENTER);
message = new JLabel("");
JPanel sub1ForSub1 = new JPanel();
sub1ForSub1.add(message);
JLabel coordinates = new JLabel("Coordinates:");
JPanel sub2ForSub1 = new JPanel();
sub2ForSub1.add(coordinates);
JPanel subPanel1 = new JPanel();
subPanel1.setLayout(new GridLayout(2, 1));
subPanel1.add(sub1ForSub1);
subPanel1.add(sub2ForSub1);
JLabel xLabel = new JLabel("x:");
xField = new JTextField(4);
JLabel yLabel = new JLabel(" y:");
yField = new JTextField(4);
JLabel rLabel = new JLabel(" Radius:");
rField = new JTextField(4);
JPanel subPanel2 = new JPanel();
subPanel2.add(xLabel);
subPanel2.add(xField);
subPanel2.add(yLabel);
subPanel2.add(yField);
subPanel2.add(rLabel);
subPanel2.add(rField);
draw = new JButton("Draw");
ActionListener bL = new ButtonListener();
draw.addActionListener(bL);
JPanel subPanel3 = new JPanel();
subPanel3.add(draw);
JPanel Panel = new JPanel();
Panel.setLayout(new BorderLayout());
Panel.add(subPanel1, BorderLayout.NORTH);
Panel.add(subPanel2, BorderLayout.CENTER);
Panel.add(subPanel3, BorderLayout.SOUTH);
add(Panel, BorderLayout.SOUTH);
setVisible(true);
}
static class ButtonListener extends JComponent implements ActionListener{
public void actionPerformed(ActionEvent e){
try{
String xString = xField.getText();
String yString = yField.getText();
String rString = rField.getText();
message.setText("TESTING 1");
x = Double.parseDouble(xString);
y = Double.parseDouble(yString);
r = Double.parseDouble(rString);
repaint();
}
catch (NumberFormatException exception){
message.setText("Please enter a number.");
}
}
//This is where I cant seem to get the code in paintComponent to run when the Draw button is pressed.
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
Ellipse2D.Double circle = new Ellipse2D.Double(x - r, y - r, r*2, r*2);
g2.draw(circle);
message.setText("TESTING 2");
}
}
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setSize(800, 800);
frame.setTitle("Circle Generator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cgPanel panel = new cgPanel();
frame.add(panel);
frame.setVisible(true);
}
}
So, a couple of things.
Your problem stems from that fact that your ButtonListener is extending a JComponent, so the repaint() method is calling the one for the ButtonListener (which really isn't a JComponent).
And the paintComponent method is also for the the ButtonListener.
Instead, you want your button listener to have access to your cgPanel, so it can tell IT to repaint. And your paintComponent needs to be moved to the cgPanel, but even then you probably don't want it there since you have a bunch of other components on cgPanel.
It's not clear from your code where you really want the circle to be drawn.
You should probably create a CirclePanel that extend JPanel, and overrides paintComponent to draw your circles, and then add that to your cgPanel. Then make your ButtonListener tell the CirclPanel instance to repaint.
Related
I am trying to make a RPG game in a GUI and it's not going so well.
Before I added the JButton everything worked and displayed in the window as it should. I'm not sure what happened after I added the JButton.
There is supposed to be the title displayed in the grey area and the button in the blue area. Ive tried running normally and running with debugger, none of the text or button shows up.
I am following the tutorial here step-by-step and I dont see anything out of place. (I know that i've changed the variable names).
What have I done wrong here? Do I need to add anything extra?
import javax.swing.*;
import java.awt.*;
public class Game {
JFrame window;
Container c;
JPanel titlePanel;
JPanel startButtonPanel;
JLabel titleLabel;
JButton startButton;
Font titleFont = new Font("Cooper Black", Font.PLAIN, 90);
Font buttonFont = new Font("Cooper Black", Font.PLAIN, 32);
public static void main(String[] args) {
new Game();
}
public Game() {
//Main Window
window = new JFrame();
window.setSize(800, 600);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().setBackground(Color.BLACK);
window.setLayout(null);
window.setVisible(true);
c = window.getContentPane();
//Title Panel
titlePanel = new JPanel();
titlePanel.setBounds(100, 100, 600, 150);
titlePanel.setBackground(Color.GRAY);
titleLabel = new JLabel("TEXT RPG");
titleLabel.setForeground(Color.WHITE);
titleLabel.setFont(titleFont);
//Start Button Panel
startButtonPanel = new JPanel();
startButtonPanel.setBounds(300, 400, 200, 100 );
startButtonPanel.setBackground(Color.BLUE);
//Start Button
startButton = new JButton("START");
startButton.setBackground(Color.BLACK);
startButton.setForeground(Color.WHITE);
startButton.setFont(buttonFont);
//Add Elements to Window
titlePanel.add(titleLabel);
startButtonPanel.add(startButton);
//Add Elements to Container
c.add(titlePanel);
c.add(startButtonPanel);
}
}
Do not follow tutorial teaching you to use null layout managers and setting bounds "manually". That is not a good practice.
Remove all bounds setting from the code.
Instead use Layout Managers, that is what they do, dynamically set bounds for you:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Game {
JFrame window;
Container c;
JPanel titlePanel;
JPanel startButtonPanel;
JLabel titleLabel;
JButton startButton;
Font titleFont = new Font("Cooper Black", Font.PLAIN, 90);
Font buttonFont = new Font("Cooper Black", Font.PLAIN, 32);
public static void main(String[] args) {
new Game();
}
public Game() {
//Main Window
window = new JFrame();
window.setSize(800, 600);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
c = window.getContentPane();
c.setBackground(Color.BLACK);
//window.setLayout(null);
//Title Panel
titlePanel = new JPanel(); //JPanel uses FlowLayout by default
//titlePanel.setBounds(100, 100, 600, 150)
titlePanel.setBackground(Color.GRAY);
titleLabel = new JLabel("TEXT RPG");
titleLabel.setForeground(Color.WHITE);
titleLabel.setFont(titleFont);
//Start Button Panel
startButtonPanel = new JPanel();
//startButtonPanel.setBounds(300, 400, 200, 100 );
startButtonPanel.setBackground(Color.BLUE);
//Start Button
startButton = new JButton("START");
startButton.setBackground(Color.BLACK);
startButton.setForeground(Color.WHITE);
startButton.setFont(buttonFont);
//Add Elements to Window
titlePanel.add(titleLabel);
startButtonPanel.add(startButton);
//Add Elements to Container
c.add(titlePanel, BorderLayout.CENTER); //JFrame content pane uses BorderLayout by default
c.add(startButtonPanel, BorderLayout.PAGE_END);
window.pack();
window.setVisible(true); //invoke after all added and pack() ed
}
}
Don't expect to get the exact desired look on first attempt. Learn how to use different Layout Managers and combinations of them to get what you want.
A friend of mine offfered to fix the problem. He added something called "extends Canvas".
Heres the fixed version:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Game extends Canvas{
private static final long serialVersionUID = 1L;
public static JFrame window;
public static Container c;
JPanel titlePanel,startButtonPanel;
JLabel titleLabel;
JButton startButton;
Font titleFont = new Font("Cooper Black", Font.PLAIN,90);
private static int width = 800;
private static int height = 600;
public static String title ="Blueberry's Game";
/*----------------------------------------------------------------------------------------------------*/
public static void main(String[] args){
Game game = new Game();
Game.window.setResizable(false);
Game.window.setTitle(Game.title);
Game.window.add(game);
Game.window.pack();
Game.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Game.window.setLocationRelativeTo(null);
Game.window.setVisible(true);
}
/*----------------------------------------------------------------------------------------------------*/
public Game(){
window = new JFrame();
setPreferredSize(new Dimension(width, height));
window.getContentPane().setBackground(Color.BLACK);
c = window.getContentPane();
//////////TITLE PANEL//////////////////////
titlePanel = new JPanel();
titlePanel.setBounds(100, 100, 600, 150);
titlePanel.setBackground(Color.BLACK);
titleLabel = new JLabel("TEXT RPG");
titleLabel.setForeground(Color.WHITE);
titleLabel.setFont(titleFont);
//////////START BUTTON PANEL//////////////////////
startButtonPanel = new JPanel();
startButtonPanel.setBounds(300, 400, 200, 100);
startButtonPanel.setForeground(Color.BLUE);
//////////START BUTTON//////////////////////
startButton = new JButton("START");
startButton.setBackground(Color.BLACK);
startButton.setForeground(Color.WHITE);
//////////ADD ELEMENTS TO WINDOW//////////////////////
titlePanel.add(titleLabel);
startButtonPanel.add(startButton);
//////////ADD ELEMENTS TO CONTAINER//////////////////////
c.add(titlePanel);
c.add(startButtonPanel);
}
/*----------------------------------------------------------------------------------------------------*/
}
EDIT: I Also managed to see why the window wasn't showing anything in my question. I just had to adjust the window size with the cursor.
I am trying to use jcef browser inside my swing application but getting problems.
First of all i unable to add jcef browser as JPanel component on jFrame. Then i try to add directly on jframe
[code]getContentPane().add(browser.getUIComponent(), BorderLayout.CENTER);[/code]
Now when browser window load inside JFrame, and If i want to switch with other Jpanel then it is not working working in any way
I cant switch the screen after loading CEF browser. Can any one point out what i need to do. Here is my test jframe.
import org.cef.CefApp;
import org.cef.CefClient;
import org.cef.browser.CefBrowser;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class CardLayoutTst extends JFrame {
static CefBrowser browser = null;
static CefClient client = null;
private static final long serialVersionUID = 1L;
private JPanel cardPanel, jp1, jp2, buttonPanel;
private JLabel jl1, jl2;
private JButton btn1, btn2;
private CardLayout cardLayout = new CardLayout();
public CardLayoutTst() {
setTitle("Test med CardLayout");
setSize(400, 300);
cardPanel = new JPanel();
buttonPanel = new JPanel();
cardPanel.setLayout(cardLayout);
jp1 = new JPanel();
jp2 = new JPanel();
jl1 = new JLabel("Card 1");
jl2 = new JLabel("Card 2");
jp1.add(jl1);
jp2.add(jl2);
cardPanel.add(jp1, "1");
cardPanel.add(browser.getUIComponent(), "2");
btn1 = new JButton("Show Card 1");
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardLayout.show(cardPanel, "1");
}
});
btn2 = new JButton("Show Card 2");
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardLayout.show(cardPanel, "2");
}
});
buttonPanel.add(btn1);
buttonPanel.add(btn2);
add(cardPanel, BorderLayout.NORTH);
add(buttonPanel, BorderLayout.SOUTH);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
CefApp.getInstance().dispose();
dispose();
}
});
}
public static void main(String[] args) {
client = CefApp.getInstance().createClient();
browser = client.createBrowser("http://www.google.com", false, false);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
CardLayoutTst frame = new CardLayoutTst();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
It is a bit late but I had just the same problem. A friend of mine solved the issue.
You have to create CefSettings, set the windowless_rendering_enabled to false and pass this settings object to the getInstance call:
CefSettings settings = new CefSettings();
settings.windowless_rendering_enabled = false;
client = CefApp.getInstance(settings).createClient();
I'm making a Hangman game and it seems that my code doesn't provide me much freedom with using layouts. I added an image to my JFrame then I added a JPanel to my image which I'm using for all the JLabels and JTextFields but it seems to me that its inefficient because in order to change the layout of my JTextFields or JLabels I have to change the layout of my image which messes up the entire looks of the game. How can I make this code more efficient and give myself more freedom to change the layouts of my JLabels and JTextFields without messing everything up? Thanks for the help in advanced.
/*PACKAGE DECLARATION*/
package Game;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
/************************
* GAME MECHANICS CLASS *
* **********************/
public class GameStructure {
/* INSTANCE DECLARATIONS */
private String []wordList = {"computer","java","activity","alaska","appearance","article",
"automobile","basket","birthday","canada","central","character","chicken","chosen",
"cutting","daily","darkness","diagram","disappear","driving","effort","establish","exact",
"establishment","fifteen","football","foreign","frequently","frighten","function","gradually",
"hurried","identity","importance","impossible","invented","italian","journey","lincoln",
"london","massage","minerals","outer","paint","particles","personal","physical","progress",
"quarter","recognise","replace","rhythm","situation","slightly","steady","stepped",
"strike","successful","sudden","terrible","traffic","unusual","volume","yesterday"};
private int []length = new int [64];
private JTextField tf;//text field instance variable (used)
private JLabel jl2;//label instance variable (used)
private JLabel jl3;//label instance (working on)
private String letter;
/*****************
* LENGTH METHOD *
* ***************/
public void length(){
jl3 = new JLabel();
int j = 0;
for(j = 0; j<64; j++) {
length[j] = wordList[j].length();//gets length of words in wordList
}//end for
int l = 0;
String line = "";
//create line first then put into .setText
for(int m = 0; m<length[l]; m++) {
line += "__ ";
l++;
}//end for
jl3.setText(line);
}//end length method
/*****************
* WINDOW METHOD *
* ***************/
public void window() {
LoadImageApp i = new LoadImageApp();//calling image class
JFrame gameFrame = new JFrame();//declaration
JPanel jp = new JPanel();
//JPanel jp2 = new JPanel();//jpanel for blanks
JLabel jl = new JLabel("Enter a Letter:");//prompt with label
jl.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
tf = new JTextField(1);//length of text field by character
jl2 = new JLabel("Letters Used: ");
tf.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
jl2.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
jp.add(jl);//add label to panel
jp.add(tf);//add text field to panel
jp.add(jl2);//add letters used
gameFrame.add(i); //adds background image to window
i.add(jp); // adds panel containing label to background image panel
gameFrame.setTitle("Hangman");//title of frame window
gameFrame.setSize(850, 600);//sets size of frame
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//exit when 'x' button pressed
gameFrame.setIconImage(new ImageIcon("Hangman-Game-grey.png").getImage());//set the frame icon to an image loaded from a file
gameFrame.setLocationRelativeTo(null);//window centered
gameFrame.setResizable(false);//user can not resize window
gameFrame.setVisible(true);//display frame
}//end window method
/*********************
* USER INPUT METHOD *
* *******************/
public void userInput() {
tf.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//when enter key pressed
JTextField tf = (JTextField)e.getSource();
letter = tf.getText();
jl2.setText(jl2.getText() + letter + " ");//sets jlabel text to users entered letter
}//end actionPerformed method
});
}//end userInput method
}//end GameMechanics class
/*PACKAGE DECLARATION*/
package Game;
/***********************
* IMPORT DECLARATIONS *
* *********************/
import java.awt.BorderLayout;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
/***************
* IMAGE CLASS *
* *************/
public class LoadImageApp extends JPanel {
private static final long serialVersionUID = 1L;
private ImageIcon image;
/***********************
* PAINT IMAGE METHOD *
* *********************/
public void paintComponent (Graphics g) {
//setLayout(new BorderLayout());
super.paintComponent(g);
image = new ImageIcon("hangman.png");//image name & type
image.paintIcon(this, g, 270, 20);
}//end paintComponent method
}//end LoadImageApp class
/*PACKAGE DECLARATION*/
package Game;
/*******************
* GAME MAIN CLASS *
* *****************/
public class GameMain {
/***************
* MAIN METHOD *
* *************/
public static void main (String []args) {
GameStructure game = new GameStructure();//declaration
game.length();
game.window();
game.userInput();
}//end main method
}//end GameMain class
Some suggestions:
Don't override a JPanel's paint(...) method, but rather its paintComponent(Graphics g) method, not unless you need to change how it renders its child components or its borders (you don't). Also by doing this you gain some Swing graphics advantages including automatic double buffering.
Never read in an image into the paint or paintComponent method. These methods are one of the main determinants of how responsive your GUI appears to the user, and so you never want to do file I/O in the method. And also, why have code that inefficiently re-reads the same image in whenever paint or paintComponent is called? Why not simply store the image or ImageIcon in a variable once, and be done with it?
Learn and use the layout managers
JPanels that go over drawing or image rendering JPanels often should be non-opaque - so be sure to call setOpaque(false) on them, and also on some other overlying Swing components.
_________________________
Edit
For example, here is my SSCCE that shows an example of getting an image (here off of the internet) in a class constructor. Also note that my SSCCE will work on any computer connected to the internet since it does not require image files, unlike yours. Also code not related to displaying the GUI has been cut out making the remaining code more pertinent to the problem. Consider doing this next time you post an SSCCE.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
class GameStructure {
private JTextField tf;
private JLabel jl2;
public void window() {
LoadImageApp loadImageApp = new LoadImageApp();
JFrame gameFrame = new JFrame();
JPanel jp = new JPanel();
jp.setOpaque(false); //!!
jp.setBorder(BorderFactory.createTitledBorder("jp"));
JLabel jl = new JLabel("Enter a Letter:");
jl.setFont(new Font("Rockwell", Font.PLAIN, 20));
tf = new JTextField(1);
jl2 = new JLabel("Letters Used: ");
tf.setFont(new Font("Rockwell", Font.PLAIN, 20));
jl2.setFont(new Font("Rockwell", Font.PLAIN, 20));
jp.add(jl);
jp.add(tf);
jp.add(jl2);
gameFrame.add(loadImageApp);
loadImageApp.add(jp);
gameFrame.setTitle("Hangman");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// gameFrame.setIconImage(
// new ImageIcon("Hangman-Game-grey.png").getImage());
gameFrame.setResizable(false);
gameFrame.pack();
gameFrame.setLocationRelativeTo(null);
gameFrame.setVisible(true);
}
}
class LoadImageApp extends JPanel {
private static final long serialVersionUID = 1L;
private static final int PREF_W = 850;
private static final int PREF_H = 600;
private BufferedImage img;
public LoadImageApp() {
// just used as an example public image
String spec = "https://duke.kenai.com/"
+ "SunRIP/.Midsize/SunRIP.png.png";
URL url;
try {
url = new URL(spec);
img = ImageIO.read(url);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
}
}
public class GameMain {
public static void main(String[] args) {
GameStructure game = new GameStructure();
game.window();
}
}
I've been working on this for some time, and I'd really appreciate some help right now.
I'm trying to get the JFrame containing the text input fields to close from my actionPerformed method, but I can't seem to get anything to work. JFrame.dispose wont let me access the right Jframe, and setVisible(false) is equally useless, unless I'm doing this completely wrong.
//halp
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
class PersonInput extends JPanel
implements ActionListener {
//Fields for data entry
private JFormattedTextField firstField, lastField, dateField;
public String x[] = new String[3];
public PersonInput() {
//Values for the fields
String first = "First Name";
String last = "Last Name";
String date = "MM/DD/YYYY";
//Create the text fields and set them up.
firstField = new JFormattedTextField();
firstField.setValue(new String(first));
lastField = new JFormattedTextField();
lastField.setValue(new String(last));
dateField = new JFormattedTextField();
dateField.setValue(new String(date));
dateField.setColumns(10);
JButton ok = new JButton("OK");
ok.setVerticalTextPosition(AbstractButton.BOTTOM);
ok.setHorizontalTextPosition(AbstractButton.CENTER);
ok.setActionCommand("ok");
ok.addActionListener(this);
ok.setToolTipText("Confirms user input and continues with the program.");
JPanel buttons = new JPanel(new GridLayout(0,1));
buttons.add(ok);
//Layout the text fields in a panel.
JPanel fieldPane = new JPanel(new GridLayout(0,1));
fieldPane.add(firstField);
fieldPane.add(lastField);
fieldPane.add(dateField);
//Put the panels in this panel, labels on left,
//text fields on right.
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
add(fieldPane, BorderLayout.CENTER);
add(buttons, BorderLayout.LINE_END);
}
public void actionPerformed(ActionEvent e) {
if ("ok".equals(e.getActionCommand()))
{
JFrame frame1 = new JFrame("People Sorter");
x[0] = firstField.getText();
x[1] = lastField.getText();
x[2] = dateField.getText();
JOptionPane.showMessageDialog(frame1, "Person has been added.");
dispPerson();
frame.setVisible(false);
}
}
public void dispPerson()
{
System.out.println(x[0] + x[1] + x[2]);
}
public static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Person Input");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add contents to the window.
frame.add(new PersonInput());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
I'm all ears if anyone has any ideas; I've been stressed over this all day. Thanks much for lending me your time!
EDIT: Just for clarification, the frame I'm trying to close is the one instantiated in the createAndShowGUI method.
it seems that the problem is that we are trying to merge both static and non static contents. For a short explanation static contents can be referred without need of creating an instance (object) of that class. Which means that createAndShowGUI can be called:
inside another static method (like main)
From class reference PersonInput.createAndShowGUI()
or from an object, but that method or attribute will be always the same, static attributes are shared.
I can suggest 2 ways to solve your problem.
One is pass the object frame to PersonInput
//halp
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
class PersonInput extends JPanel
implements ActionListener {
//Fields for data entry
private JFormattedTextField firstField, lastField, dateField;
public String x[] = new String[3];
JFrame frame;
public PersonInput(JFrame frame) {
this.frame = frame;
//the rest of your code
}
The other way is to have the frame object outside the method and declare it static.
static JFrame frame = new JFrame("Person Input");;
public static void createAndShowGUI() {
//Create and set up the window.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add contents to the window.
frame.add(new PersonInput());
//Display the window.
frame.pack();
frame.setVisible(true);
}
Remember that static variable cannot be referenced from a static context
I'm fairly new to Java Swing/AWT et al and hence the question. I have a simple dialog with some text and a couple JButton. I am using the GridbagLayout for this dialog.
But when I look at the dialog, the JButtons are kind of having a weird shape and I cannot seem to right justify the text either.
Is this a limitation of the Layout I am using. Is there much simpler and elegant solution for my problem with either the buttons or the textlayout?
A screenshot of the dialog is attached below.
The code for my dialog Class is:
public class UpgradePopupWindow extends JPanel implements ActionListener {
static final long serialVersionUID = 0;
final String upgrade = " Continue Upgrade ";
final String restore = "Restore Previous Version";
JPanel panels;
JButton upgradeButton;
JButton restoreButton;
JTextArea Message;
JFrame newFrame;
FlasherThread flash;
protected JTextArea addText(String text, boolean visible, int fontStyle) {
JTextArea textArea = new JTextArea(text);
textArea.setFont(new Font("SansSerif", fontStyle, 12)); //$NON-NLS-1$
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
textArea.setBackground(Color.DARK_GRAY);
textArea.setForeground(Color.WHITE);
textArea.setOpaque(false);
textArea.setVisible(visible);
textArea.setAlignmentX(Component.CENTER_ALIGNMENT);
add(textArea);
return textArea;
}
protected JTextArea addMultiLineLabel(String text, int fontStyle, int fontSize, Object constraints) {
JTextArea textArea = new JTextArea(text);
textArea.setFont(new Font("SansSerif", fontStyle, fontSize));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
textArea.setBackground(new Color(0, 0, 0, 0)); // Zero alpha = transparent background
textArea.setOpaque(false);
textArea.setBorder(new TitledBorder(""));
textArea.setAlignmentX(Component.CENTER_ALIGNMENT);
add(textArea, constraints);
return textArea;
}
private UpgradePopupWindow(JFrame frame, Object ft) {
super(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
flash = (FlasherThread)ft;
String text = "An error occurred during the attempt to update your device's software. We recommend the following: (1) Restore your device to its previous version, (2) back up important data, and then (3) try updating your device again. If you continue with the current update, only your previously backed-up data will be available.";
//addFiller(5);
//addLabel(text, Font.PLAIN, 12);
gbc.gridy = 0;
gbc.gridx = 0;
gbc.gridwidth = 2;
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
addMultiLineLabel(text, Font.PLAIN, 12, gbc);
//addText(text, true, Font.PLAIN);
addFiller(20);
newFrame = frame;
gbc.gridy = 1;
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.NONE;
upgradeButton = new JButton(upgrade);
upgradeButton.setActionCommand("upgrade");
upgradeButton.addActionListener(this);
upgradeButton.setEnabled(true);
upgradeButton.setBackground(Color.WHITE);
upgradeButton.setForeground(Color.GRAY);
add(upgradeButton,gbc);
++ gbc.gridx;
restoreButton = new JButton(restore);
restoreButton.setActionCommand("restore");
restoreButton.addActionListener(this);
restoreButton.setEnabled(true);
//restoreButton.setForeground(Color.DARK_GRAY);
restoreButton.setBackground(Color.DARK_GRAY);
add(restoreButton,gbc);
setOpaque(true);
newFrame.setContentPane(this);
//newFrame.getContentPane().setBackground(Color.LIGHT_GRAY);
}
protected void addFiller(int size) {
Dimension diminsion = new Dimension(size, size);
Filler filler = new Filler(diminsion, diminsion, diminsion);
filler.setAlignmentX(Component.CENTER_ALIGNMENT);
add(filler);
}
public static void createGUI(Object obj) {
//Create and set up the frame.
JFrame frame = new JFrame("PopUp Dialog");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(440, 180));
//create and setup the content pane
UpgradePopupWindow popUpContentPane = new UpgradePopupWindow(frame, obj);
popUpContentPane.setOpaque(true);
frame.setContentPane(popUpContentPane);
frame.pack();
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if("restore".equals(e.getActionCommand())) {
System.out.println("restore button selected");
flash.setUpgradeRestoreChoice("restore");
newFrame.dispose();
} else if ("upgrade".equals(e.getActionCommand())) {
System.out.println("upgrade button selected");
flash.setUpgradeRestoreChoice("upgrade");
newFrame.dispose();
}
}
}
![alt text][1]
As #Javaguru said - use MigLayout. For the text DO NOT use JTextArea. This component is mostly for text editing. JLabel is enough for your purpose - you can even use HTML inside of it.
You don't have to create this kind of dialog from scratch. There are many options. One of them is my Swing TaskDialog framework ;)
But if you still insist on implementing it yourself here a simple implementation using MigLayout ( even with MigLayout it can be done using several differnt ways):
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import net.miginfocom.swing.MigLayout;
public class TestDialog extends JDialog {
private static final long serialVersionUID = 1L;
private final JLabel label = new JLabel("Your text here");
private final JButton restoreButton = new JButton("Restore Previous Version");
private final JButton ugradeButton = new JButton("Continue Upgrade");
public TestDialog( String title ) {
super( (JDialog)null, title );
setContentPane(createContent());
}
private JPanel createContent() {
JPanel content = new JPanel();
content.setPreferredSize( new Dimension(400, 100));
content.setBackground(Color.WHITE);
content.setLayout(new MigLayout("", "[400px,grow][pref!]", "[grow][pref!]"));
this.label.setVerticalAlignment(SwingConstants.TOP);
content.add(this.label, "cell 0 0 2 1,grow");
content.add(this.restoreButton, "cell 1 1,alignx left,aligny top");
content.add(this.ugradeButton, "cell 0 1,alignx right,aligny top");
return content;
}
// very simplified test
public static void main(String[] args) {
TestDialog dlg = new TestDialog("Popup Dialog");
dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dlg.pack();
dlg.setLocationRelativeTo(null);
dlg.setVisible(true);
}
}
There are a lot of much more elegant solutions out there .. ;)
You should really never use GridbagLayout if not absolutely required (or only with a gui editor)! It's simply a pain in the ass!
Rather I suggest using one of the following LayoutManagers:
MigLayout: http://www.miglayout.com/
TableLayout: https://tablelayout.dev.java.net/
Creating a pleasing layout is much simpler and intuitive than with the GridbagLayout and its configuration overhead.