Stack GUI in java swing - java

I am creating a GUI of stack. Here is my code
private void StackActionPerformed(java.awt.event.ActionEvent evt) {
b1=new JButton("Push");
b2=new JButton("Pop");
b3=new JButton("Peek");
b4=new JButton("Clear");
b1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
pushButtonActionPerformed(evt);
}
});
tb.add(b1);
tb.add(b2);
tb.add(b3);
tb.add(b4);
frame_st.add(tb);
revalidate();
repaint();
frame_st.setSize(1022, 534);
drawstack();
}
public void drawstack()
{
m1.setBorder(BorderFactory.createRaisedSoftBevelBorder());
m1.setBackground(Color.white);
m1.setLayout(null);
JLabel l1=new JLabel("STACK");
l1.setBounds(500, 5, 100, 70);
m1.add(l1);
}
My code is compiling prefectly drawstack() is drawing the things which is required but as the drawstack() is called my buttons which are present in StackActionPerformed(java.awt.event.ActionEvent evt) i.e b1,b2,etc becomes invisible. I don't want this to happen . I want my buttons visible all the time. please help .
m1 is a panel which covers my entire frame.

I'm guessing you're putting m1 on top of your buttons (and frame_st). I'd put the buttons on m1 directly. Windows like this are Container objects. They have (sub)containers placed on them, with (sub)(sub)containers placed on them, etc.. You need to keep straight how all the containers at a particular level are laid out on their parent. If they overlay rather than abut, you have a problem.
I've found javax.swing.Box the most useful, and simplest, class for laying out windows, and I'd recommend it to you. Put one vertical Box on your whole window. Then make frame_st a horizontal Box, add it to the vertical one, and add your buttons just as you are doing. Then add m1, whatever it is, to the vertical Box also, and you should be good to go.
javax.swing.Box is not the solution to all the world's problems, but it should get you started. Once your buttons are showing, you can try other stuff.

Related

Why does my button disappear from my borderlayout when I add an actionListener to it?

