java frame reprint not working - java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class sample {
JTextField field=new JTextField(10);
JPanel panel=new JPanel();
JFrame frame=new JFrame();
String message;
public sample()
{
frame.setSize(500, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
field.setEditable(true);
JButton button=new JButton("press here");
ActionListener listener=new action();
button.addActionListener(listener);
panel.add(field);
panel.add(button);
frame.add(panel);
}
public void getMessage()
{
JTextField f=new JTextField(10);
f.setText(message);
JPanel p=new JPanel();
p.add(f);
frame.add(p);
frame.repaint(); <-- problem here
}
class action implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
message=field.getText();
frame.remove(panel);
getMessage();
}
}
}
//The problem is frame doesn't call repaint method at getMessage method. So, I have to minimize the window to solve this problem. Is their any other way to solve this problem?

The problem is that you added a component to a visible GUI. By default all components have a size of (0, 0) so there is nothing to paint.
What you really need to do is invoke the layout manager so the size/location of the component can be determined.
The basic code should be:
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint(); // to repaint components
In JDK7 and later you can also do the revalidate()/repaint() on the frame.

Related

Java swing, Changing java swing windows but blank screen appearing. When running each program separate , each works fine

I am Designing a login screen and a main menu screen in Java using java swing. The problem i am getting is when the login is correct, I get a blank java swing window when i already designed the main menu.
I just started learning Java so i am not quite knowledgeable on it.
I am designing the frame by myself, meaning i am not using the GUI Interface, all buttons and Text boxes are done manually.
This is login code.
package loginapp;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Login_App extends JFrame {
public static void main(String[] args) {
JFrame frame = new JFrame("Mo Garage Login");
//frame setup
frame.setSize(500, 600);
frame.setVisible(true);
//Label and Text boxes
JLabel usernamelbl = new JLabel("Username");
usernamelbl.setBounds(100,100, 100,20);
frame.add(usernamelbl);
frame.setLayout(null);
frame.setVisible(true);
JLabel passwordlbl = new JLabel("Password");
passwordlbl.setBounds(100,200,100,20);
frame.add(passwordlbl);
frame.setLayout(null);
frame.setVisible(true);
JTextField username = new JTextField();
username.setBounds(200,100,100,20);
frame.add(username);
frame.setLayout(null);//using no layout managers
frame.setVisible(true);
JPasswordField pass = new JPasswordField();
pass.setBounds(200,200,100,20);
frame.add(pass);
frame.setLayout(null);
frame.setVisible(true);
//Buttons
JButton log=new JButton("Login");
log.setBounds(200,500,100,40);
frame.add(log);
frame.setLayout(null);//using no layout managers
frame.setVisible(true);
//login button action
log.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent arg0) {
String uname=username.getText();
String passwd=pass.getText();
if (uname.equals("") && passwd.equals(""))
{
JOptionPane.showMessageDialog(frame, "Login Successfull");
MainMenu mainmenu =new MainMenu();
mainmenu.setVisible(true);
frame.setVisible(false);
}
else {
JOptionPane.showMessageDialog(frame, "Incorrect Credentials");
}
}
}
);
JButton clear=new JButton("Clear");
clear.setBounds(50,500,100,40);
frame.add(clear);
frame.setLayout(null);
frame.setVisible(true);
//clear button action
clear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
username.setText("");
pass.setText("");
}
}
);
}
}
This is my main menu code.
package loginapp;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class MainMenu extends JFrame {
public static void main(String[] args) {
JFrame frame= new JFrame("Main Menu");
frame.setSize(500,600);
frame.setVisible(true);
JButton client= new JButton("Add new Client");
client.setBounds(200,100,120,30);
frame.add(client);
frame.setLayout(null);
frame.setVisible(true);
JButton Mod= new JButton("Update Database");
Mod.setBounds(190,200,140,30);
frame.add(Mod);
frame.setLayout(null);
frame.setVisible(true);
JButton info= new JButton("Information");
info.setBounds(200,300,120,30);
frame.add(info);
frame.setLayout(null);
frame.setVisible(true);
JButton exit= new JButton("Quit");
exit.setBounds(200,400,120,30);
frame.add(exit);
frame.setLayout(null);
frame.setVisible(true);
}
}
I tried different methods but i could not find it. Help please.
Thank you.
In your Login_App class, in the actionPerformed() method, you call the constructor of class MainMenu like so...
MainMenu mainmenu =new MainMenu();
However, class MainMenu does not have a constructor - at least not in the code you posted. You build the GUI in method main() of class MainMenu. So I would suggest the easiest solution - based on the code you posted - would be to change the code in method actionPerformed() of class Login_App. Replace the line shown above with...
MainMenu.main(new String[]{});
while every one comments was absolutely right and helpful but your proplem wasn't in any !! your proplem is in adding the Component's to MainMenu object .
so in short , copy the hole code of the main of the MainMenu and put it in another method let's call it go public void go() and replace the line :-
JFrame frame= new JFrame("Main Menu");
with
this.setTitle("MainMenue");
and replace any refrence of the object frame with the keyword this .
Try calling the method revalidate() at the beginning of actionPerformed for your login. It reloads the frame.

