Open a new window by button Press - java

I am trying to open a New Window by pressing the JButton. Now my actionPerformed method for the Jbutton is just closing the window after pressing it. I want it to open a new window as the old window closes. I know, this question is already had been asked, but I tried lot of things, no one seems to work perfectly.
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.Random;
public class secondTab extends JFrame
{
static JTabbedPane Pane = new JTabbedPane();
static JPanel Second = new JPanel();
static JPanel second = new JPanel(); // This Panel is inside the Second Panel
static JButton guess1 = new JButton();
static String words[] = new String[9];
static Random getRandomWord = new Random();
static int rr;
static JButton Labels[] = new JButton[10];
public static void main(String args[])
{
//construct frame
new secondTab().show();
}
public secondTab()
{
// code to build the form
setTitle("Shopping Cart");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridBagLayout());
// position tabbed pane
GridBagConstraints gridConstraints = new GridBagConstraints();
gridConstraints.gridx = 1;
gridConstraints.gridy = 1;
Pane.setForeground(Color.YELLOW);
Pane.setBackground(Color.MAGENTA);
getContentPane().add(Pane, gridConstraints);
getContentPane().setLayout(new GridBagLayout());
// Tabs Starts From Here
Second.setLayout(new GridBagLayout());
words[1] = "JAVA";
words[2] = "FLOAT";
words[3] = "VOID";
words[4] = "MAIN";
words[5] = "STATIC";
words[6] = "FINAL";
words[7] = "PRIVATE";
words[8] = "CHAR";
words[9] = "IF";
rr = getRandomWord.nextInt(10);
for(int i = 1; i <=words[rr].length(); i++)
{
Labels[i] = new JButton();
gridConstraints.gridx = 0;
gridConstraints.gridy = 0;
second.add(Labels[i]);
}
gridConstraints.gridx= 0;
gridConstraints.gridx= 0;
Second.add(second, gridConstraints);
guess1.setText("New Word");
gridConstraints.gridx = 0;
gridConstraints.gridy = 2;
Second.add(guess1, gridConstraints);
Here is my button's Action Performed method
// Action Performed method for the JButton guess1
guess1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
dispose();
}
});
Pane.addTab("Game ", Second);
pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds((int) (0.5 * (screenSize.width - getWidth())), (int) (0.5 *
(screenSize.height - getHeight())), getWidth(), getHeight());
}
}

Just add your new panel statement after the dispose(). for example : add
guess1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
new JFrame("New Window").show();
}
});
and one more point - you have created array of 9 element and you are trying to insert at 10 index that throws ArrayIndexOutOfBound exception.

You have to remove static keyword for your button and other controls, then you can do this
JTabbedPane Pane = new JTabbedPane();
JPanel Second = new JPanel();
JPanel second = new JPanel(); // This Panel is inside the Second Panel
JButton guess1 = new JButton();
String words[] = new String[10];
Random getRandomWord = new Random();
int rr;
JButton Labels[] = new JButton[10];
You have to create new instance of same class and show it
guess1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
new secondTab().show();
}
});

So, rather then closing the current window and creating a new instance of the window, which is just annoying (and a little lazy).
You should provide a means by which you can reset the state of your UI.
You should do this via some method call that resets the internal state and updates the UI.
You could accomplish the same thing by removing the "game" panel, creating a new instance of it and adding it back to the frame.
Blinking frames is a bad idea - IMHO

Hi,
Please try like this.. It may help..
guess1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
dispose();
new AnotherJFrame();
}
}
---------------------------------------------
import javax.swing.JFrame;
import javax.swing.JLabel;
public class AnotherJFrame extends JFrame
{
public AnotherJFrame()
{
super("Another GUI");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new JLabel("Empty JFrame"));
pack();
setVisible(true);
}
}