I am writing the back end code for my java project which is implementing a fitness logger. For some reason when I put the actionListener function to a button in my Border Layout then the button disappears.
I tried setting the function in different places in the constructor.
public class Buttons extends JFrame implements ActionListener {
JFrame frame = new JFrame("Menu");
JPanel MyPanel= new JPanel();
JButton b1= new JButton("Daily Logger");
JButton b2= new JButton("View Weekly Logs");
JButton b3= new JButton("Weight Calculator");
JButton b4= new JButton("BMI Calculator");
JButton b5= new JButton("Log Out");
public Buttons(){
MyPanel.setLayout(new BorderLayout());
MyPanel.add(b1, "North");
MyPanel.add(b2, "Center");
MyPanel.add(b3, "East");
MyPanel.add(b4, "West");
MyPanel.add(b5, "South");
b1.addActionListener(this);
add(b1);
frame.getContentPane().add(MyPanel, "North");
frame.setSize(500,115);
frame.setVisible(true);
}
public static void main(String[] args) {
new Buttons();
}
#Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if(command.equals("Daily Logger"))
myMethod();
}
public void myMethod() {
JOptionPane.showMessageDialog(this,"Onto the next step");
}
}
I expected the button to show up in the border layout when I add the actionListener function but it disappears. If the button did work as it should it should implement the myMethod() function. My main goal is to show my JTable that I created in another class to show up when the button is pressed.
add(b1);
Should be removed. The code has already added it via:
MyPanel.add(b1, "North");
A BorderLayout accommodates up to five components, each in a separate layout constraint. If a component is added twice, in different areas, it faces two problems:
A component can only appear in one place.
The component 'overwrites' the original component added to that area of the layout.
More general tips:
Please learn common Java nomenclature (naming conventions - e.g. EachWordUpperCaseClass, firstWordLowerCaseMethod(), firstWordLowerCaseAttribute unless it is an UPPER_CASE_CONSTANT) and use it consistently.
For better help sooner, add a minimal reproducible example or Short, Self Contained, Correct Example. Note: The posted code only needed appropriate import statements to be an MRE / SSCCE.
MyPanel.add(b3, "East"); re East
There are constants for this. E.G. BorderLayout.EAST. always use the constants for compile time checking.
But BorderLayout.LINE_END is sensitive to the locale. It will appear on the RHS for left to right languages, and the left for right to left languages.
All Swing & AWT GUIs should be created & updated on the EDT (Event Dispatch Thread).
The code both extends and keeps a reference to, JFrame. Keep the latter, ditch the former.
Be sure to add the java (language) and swing (GUI toolkit) tags to questions! The only reason I saw this was because I (extraordinarily) checked the question listing for the jframe tag! To the best of my recollection, it's the first time I've ever checked that tag's question listing. Even more ironic, it did not make the list of 5 tags I saw as being most relevant to this question.
frame.getContentPane().add(.. can be shortened to frame.add(.. since Java 1.5.
frame.setSize(500,115); should better be frame.pack();, since 500 x 115 is no better than a guess, and will be 'wrong' for different OS' (the size of the content pane will change due to different frame decorations per system).

Refresh java program with Button

I am trying to make a refresh button that will essentially restart the program when ever I click the button. I don't know how I should go about doing this.
I've place the Graphical User Interface i decided to use do complete this action. Any and all help would be greatly appreciated.
package pdfView;
import javax.swing.*;
import java.awt.*;
public class View extends JFrame {
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
JButton ReFresh = new JButton("ReFresh");
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel(
"com.sun.java.squing.plaf.nimbus.NimbusLookAndFeel"
);
} catch (Exception exc){
}
}
public static void main(String[] args) {
View pdf = new View();
}
}
What do you mean by refresh or restart?
Do you mean:
Let the application be as it is, just update what it's showing?
Really restart the application?
Updating what the application is showing
You first need to decide what actually should cause your application to refresh. You already talked about a Button. The mechanism for activating something like a button is called Action. You can do that stuff manually, using an ActionListener, or you could extend AbstractAction, which is what I recommend. Extending AbstractAction allows you to use the same logical action something in more than one location on the UI. Look at typical applications, they offer Cut/Copy/Paste through menu, toolbar, popupmenu and keyboard shortcuts. The simplest way to achieve this in Java is using Action by extending AbstractAction.
The methods you need to call to update your application are invalidate(), validate() or repaint().
Restarting an application
So you want to run through main() again? That should actually not be required, unless you have an application that supports updating itself. Even then it can sometimes be avoided by smart usage of a ClassLoader.
Some more notes on your code
Usage by extension anti-pattern
I wouldn't extend JFrame just to display a window on the screen. Usage by extension is an anti-pattern. You don't need to extend JFrame to get a JFrame displayed on the screen and do what you want.
Referring static members
I would refer to constants via their original declaration. I.e. I'd refer to EXIT_ON_CLOSE via WindowConstants.EXIT_ON_CLOSE, not JFrame.EXIT_ON_CLOSE.
Typo
You have a typo in your UIManager.setLookAndFeel() code. Search for swing and you will see the typo.
Exception information
You might actually want to print the exception to stderr using exc.printStackTrace() instead of ignoring it completely, because when you have a typo in the LaF class name, as you do, and you don't print the exception, you might actually not come to know what's going wrong.
Sequence of widget construction and UIManager.setLookAndFeel()
The sequence of UIManager.setLookAndFeel() and the effective new JFrame() via super(...) does not guarantee you that the whole UI will be in Nimbus, parts of it might still be in Metal. I recommend to set the LaF before even constructing the first widget, to be on the safe side. As far as I remember, it's not guaranteed that changing the LaF after component construction has an effect, unless you tell the UIManager to update the LaF. See also this quote from the documentation of UIManager:
Once the look and feel has been changed it is imperative to invoke updateUI on all JComponents. The method SwingUtilities.updateComponentTreeUI(java.awt.Component) makes it easy to apply updateUI to a containment hierarchy. Refer to it for details. The exact behavior of not invoking updateUI after changing the look and feel is unspecified. It is very possible to receive unexpected exceptions, painting problems, or worse.
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
setSize() vs. pack() with a little help of Insets and Border
Instead of setting the size manually, you might want to play with Insets or Border and JFrame.pack() in order to get a decent layout of your window. Setting the size manually assumes that you know a lot about the screen resolution and the font size of the user.
The pack() method performs automatic size calculation based on the contents. Insets and Border allow you to create some space and borders, even with some designs or labels, around components so they wouldn't be cramped tightly in a window but be nicely spaced.
First you have to assign an actionListener to the ReFresh Jbutton.
You can either implement the interface ActionListener to the class, and override the actionPerformed() method like this
public class View extends JFrame implements ActionListener{
private JButton ReFresh;
public View() {
super("PDF Viewer");
setLookAndFeel();
setSize(500, 125);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FlowLayout flo = new FlowLayout();
setLayout(flo);
JTextField Search = new JTextField ("Search", 29);
JButton Search1 = new JButton("Search");
//this is where i have the button
ReFresh = new JButton("ReFresh");
ReFresh.addActionListener(this);
add(Search);
add(Search1);
add(ReFresh);
setVisible(true);
}
private void setLookAndFeel() { //right way for nimbus: http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/nimbus.html
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.equals(ReFresh))
{
super.repaint();
}
}}
public static void main(String[] args) {
View pdf = new View();
}
Or you can do inline assignment to addActionListener, like this
ReFresh.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
super.repaint();
}
});
You can try these methods to refresh/reload the JFrame,
invalidate();
validate();
repaint();
you can also use dispose(); and then new View(); to create the new JFrame, but in this sequence it will close the window and create new one.
or you can even try setVisible(false); then setVisible(true);
I recommend the first 3.