Adding a JPanel from a different class

I'm trying to add a simple JPanel from a different class with only a JButton and a JTextArea into the GUI.
I'm using IntelliJ IDEA for the swing application and there are no errors. However, the JPanel simply doesn't appear/isn't shown.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ContainerAdapter;
import java.awt.event.ContainerEvent;
public class GUI {
private JPanel mainPanel;
private JPanel mainInner;
public GUI() {
mainPanel.addContainerListener(new ContainerAdapter() {
#Override
public void componentAdded(ContainerEvent e) {
super.componentAdded(e);
System.out.println("component Added");
}
});
}
public void start() {
JFrame frame = new JFrame("GUI");
frame.setContentPane(new GUI().mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
InnerPanel inner = new InnerPanel();
mainInner = inner.getMainInner();
inner.setLayout(new BorderLayout());
mainPanel.setLayout(new BorderLayout());
mainPanel.add(mainInner, BorderLayout.CENTER);
mainPanel.revalidate();
mainPanel.repaint();
frame.pack();
frame.setVisible(true);
}
}
The component listener shows that the component has been added, yet it isn't shown.
You forgot to add the mainPanel to frame:
frame.add(mainPanel);

why cant i change the position of the panel inside a frame?

I am trying to create a GUI with a couple of buttons and a drawing area.
it seems to be working except the drawing area is very small and not in the right location.
here is my code:
public class ssGUI extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
protected JButton b1, bConnect, bDisconnect, b2;
protected JPanel canvas;
public ssGUI() {
// run button
b1 = new JButton("do something");
b1.setVerticalTextPosition(AbstractButton.CENTER);
b1.setHorizontalTextPosition(AbstractButton.LEADING);
b1.setMnemonic(KeyEvent.VK_D);
b1.addActionListener(this);
b1.setEnabled(false);
// connect button
bConnect = new JButton("Connect");
bConnect.setMnemonic(KeyEvent.VK_E);
bConnect.addActionListener(this);
bConnect.setEnabled(true);
// disconnect button
bDisconnect = new JButton("Disconnect");
bDisconnect.setMnemonic(KeyEvent.VK_E);
bDisconnect.addActionListener(this);
bDisconnect.setEnabled(false);
// clean nmea data button
b2 = new JButton("do something else");
b2.setMnemonic(KeyEvent.VK_E);
b2.addActionListener(this);
b2.setEnabled(false);
// drawing panel
canvas = new JPanel();
canvas.setBackground(Color.white);
add(b1); add(bConnect); add(bDisconnect); add(b2); add(canvas, BorderLayout.CENTER);
}
public static void createAndShowGUI() {
JFrame frame = new JFrame("Range Adjustment GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ssGUI newContentPane = new ssGUI();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
frame.setLocation(500, 500);
frame.setSize(500, 500);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}}
this is how my GUI looks like:
as you can see, the "canvas" is very small and at the side of the buttons.
i need it to be placed underneath them and fill frame area.
can anyone help me to resolve that problem?
thank you for your help.
Set your main panel's layout to BorderLayout.
Create a panel just for your buttons and add this panel to your main panel's NORTH position.
Here is a working example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ssGUI extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
protected JButton b1, bConnect, bDisconnect, b2;
protected JPanel canvas;
public ssGUI() {
setLayout(new BorderLayout());
// run button
b1 = new JButton("do something");
b1.setVerticalTextPosition(AbstractButton.CENTER);
b1.setHorizontalTextPosition(AbstractButton.LEADING);
b1.setMnemonic(KeyEvent.VK_D);
b1.addActionListener(this);
b1.setEnabled(false);
// connect button
bConnect = new JButton("Connect");
bConnect.setMnemonic(KeyEvent.VK_E);
bConnect.addActionListener(this);
bConnect.setEnabled(true);
// disconnect button
bDisconnect = new JButton("Disconnect");
bDisconnect.setMnemonic(KeyEvent.VK_E);
bDisconnect.addActionListener(this);
bDisconnect.setEnabled(false);
// clean nmea data button
b2 = new JButton("do something else");
b2.setMnemonic(KeyEvent.VK_E);
b2.addActionListener(this);
b2.setEnabled(false);
// drawing panel
canvas = new JPanel();
canvas.setBackground(Color.white);
JPanel topPanel = new JPanel();
topPanel.add(b1);
topPanel.add(bConnect);
topPanel.add(bDisconnect);
topPanel.add(b2);
add(topPanel, BorderLayout.NORTH);
add(canvas, BorderLayout.CENTER);
}
public static void createAndShowGUI() {
JFrame frame = new JFrame("Range Adjustment GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ssGUI newContentPane = new ssGUI();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
frame.setLocation(500, 500);
frame.setSize(500, 500);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
This is another problem with the layouts.
JPanel has a default layout and I don't see you setting the layout for ssGUI class. Hence the default layout (FlowLayout) will be used.
All components added to ssGUI will be arranged in a linear fashion in a row for as much as it can hold. When your component exceed the width, it will be placed to the next row.
You can consider using a layout for your main panel ssGUI. A GridBagLayout will probably give you what you want.

Java: Why validate don't work

I want to change the panel dynamically and as this answer show, they recommend to use the cardLayout. But I want to change the whole UI(no old button left) and cardLayout seems not so convenient. So I have the following code:
JFrame frame = new JFrame ("Key test");
MyDrawPanel1 dp1 = new MyDrawPanel1(frame);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible (true);
JPanel p = new JPanel ();
p.setLayout(new BorderLayout());
p.add(dp1,BorderLayout.CENTER);
frame.getContentPane().add(p);
frame.pack();
frame.setVisible (true);
And in the MyDrawPanel1 there is a button to change panel:
public MyDrawPanel1(final JFrame frame) {
clickButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
frame.getContentPane().removeAll();
//frame.validate();
frame.getContentPane().add(new MyDrawPanel2());
((JPanel)frame.getContentPane()).revalidate();
}
});
this.add(clickButton);
}
Edit:some more codes in MyDrawPanel1.
JButton clickButton = new JButton("click");
Image image = new ImageIcon("D:/0.jpg").getImage();
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.drawImage(image, 3, 40, null);
}
public Dimension getPreferredSize() {
if (image != null) {
return new Dimension(image.getWidth(null), image.getHeight(null));
}
return super.getPreferredSize(); // default
}
But the first panel doesn't disappear and I have to minimize it to refresh it so I can see the second panel. My question is the why validate don't work and if there is any other alternatives. Thanks.
Edit:here are the pictures I snipped about the panel.(first panel):
(after clicked):
Edit:
The madProgrammer and Adarsh Singhal provide two ways to solve the problem. The first is the second the panel don't call the super.paintComponent(), so add it then it works fine (as this answer say, it is the eraser so the first panel was gone). The second is calling the frame.repaint(), but I don't understand why?
We've to use repaint() to tell the components to repaint themselves. Visualize it as your case. While revalidate is used to update the layouts. So, whenever you add/remove components dynamically, you need to call both of them.The following written code displays a JFrame set to CardLayout to draw Red dp1(JPanel) completely on JFrame. On dp1, there is a Jbutton. If you click that button, dp1 will be removed & dp2(JPanel) will be drawn. dp2 is Green to distinguish changes. It seems you've forgotten repaint().
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyFrame extends JFrame{
JButton button;
private static MyFrame frame;
public MyFrame(){
this.setSize(400, 400);
this.setLayout(new CardLayout());
this.setLocationRelativeTo(null);
JPanel dp1 = new JPanel();
dp1.setBackground(Color.RED);
add(dp1);
button = new JButton("Click me to remove dp1 & draw dp2");
dp1.add (button);
JPanel dp2 = new JPanel ();
dp2.setBackground(Color.GREEN);
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
frame.getContentPane().remove(dp1);
frame.add(dp2);
frame.revalidate();
frame.repaint();
}});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible (true);
}
public static void main(String[] args) {
frame = new MyFrame();
}
}