I see your question has been answered, so this does not address your problem. I just thought I'd share some things you might want to condider fixing:
Don't use show()/hide(), because they are deprecated. [More info]
Use setVisible(true/false) respectively. [More info]
You don't have to add a new 'GridBagLayout()' before adding each component into the same container. I.e., you can remove the second getContentPane().setLayout(new GridBagLayout()); [More info]
Just make sure you understand that array-indices in Java (and all programming languages I know od - which isn't that much...but still) are zero-based ! [More info]
In order to find the center of the "usable" screen size Toolkit.getDefaultToolkit().getScreenSize(); isn't enough, since it includes screen-insets (e.g. non-visible margins, taskbars etc). You need to also use Toolkit.getDefaultToolkit().getScreenInsets(GraphicsConfiguration); and substract left and right insets from screen-width as well as top and bottom insets from screen-height.
If all you need is center a JFrame on the screen, you can simply use setLocationRelativeTo(null). [More info]

see the below link... It may help for you..
Java swing application, close one window and open another when button is clicked

Related

Make the animation faster when there are thousands of components

I am trying to hide a JSplitPane with animation. By hide, I mean to setDividerLocation(0) so its left component is invisible (technically it is visible, but with zero width):
public class SplitPaneTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel leftPanel = new JPanel(new BorderLayout());
leftPanel.setBorder(BorderFactory.createLineBorder(Color.green));
JPanel rightPanel = new JPanel(new GridLayout(60, 60));
for (int i = 0; i < 60 * 60; i++) {
// rightPanel.add(new JLabel("s"));
}
rightPanel.setBorder(BorderFactory.createLineBorder(Color.red));
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
frame.add(splitPane);
JButton button = new JButton("Press me to hide");
button.addActionListener(e -> hideWithAnimation(splitPane));
leftPanel.add(button, BorderLayout.PAGE_START);
frame.setMaximumSize(new Dimension(800, 800));
frame.setSize(800, 800);
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
private static void hideWithAnimation(JSplitPane splitPane) {
final Timer timer = new Timer(10, null);
timer.addActionListener(e -> {
splitPane.setDividerLocation(Math.max(0, splitPane.getDividerLocation() - 3));
if (splitPane.getDividerLocation() == 0)
timer.stop();
});
timer.start();
}
}
If you run it, will see that everything seems good, and the animation runs smooth.
However, in the real application the right of the JSplitPane is a JPanel with CardLayout and each card has a lot of components.
If you uncomment this line in order to simulate the number of components:
// rightPanel.add(new JLabel("s"));
and re-run the above example, you will see that the animation no longer runs smoothly. So, the question is, is is possible to make it smooth(-ier)?
I have no idea how to approach a solution - if any exists.
Based on my research, I registered a global ComponentListener:
Toolkit.getDefaultToolkit()
.addAWTEventListener(System.out::println, AWTEvent.COMPONENT_EVENT_MASK);
and saw the tons of events that are being fired. So, I think the source of the problem is the tons of component events that are being fired for each component. Also, it seems that components with custom renderers (like JList - ListCellRenderer and JTable - TableCellRenderer), component events are firing for all of the renderers. For example, if a JList has 30 elements, 30 events (component) will be fired only for it. It also seems (and that's why I mentioned it) that for CardLayout, events are taking place for the "invisible" components as well.
I know that 60*60 might sound crazy to you, but in a real application (mine has ~1500) as it makes sense, the painting is heavier.
I know that 60*60 might sound crazy to you, but in a real application (mine has ~1500) as it makes sense, the painting is heavier.
The layout manager is invoked every time the divider location is changed which would add a lot of overhead.
One solution might be to stop invoking the layout manager as the divider is animating. This can be done by overriding the doLayout() method of the right panel:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SplitPaneTest2 {
public static boolean doLayout = true;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel leftPanel = new JPanel(new BorderLayout());
leftPanel.setBorder(BorderFactory.createLineBorder(Color.green));
JPanel rightPanel = new JPanel(new GridLayout(60, 60))
{
#Override
public void doLayout()
{
if (SplitPaneTest2.doLayout)
super.doLayout();
}
};
for (int i = 0; i < 60 * 60; i++) {
rightPanel.add(new JLabel("s"));
}
rightPanel.setBorder(BorderFactory.createLineBorder(Color.red));
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
frame.add(splitPane);
JButton button = new JButton("Press me to hide");
button.addActionListener(e -> hideWithAnimation(splitPane));
leftPanel.add(button, BorderLayout.PAGE_START);
frame.setMaximumSize(new Dimension(800, 800));
frame.setSize(800, 800);
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
private static void hideWithAnimation(JSplitPane splitPane) {
SplitPaneTest2.doLayout = false;
final Timer timer = new Timer(10, null);
timer.addActionListener(e -> {
splitPane.setDividerLocation(Math.max(0, splitPane.getDividerLocation() - 3));
if (splitPane.getDividerLocation() == 0)
{
timer.stop();
SplitPaneTest2.doLayout = true;
splitPane.getRightComponent().revalidate();
}
});
timer.start();
}
}
Edit:
I was not going to include my test on swapping out the panel full of components with a panel that uses an image of components since I fell the animation is the same, but since it was suggested by someone else here is my attempt for your evaluation:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
public class SplitPaneTest2 {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel leftPanel = new JPanel(new BorderLayout());
leftPanel.setBorder(BorderFactory.createLineBorder(Color.green));
JPanel rightPanel = new JPanel(new GridLayout(60, 60));
for (int i = 0; i < 60 * 60; i++) {
rightPanel.add(new JLabel("s"));
}
rightPanel.setBorder(BorderFactory.createLineBorder(Color.red));
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
frame.add(splitPane);
JButton button = new JButton("Press me to hide");
button.addActionListener(e -> hideWithAnimation(splitPane));
leftPanel.add(button, BorderLayout.PAGE_START);
frame.setMaximumSize(new Dimension(800, 800));
frame.setSize(800, 800);
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
private static void hideWithAnimation(JSplitPane splitPane) {
Component right = splitPane.getRightComponent();
Dimension size = right.getSize();
BufferedImage bi = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
right.paint( g );
g.dispose();
JLabel label = new JLabel( new ImageIcon( bi ) );
label.setHorizontalAlignment(JLabel.LEFT);
splitPane.setRightComponent( label );
splitPane.setDividerLocation( splitPane.getDividerLocation() );
final Timer timer = new Timer(10, null);
timer.addActionListener(e -> {
splitPane.setDividerLocation(Math.max(0, splitPane.getDividerLocation() - 3));
if (splitPane.getDividerLocation() == 0)
{
timer.stop();
splitPane.setRightComponent( right );
}
});
timer.start();
}
}
#GeorgeZ. I think the concept presented by #camickr has to do with when you actually do the layout. As an alternative to overriding doLayout, I would suggest subclassing the GridLayout to only lay out the components at the end of the animation (without overriding doLayout). But this is the same concept as camickr's.
Although if the contents of your components in the right panel (ie the text of the labels) remain unchanged during the animation of the divider, you can also create an Image of the right panel when the user clicks the button and display that instead of the actual panel. This solution, I would imagine, involves:
A CardLayout for the right panel. One card has the actual rightPanel contents (ie the JLabels). The second card has only one JLabel which will be loaded with the Image (as an ImageIcon) of the first card.
As far as I know, by looking at the CardLayout's implementation, the bounds of all the child components of the Container are set during layoutContainer method. That would probably mean that the labels would be layed out inspite being invisible while the second card would be shown. So you should probably combine this with the subclassed GridLayout to lay out only at the end of the animation.
To draw the Image of the first card, one should first create a BufferedImage, then createGraphics on it, then call rightPanel.paint on the created Graphics2D object and finally dispose the Graphics2D object after that.
Create the second card such that the JLabel would be centered in it. To do this, you just have to provide the second card with a GridBagLayout and add only one Component in it (the JLabel) which should be the only. GridBagLayout always centers the contents.
Let me know if such a solution could be useful for you. It might not be useful because you could maybe want to actually see the labels change their lay out profile while the animation is in progress, or you may even want the user to be able to interact with the Components of the rightPanel while the animation is in progress. In both cases, taking a picture of the rightPanel and displaying it instead of the real labels while the animation takes place, should not suffice. So it really depends, in this case, on how dynamic will be the content of the rightPanel. Please let me know in the comments.
If the contents are always the same for every program run, then you could probably pre-create that Image and store it. Or even, a multitude of Images and store them and just display them one after another when the animation turns on.
Similarly, if the contents are not always the same for every program run, then you could also subclass GridLayout and precalculate the bounds of each component at startup. Then that would make GridLayout a bit faster in laying out the components (it would be like encoding a video with the location of each object), but as I am testing it, GridLayout is already fast: it just calculates about 10 variables at the start of laying out, and then imediately passes over to setting the bounds of each Component.
Edit 1:
And here is my attempt of my idea (with the Image):
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.IntBinaryOperator;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SplitPaneTest {
//Just a Timer which plays the animation of the split pane's divider going from side to side...
public static class SplitPaneAnimationTimer extends Timer {
private final JSplitPane splitPane;
private int speed, newDivLoc;
private IntBinaryOperator directionf;
private Consumer<SplitPaneAnimationTimer> onFinish;
public SplitPaneAnimationTimer(final int delay, final JSplitPane splitPane) {
super(delay, null);
this.splitPane = Objects.requireNonNull(splitPane);
super.setRepeats(true);
super.setCoalesce(false);
super.addActionListener(e -> {
splitPane.setDividerLocation(directionf.applyAsInt(newDivLoc, splitPane.getDividerLocation() + speed));
if (newDivLoc == splitPane.getDividerLocation()) {
stop();
if (onFinish != null)
onFinish.accept(this);
}
});
speed = 0;
newDivLoc = 0;
directionf = null;
onFinish = null;
}
public int getSpeed() {
return speed;
}
public JSplitPane getSplitPane() {
return splitPane;
}
public void play(final int newDividerLocation, final int speed, final IntBinaryOperator directionf, final Consumer<SplitPaneAnimationTimer> onFinish) {
if (newDividerLocation != splitPane.getDividerLocation() && Math.signum(speed) != Math.signum(newDividerLocation - splitPane.getDividerLocation()))
throw new IllegalArgumentException("Speed needs to be in the direction towards the newDividerLocation (from the current position).");
this.directionf = Objects.requireNonNull(directionf);
newDivLoc = newDividerLocation;
this.speed = speed;
this.onFinish = onFinish;
restart();
}
}
//Just a GridLayout subclassed to only allow laying out the components only if it is enabled.
public static class ToggleGridLayout extends GridLayout {
private boolean enabled;
public ToggleGridLayout(final int rows, final int cols) {
super(rows, cols);
enabled = true;
}
#Override
public void layoutContainer(final Container parent) {
if (enabled)
super.layoutContainer(parent);
}
public void setEnabled(final boolean enabled) {
this.enabled = enabled;
}
}
//How to create a BufferedImage (instead of using the constructor):
private static BufferedImage createBufferedImage(final int width, final int height, final boolean transparent) {
final GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice gdev = genv.getDefaultScreenDevice();
final GraphicsConfiguration gcnf = gdev.getDefaultConfiguration();
return transparent
? gcnf.createCompatibleImage(width, height, Transparency.TRANSLUCENT)
: gcnf.createCompatibleImage(width, height);
}
//This is the right panel... It is composed by two cards: one for the labels and one for the image.
public static class RightPanel extends JPanel {
private static final String CARD_IMAGE = "IMAGE",
CARD_LABELS = "LABELS";
private final JPanel labels, imagePanel; //The two cards.
private final JLabel imageLabel; //The label in the second card.
private final int speed; //The speed to animate the motion of the divider.
private final SplitPaneAnimationTimer spat; //The Timer which animates the motion of the divider.
private String currentCard; //Which card are we currently showing?...
public RightPanel(final JSplitPane splitPane, final int delay, final int speed, final int rows, final int cols) {
super(new CardLayout());
super.setBorder(BorderFactory.createLineBorder(Color.red));
spat = new SplitPaneAnimationTimer(delay, splitPane);
this.speed = Math.abs(speed); //We only need a positive (absolute) value.
//Label and panel of second card:
imageLabel = new JLabel();
imageLabel.setHorizontalAlignment(JLabel.CENTER);
imageLabel.setVerticalAlignment(JLabel.CENTER);
imagePanel = new JPanel(new GridBagLayout());
imagePanel.add(imageLabel);
//First card:
labels = new JPanel(new ToggleGridLayout(rows, cols));
for (int i = 0; i < rows * cols; ++i)
labels.add(new JLabel("|"));
//Adding cards...
final CardLayout clay = (CardLayout) super.getLayout();
super.add(imagePanel, CARD_IMAGE);
super.add(labels, CARD_LABELS);
clay.show(this, currentCard = CARD_LABELS);
}
//Will flip the cards.
private void flip() {
final CardLayout clay = (CardLayout) getLayout();
final ToggleGridLayout labelsLayout = (ToggleGridLayout) labels.getLayout();
if (CARD_LABELS.equals(currentCard)) { //If we are showing the labels:
//Disable the laying out...
labelsLayout.setEnabled(false);
//Take a picture of the current panel state:
final BufferedImage pic = createBufferedImage(labels.getWidth(), labels.getHeight(), true);
final Graphics2D g2d = pic.createGraphics();
labels.paint(g2d);
g2d.dispose();
imageLabel.setIcon(new ImageIcon(pic));
imagePanel.revalidate();
imagePanel.repaint();
//Flip the cards:
clay.show(this, currentCard = CARD_IMAGE);
}
else { //Else if we are showing the image:
//Enable the laying out...
labelsLayout.setEnabled(true);
//Revalidate and repaint so as to utilize the laying out of the labels...
labels.revalidate();
labels.repaint();
//Flip the cards:
clay.show(this, currentCard = CARD_LABELS);
}
}
//Called when we need to animate fully left motion (ie until reaching left side):
public void goLeft() {
final JSplitPane splitPane = spat.getSplitPane();
final int currDivLoc = splitPane.getDividerLocation(),
minDivLoc = splitPane.getMinimumDividerLocation();
if (CARD_LABELS.equals(currentCard) && currDivLoc > minDivLoc) { //If the animation is stopped:
flip(); //Show the image label.
spat.play(minDivLoc, -speed, Math::max, ignore -> flip()); //Start the animation to the left.
}
}
//Called when we need to animate fully right motion (ie until reaching right side):
public void goRight() {
final JSplitPane splitPane = spat.getSplitPane();
final int currDivLoc = splitPane.getDividerLocation(),
maxDivLoc = splitPane.getMaximumDividerLocation();
if (CARD_LABELS.equals(currentCard) && currDivLoc < maxDivLoc) { //If the animation is stopped:
flip(); //Show the image label.
spat.play(maxDivLoc, speed, Math::min, ignore -> flip()); //Start the animation to the right.
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel leftPanel = new JPanel(new BorderLayout());
leftPanel.setBorder(BorderFactory.createLineBorder(Color.green));
int rows, cols;
rows = cols = 60;
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
final RightPanel rightPanel = new RightPanel(splitPane, 10, 3, rows, cols);
splitPane.setLeftComponent(leftPanel);
splitPane.setRightComponent(rightPanel);
JButton left = new JButton("Go left"),
right = new JButton("Go right");
left.addActionListener(e -> rightPanel.goLeft());
right.addActionListener(e -> rightPanel.goRight());
final JPanel buttons = new JPanel(new GridLayout(1, 0));
buttons.add(left);
buttons.add(right);
frame.add(splitPane, BorderLayout.CENTER);
frame.add(buttons, BorderLayout.PAGE_START);
frame.setSize(1000, 800);
frame.setMaximumSize(frame.getSize());
frame.setLocationByPlatform(true);
frame.setVisible(true);
splitPane.setDividerLocation(0.5);
});
}
}

Java - updating values in JFrame/JLabels

I am a beginner Java-coder and a few days ago I felt confident enough in my skills to start my first "big" project. It was basically a calculator, a GUI(only JFrame, JPanels, JLabels and Buttons) that would display data, accept user input, grab some more data from other classes, then calculate stuff and finally update the GUI with the new JLabel values. However I never managed to get the update part done properly, whenever I would press the 'process'-button it would create a new JFrame with the new values, while the old one was still up.
I tried the obvious stuff (repaint(), revalidate(), etc) but that didn't work at all, then I started to shift things around, put parts of the code into new classes, copied code from the net until it eventually worked. However the code was a total mess and I didn't even really understand what went exactly wrong in the first place, so I trashed the entire thing.
Here is a very simplified version of my code before things went downhill:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test_1 extends JFrame {
public static class clicks{
static int clicks = 0;
public int getclicks(){
return clicks;
}
public void setclicks(){
clicks = clicks+1;
}
}
public Test_1(){
clicks getNumber = new clicks();
int x = getNumber.getclicks();
//FRAME AND LAYOUT
JFrame window = new JFrame();
window.getContentPane().setBackground(Color.darkGray);
window.getContentPane().setLayout(new BorderLayout(20,10));
window.setTitle("Test Frame 1");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(true);
// Top JPanel
JPanel northpanel = new JPanel();
LayoutManager northlayout = new FlowLayout();
northpanel.setLayout(northlayout);
// Top JPanel content
JLabel nlabel1 = new JLabel("Hello North");
nlabel1.setPreferredSize(new Dimension(100,20));
northpanel.add(nlabel1);
JPanel westpanel = new JPanel();
LayoutManager westlayout = new BoxLayout(westpanel, BoxLayout.Y_AXIS);
westpanel.setLayout(westlayout);
JLabel wlabel1 = new JLabel("Hello West");
wlabel1.setPreferredSize(new Dimension(100,20));
westpanel.add(wlabel1);
JPanel eastpanel = new JPanel();
LayoutManager eastlayout = new BoxLayout(eastpanel, BoxLayout.Y_AXIS);
eastpanel.setLayout(eastlayout);
JLabel elabel1 = new JLabel ("Hello East");
elabel1.setPreferredSize(new Dimension(100,20));
eastpanel.add(elabel1);
JButton southbutton = new JButton("start");
southbutton.setPreferredSize(new Dimension(400,50));
southbutton.addActionListener(new Action());
JPanel centralpanel = new JPanel();
JLabel clabel1 = new JLabel("Clicks: " + x);
centralpanel.add(clabel1);
window.add(centralpanel, BorderLayout.CENTER);
window.add(southbutton, BorderLayout.SOUTH);
window.add(eastpanel, BorderLayout.EAST);
window.add(westpanel, BorderLayout.WEST);
window.add(northpanel, BorderLayout.NORTH);
window.pack();
window.setVisible(true);
}
public static void main(String[] args) {
Test_1 window_start = new Test_1();
}
static class Action implements ActionListener{
#Override
public void actionPerformed (ActionEvent e){
clicks Numbers = new clicks();
Numbers.setclicks();
int test = Numbers.getclicks();
System.out.println("Button works, Number of clicks: "+test);
Test_1 updateData = new Test_1();
}
}
}
I know that the ActionListener creates a new instance of my JFrame, however that was the closest I ever came to "updating the JFrame" before I turned the code into Spaghetti. I assume that the way I build my code is the cause of my problem but creating the Frame and its content it different classes didn't work at all.
So my questions are:
Is there something really obvious I missing? Would it be possible to make this run the way I want to without completely changing it?
Is there a more efficient way to create a GUI? I get the feeling that the way I made this is total garbage.
I read other questions that dealt with similar problems but maybe it's because I am still pretty bad at Java but I couldn't really tell if they were related to my problem. Also I really want to understand this, so copying someone elses code wouldn't help at all.
Any help or comments are appreciated.
btw, the class click is something I just put there as a placeholder.
Alrighty I managed to get it to work. It's probably against the Etiquette to answer to his own question but I thought it might be useful for some beginners(like me yesterday). So here is my new code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test_1 extends JFrame {
public static class clicks{
static int clicks = 0;
public int getclicks(){
return clicks;
}
public void setclicks(){
clicks = clicks+1;
}
}
clicks getNumber = new clicks();
int x = getNumber.getclicks();
JPanel northpanel, westpanel, eastpanel, southpanel, centralpanel;
static JLabel nlabel1, nlabel2, nlabel3, nlabel4, nlabel5;
static JLabel wlabel1, wlabel2, wlabel3, wlabel4, wlabel5;
static JLabel elabel1, elabel2, elabel3, elabel4, elabel5;
static JLabel clabel1;
JButton southbutton;
String TextnL, TextwL, TexteL;
public Test_1(){
setBackground(Color.darkGray);
setLayout(new BorderLayout(20,10));
setTitle("Test Frame 1");
setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(true);
setLocationRelativeTo(null);
setVisible(true);
nlabel1 = new JLabel("North_1");
nlabel2 = new JLabel("North_2");
nlabel3 = new JLabel("North_3");
nlabel4 = new JLabel("North_4");
nlabel5 = new JLabel("North_5");
wlabel1 = new JLabel("West_1 ");
wlabel2 = new JLabel("West_2 ");
wlabel3 = new JLabel("West_3 ");
wlabel4 = new JLabel("West_4 ");
wlabel5 = new JLabel("West_5 ");
elabel1 = new JLabel("East_1");
elabel2 = new JLabel("East_2");
elabel3 = new JLabel("East_3");
elabel4 = new JLabel("East_4");
elabel5 = new JLabel("East_5");
clabel1 = new JLabel("START");
southbutton = new JButton("Process");
southbutton.addActionListener(new Action());
northpanel = new JPanel();
northpanel.add(nlabel1);
northpanel.add(nlabel2);
northpanel.add(nlabel3);
northpanel.add(nlabel4);
northpanel.add(nlabel5);
add(northpanel, BorderLayout.NORTH);
westpanel = new JPanel();
LayoutManager wBox = new BoxLayout(westpanel, BoxLayout.Y_AXIS);
westpanel.setLayout(wBox);
westpanel.add(wlabel1);
westpanel.add(wlabel2);
westpanel.add(wlabel3);
westpanel.add(wlabel4);
westpanel.add(wlabel5);
add(westpanel, BorderLayout.WEST);
eastpanel = new JPanel();
LayoutManager eBox = new BoxLayout(eastpanel, BoxLayout.Y_AXIS);
eastpanel.setLayout(eBox);
eastpanel.add(elabel1);
eastpanel.add(elabel2);
eastpanel.add(elabel3);
eastpanel.add(elabel4);
eastpanel.add(elabel5);
add(eastpanel, BorderLayout.EAST);
centralpanel = new JPanel();
centralpanel.add(clabel1);
add(centralpanel, BorderLayout.CENTER);
add(southbutton, BorderLayout.SOUTH);
}
public static void main(String[] args) {
Test_1 window_start = new Test_1();
}
static class Action implements ActionListener{
#Override
public void actionPerformed (ActionEvent e){
clicks Numbers = new clicks();
Numbers.setclicks();
int test = Numbers.getclicks();
clabel1.setText("clicks: "+test);
}
}
}
And again, any comments/suggestions are welcome.