In JAVA, JButton, Button displayed only when cursor is on the button and works even on clicking anywhere in contentPane

I am a beginner into Java and OOPS in general. Am studyin Head First Java to start, and studying GUI and Swing concepts in it.
The below code is just for understanding purposes.
On running the code, The frame window is displayed with Button, and when I expand it I can see Radio Button too.
Issues-
Button works till the window size is not more than the button size . As soon as I increase the window size even slightly more than button's dimensions, then the button is displayed only when cursor is on it.
I am changing window size using mouse.
Also even if I set Frame size to be more than button. say frame.setSize(800,800); then the button covers whole contentPane. and still behaves same way on resizing.
And the button responds to clicking on mouse, irrespective of where I click in the contentPane. It should respond only when i click directly on the button.
Please inform me why it is behaving this way.
And if possible,corrections in code or additions to correct this.
import java.awt.Color;
import javax.swing.*;
import java.awt.event.*;
public class Test1 implements ActionListener {
JFrame frame = new JFrame("Frame");
JButton button = new JButton("Button!");
JRadioButton radio = new JRadioButton("VideoKilledTheRadioStar!",true);
int j=0;
public static void main(String[] args) {
Test1 t = new Test1();
t.method1();
}
public void method1()
{
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.setSize(100,100);
button.setBackground(Color.ORANGE);
frame.add(button);
frame.setSize(100,100);
frame.setVisible(true);
button.addActionListener(this);
frame.getContentPane().add(radio);
radio.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{j++;
button.setText("clicked .. " + j);
if(button.getBackground()==Color.ORANGE)
button.setBackground(Color.BLUE);
else
button.setBackground(Color.ORANGE);
}
}
P.S I did not know which segment of code is important or more relevant to this question, so I have put complete code.
You are trying to add the JButton button and JRadioButton objects in the default layout(BorderLayout) of the JFrame.
Whenevery you add a component to JFrame having BorderLayout the components goes in the Middle Section and BorderLayout center section has tendency to occupy the complete space, so to position elements properly you will need to specify the location as well as set the PreferredSize of the component.
frame.add(radio, BorderLayout.SOUTH);
component.setPreferredSize(Dimension);
You are adding the JButton button and the JRadioButton both in the BorderLayout.CENTER location so only one is being displayed. Components at this location will be sized in the X and Y axis.
The JButton only displays when the cursor is over it due to the fact that it has its own MouseListener used for painting.
Also, the statements
frame.add(myComponent);
and
frame.getContentPane().add(myComponent);
both add the component to the frame's ContentPane & are equivalent but the first is chosen for convenience.
Note that components cannot co-exist in the same position in a BorderLayout. You could place the button at the BorderLayout.SOUTH position (& add directly to the frame):
frame.add(radio, BorderLayout.SOUTH);
BorderLayout disregards any preferred sizes for components so you would have to use a different layout manager such as BoxLayout to maintain a fixed size JButton.
See more about Layout Managers

ActionEvent for jButton given a jRadioButton option

So basically, I'm trying to make a simple program here with GUI that let's you make a choice given two jRadioButtons as choices of which either of the two leads to a corresponding storyline in similar fashion to visual novels. The problem however is that I'm having trouble connecting the idea of a jButton to a choice from a jRadioButton.
The concept is like this: In a frame, there's a jTextArea which displays strings of texts forming a storyline which gives two options to choose from here and there as represented by two jRadioButtons which then must be executed by a jButton.
So far, the only logic I've placed inside the ActionListener for both jRadioButtons is having to disable the other once a jRadioButton is clicked while the jButton is intentionally blank. Anyone got any similar program or module he / she would like to share, at least, the logic on this one programatically speaking?
We usually use RadioButtons to choose between one of a few options and only one button can be selected at a time. To get this functionality, you need to add your buttons to a javax.swing.ButtonGroup . Here is a quick example:
//Fields declared in your main GUI class
JRadioButton option1,option2;
JButton goButton; //executes the "Story"
//Constructor code or place in init() method that constructor calls:
{
//initialize buttons and place them in your frame.
ButtonGroup buttonGroup = new javax.swing.ButtonGroup();
buttonGroup.add(option1);
buttonGroup.add(option2);
buttonGroup1.setSelected(option1.getModel(), true);
goButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
goButtonActionPerformed(evt);
}
});
}
private void goButtonActionPerformed(java.awt.event.ActionEvent evt) {
if(option1.isSelected()) {
//place text in your text area
}
if(option2.isSelected()) {
//place different text in your text area
}
}