removeAll not removing at next validate?

Can someone explain why the following doesn't work as I expect?
Pressing the button 'should' result in the display only containing the (empty) JScrollPane, ie the input field and button should disappear. However they stay until the component is resized...
public static void main(String[] args)
{
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final JPanel panel = new JPanel();
Container cp = frame.getContentPane();
cp.setLayout(new FlowLayout());
cp.add(new JScrollPane(panel));
Component textField = new JTextField("i am input");
JButton button = new JButton(new AbstractAction("i am pressy")
{
#Override
public void actionPerformed(ActionEvent e)
{
// this is already on the EDT
panel.removeAll();
panel.revalidate();
}
});
panel.setLayout(new FlowLayout());
panel.add(textField);
panel.add(button);
frame.pack();
frame.setVisible(true);
}
Thanks for your help. p.
When updating a visible GUI the code should be:
panel.revalidate();
panel.repaint(); // sometimes needed, this appears to be one of them
The revalidate() method marks components as needing to be laid out, but until something triggers repaint() you won't see any change. Resizing the parent window is one such trigger; switching applications is another. In this previous version, note how setSize() on the panel obviates the need for repaint(). Similarly, this example changes the layout in resetGame().
The article Painting in AWT and Swing goes into more detail.
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
/** #see https://stackoverflow.com/questions/5812002 */
public class RevalidateTest {
private static JPanel panel = new JPanel(); // default FlowLayout
private static JTextField text = new JTextField("Text field");
private static JButton clear = new JButton(new AbstractAction("Clear") {
#Override
public void actionPerformed(ActionEvent e) {
panel.removeAll();
panel.add(reset);
panel.revalidate();
panel.repaint();
}
});
private static JButton reset = new JButton(new AbstractAction("Reset") {
#Override
public void actionPerformed(ActionEvent e) {
panel.removeAll();
panel.add(text);
panel.add(clear);
panel.revalidate();
panel.repaint();
}
});
static void createAndShowGUI() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
panel.add(text);
panel.add(clear);
frame.add(panel); // default BorderLayout center
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
You can execute panel.repaint() as specified in the comment by #Jeremy, however, the UI will still change when you resize the window. The reason being that the removal of the elements from the JPanel will cause the panel to resize. A repaint operation will not cause the panel to resize until the JFrame rechecks its layout (as happens on a window resize).
To make sure that the layout is correctly layed out on a change, you can call frame.validate(). This operation will cause the JFrame to revalidate itself and all child components, which is the same operation that is taking place during a window resize event. To execute this method in your code you would need to change JFrame frame to final, i.e.,
final JFrame frame = new JFrame("test");

Categories