How can I put textfield and graphics in the same jframe?

I am trying to have a textfield and graphics in the same jframe but it is not working properly. I want to have the textfield in the bottom and the rest of the jframe for the graphics instead when I run it the textfield acts weirdly and covers up the entire area. Does anybody know how I can get it to work how I want it?
package pack;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class gui extends JPanel implements Runnable{
Thread t = new Thread(this);
protected JTextField textField;
private final static String newline = "\n";
public int x;
public int y;
public static void main(String args[])
{
new gui();
new input();
}
public void input()
{
textField = new JTextField(20);
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridwidth = 500;
c.gridheight = 100;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
}
public void actionPerformed(ActionEvent evt) {
String text = textField.getText();
textField.selectAll();
}
public gui()
{
textField = new JTextField(20);
JFrame f = new JFrame("lol");
System.out.println("::");
f.setTitle("Basic window");
f.setSize(500, 500);
f.setLocationRelativeTo(null);
f.add(this);
f.setVisible(true);
f.setFocusable(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(textField);
run();
}
public void run()
{
while(true)
{
try
{
t.sleep(10);
}
catch(Exception e){}
System.out.println(":D");
x++;
y++;
repaint();
}
}
public void paint (Graphics g)
{
g.setColor(Color.red);
}
}
Delete this class and start fresh with a new class. The structure of the code is wrong , the class names are wrong, the custom painting is wrong, the use of Threads is wrong, the new input() doesn't do anything, you should not be using Thread.sleep(), you should not override paint(), you should not add a component to the frame after the frame is visible.
Start by reading the section from the Swing tutorial on Custom Painting. There you will find a working example that will show you how to better structure you class when doing custom painting. Use this demo code as the starting point for your program and make changes (one at a time) to this working code.
Then you can change that code and add a JTextField to the frame. You will also need to read the Swing tutorial on Using Layout Managers, to understand how a BorderLayout works. So start with something simple that works and then add extra components. Don't try to do it all at one time.
Things that you are doing in wrong way.
JFrame by default has uses BorderLayout and you are adding two components in the center hence only last components are visible.
You are adding JTextField inside JFrame as well as JPanel. Don't know why?
Use BorderLayout.SOUTH to add the JTextField in the south and don't add it into JPanel as shown below:
public gui() {
...
textField = new JTextField(20);
JFrame f = new JFrame("lol");
f.add(this);
f.add(textField, BorderLayout.SOUTH);
...
}
Please read below post once again.
How to Use GridLayout
How to Use GridBagLayout

change jlabel with method

I am writing a small program that converts files, and I wanted to have a box pop up that asks the user to please wait while the program loops through and converts all the relevant files, but I am running into a small problem. The box that pops up should have a JLabel and a JButton, while the user is "waiting" I wanted to display a message that says please wait, and a disabled "OK" JButton, and then when its finished I wanted to set the text of the JLabel to let them know that It successfully converted their files, and give them a count of how many files were converted. (I wrote a method called alert that sets the text of the label and enables the button.) The problem is That while the program is running, the box is empty, the Label and the Button are not visible, when it finishes, label appears with the final text that I want and the button appears enabled. I am not sure exactly what is going on, I tried changing the modifiers of the JLabel and JButton several times but I cant seem to get it to work correctly. Here is the code for the box that pops up, any help is greatly appricated.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class PleaseWait extends javax.swing.JFrame{
private static final int height = 125;
private static final int width = 350;
final static JLabel converting = new JLabel("Please Wait while I convert your files");
private static JButton OK = new JButton("OK");
public PleaseWait(){
// creates the main window //
JFrame mainWindow = new JFrame();
mainWindow.setTitle("Chill For A Sec");
mainWindow.setSize(width, height);
mainWindow.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
// creates the layouts//
JPanel mainLayout = new JPanel(new BorderLayout());
JPanel textLayout = new JPanel(new FlowLayout());
JPanel buttonLayout = new JPanel(new FlowLayout());
// Sets Text //
converting.setText("Please wait while I convert your files");
// disables button //
OK.setEnabled(false);
// adds to the layouts //
textLayout.add(converting);
buttonLayout.add(OK);
mainLayout.add(textLayout, BorderLayout.CENTER);
mainLayout.add(buttonLayout, BorderLayout.SOUTH);
// adds to the frame //
mainWindow.add(mainLayout);
// sets everything visible //
mainWindow.setVisible(true);
}
public static void alert(){
OK.setEnabled(true);
String total = String.valueOf(Convert.result());
converting.setText("Sucsess! " + total + " files Converted");
}
}
Okay here's the issue. You are extending the JFrame . That means your class IS a JFrame.
When you create the PleaseWait frame you don't do anything to it. This is the empty box you are seeing. You are instead creating a different JFrame in your constructor. Remove your mainWindow and instead just use this. Now all of your components will be added to your PleaseWait object. That should fix your blank box issue.
You need an application to create your frame first. This is a simple example of such application.
import javax.swing.UIManager;
import java.awt.*;
public class Application {
boolean packFrame = false;
//Construct the application
public Application() {
PleaseWait frame = new PleaseWait();
//Validate frames that have preset sizes
//Pack frames that have useful preferred size info, e.g. from their layout
if (packFrame) {
frame.pack();
}
else {
frame.validate();
}
//Center the window
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
frame.convert();
}
//Main method
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {
e.printStackTrace();
}
new Application();
}
}
You have to slightly modify your frame to add controls to the content pane. You can do some work after frame is created, then call alert.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class PleaseWait extends JFrame {
private static final int height = 125;
private static final int width = 350;
final static JLabel converting = new JLabel();
private static JButton OK = new JButton("OK");
BorderLayout borderLayout1 = new BorderLayout();
JPanel contentPane;
int count;
public PleaseWait(){
contentPane = (JPanel)this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(width, height));
this.setTitle("Chill For A Sec");
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
// creates the layouts//
JPanel mainLayout = new JPanel(new BorderLayout());
JPanel textLayout = new JPanel(new FlowLayout());
JPanel buttonLayout = new JPanel(new FlowLayout());
// Sets Text //
converting.setText("Please wait while I convert your files");
// disables button //
OK.setEnabled(false);
OK.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
// adds to the layouts //
textLayout.add(converting);
buttonLayout.add(OK);
mainLayout.add(textLayout, BorderLayout.CENTER);
mainLayout.add(buttonLayout, BorderLayout.SOUTH);
// adds to the frame //
contentPane.add(mainLayout);
}
public void convert(){
count = 0;
for (int i = 0; i <10; i++){
System.out.println("Copy "+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
count++;
}
alert();
}
public void alert(){
OK.setEnabled(true);
// String total = String.valueOf(Convert.result());
converting.setText("Sucsess! " + count + " files Converted");
}
}