Hide a button from Layout in Java Swing

I am trying something very basic:
I have a list of 5 buttons. They are in a FlowLayout and the general idea should be that once I click one it should disappear and the others should reorder themselves accordingly.
Now, if I call setVisible(false) the button becomes invisible, but it still occupies it's space in the Layoutmanager.
Is there any way to keep the Button in the JPanel while hiding it so it doesn't get picked up by Layout?
Update:: Thanks for all the answers, the problem with removing the buttons is that the order is important. The problem I was trying to solve was a find as you type szenario where a very long list of buttons gets filtered down to only the ones matching the characters entered so users can easily click them. Since users can delete characters from the search field ordering is important and buttons have to pop back in once they match again.
Works fine for me.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FlowLayoutInvisible extends JFrame
implements ActionListener
{
JPanel north;
int i;
public FlowLayoutInvisible()
{
north = new JPanel();
for (int i = 0; i < 5; i++)
{
JButton button = new JButton("North - " + i);
button.addActionListener(this);
north.add(button);
}
getContentPane().add(north, BorderLayout.NORTH);
}
public void actionPerformed(ActionEvent e)
{
Component c = (Component)e.getSource();
c.setVisible(false);
((JPanel)c.getParent()).revalidate();
}
public static void main(String[] args)
{
FlowLayoutInvisible frame = new FlowLayoutInvisible();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
If you need more help post your SSCCE.
Update: I don't know if the revalidate() is required. I seemed to have a problem once but now I can't duplicate the problem.
Just remove it:
panel.remove( button );
What's wrong with this option?
Layout managers are thought precisely to avoid having the "user" to make tricks in order to have each component it the right place ( although it seems to provoke the opposite effect )
Removing the button from the panel will have the effect of laying out again all the remaining components. That's why it's name is "Layout manager" it manages to layout the components for you.
I see two possibilities:
Write your own layout manager that listens for changes to its children's visible property - shouldn't be too hard, you can probably subclass FlowLayout to do it.
actually remove the clicked-button from the panel and, if necessary, re-add it later.
You could override each button's getPreferredSize() methods (and possibly getMinimumSize() as well to return 0,0 when the component is invisible; and you need to call, I think, invalidate() (or revalidate or validate, I can never keep them straight) on the container.

Categories