Custom JLabel Cleanup

I need to clean my labelResult each time on textField Action, but on the first time it adds 'null' in front of string and then - prints new string right after. Please help.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Frame extends JFrame implements ActionListener {
boolean isDirect = true;
String[] typeStr = {"direct", "invert"};
JLabel labelTip = new JLabel("Choose 'direct' OR 'invert' to print your next line in direct order or inverted respectively.");
JTextField textField = new JTextField("Some text!", 40);
JComboBox comboBox = new JComboBox(typeStr);
EventProcessing eventProcessing = new EventProcessing();
JLabel labelResult = new JLabel();
public Frame() {
setLayout(new BorderLayout());
getContentPane().add(labelTip, BorderLayout.PAGE_START);
getContentPane().add(comboBox, BorderLayout.CENTER);
getContentPane().add(textField, BorderLayout.AFTER_LINE_ENDS);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textField.addActionListener(this);
pack();
}
public void actionPerformed(ActionEvent e) {
getContentPane().remove(labelResult);
labelResult = new JLabel();
labelResult.setText("");
if (!(comboBox.getSelectedItem()).equals("direct")) {
isDirect = false;
}
else {
isDirect = true;
}
labelResult.setText(eventProcessing.action(isDirect, textField.getText()));
getContentPane().add(labelResult, BorderLayout.PAGE_END);
pack();
}
}
#Tim I know that in official tutorial about JComboBox is used ActionListener, but for any of actions from JComboBox to the GUI is better look for ItemListener, there you are two states (always be called twice, but you can filtering between thes two options SELECTED / DESELECTED by wraping to the if ... else)
and your code should be only
Runnable doRun = new Runnable() {
#Override
public void run() {
labelResult.setText(eventProcessing.action(isDirect, textField.getText()));
add(labelResult, BorderLayout.PAGE_END);
//1) this.pack(); if you want to re-layout with effect to size of JFrame too
//2a revalidate();
//2b plus in most cases
//2b repaint(); relayout Container with fitting JComponents inside Container,
//2b but without resize of JFrame
}
};
SwingUtilities.invokeLater(doRun);
Without the code to EventProcessing.action() it's hard to determine, but I would guess you attempt to concatenate two strings, the first of which is null. Null strings get converted to the literal string "null."

Categories

Resources