I am currently trying to code a GUI for an assignment as extra credit, as a learning opportunity. I need to have a menu of buttons, with each button effectively changing the main panel to enter or display data. Right now, I have a class called buttonContainer, which holds the main menu, and mainPanel, which holds the main panel for the entire GUI. Basically I need a way to have buttonContainer add and remove elements from its parent, mainPanel- with the two of them remaining seperate files.
My buttonContainer class looks like this:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class buttonPanel extends JPanel implements ActionListener
{
private JButton load, save, list, find, input, sort, exit;
private JPanel BtnContainer, parent;
private newContactPanel newContact;
public buttonPanel()
{
load = new JButton("Load Contacts");
save = new JButton("Save Contacts");
list = new JButton("List Contacts");
find = new JButton("Find Contact");
sort = new JButton("Sort Contacts");
input = new JButton("New Contact");
exit = new JButton("Exit Program");
newContact = new newContactPanel();
parent = this.getParent();
BtnContainer = new JPanel();
BtnContainer.setLayout(new GridLayout(0,1));
BtnContainer.add(load);
BtnContainer.add(save);
BtnContainer.add(list);
BtnContainer.add(sort);
BtnContainer.add(find);
BtnContainer.add(input);
BtnContainer.add(exit);
add(BtnContainer);
}
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == input)
{
//Change panel command here
}
}
}
With the mainPanel code looking like this:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class mainPanel extends JPanel //implements ActionListener
{
private buttonPanel MainMenu;
private newContactPanel newContact;
private JPanel wrapper;
public mainPanel()
{
wrapper = new JPanel();
this.setLayout(new BorderLayout());
wrapper.setLayout(new BorderLayout());
MainMenu = new buttonPanel();
newContact = new newContactPanel();
wrapper.add(MainMenu, BorderLayout.WEST);
add(wrapper, BorderLayout.WEST);
}
}
contactPanel is a different panel, that I want buttonPanel to trigger mainPanel to show. Is there any easy way of refrencing the parent class like this, while keeping the two classes separate?
I know variants of this question have been asked before, but, nothing I read here seemed to get done what I wanted. Several of them didn't really match exactly what I was looking for- most of them were from the same file. several used a getParent()- but if I try to use it, it only grabs a Container, and not a JPanel.
EDIT: Thanks to the people who answered. A couple of good ideas were presented- which helped me realize I forgot to actually add the action listener to the button. This question has been fully solved!
Basically I need a way to have buttonContainer add and remove elements from its parent, mainPanel- with the two of them remaining
seperate files.
You can use SwingUtilities.getAncestorOfClass(class, comp) from within your ButtonContainer class as you know it will be a child of that class. For example:
class ButtonContainer extends JPanel implements ActionListener {
...
#Override
public void actionPerformed(ActionEvent e) {
MainPanel mainPanel = (MainPanel)SwingUtilities.getAncestorOfClass(MainPanel.class, ButtonContainer.this);
if (mainPanel != null) {
// Change panel command here
}
}
}
Off-topic
Please read Java Code Conventions and stick to them. Class' names start with a capital letter; variables and methods names start with lower case.
you can make wrapper public static
public static JPanel wrapper;
then from buttonPanel you can use this code
mainPanel.wrapper.remove(<whatever component>);
mainPanel.wrapper.add(<whatever component>);
mainPanel.wrapper.validate();
mainPanel.wrapper.repaint();
i think this will work
Related
I have a JFrame which contains 3 JPanels (each in a separate class). The first JPanel contains two JTextFields in which I write the name of the file to be read from and the condition to be fulfilled respectively. This doesn't really affect my question, so let's move on.
The second JPanel has a JTextArea.
The third JPanel has two JButtons (Load, Sort) which are supposed to load a list of entries that suffice the condition from the first JPanel and then reorganize them according to some rules (respectively).
THE PROBLEM:
Ok so, the first class is the JFrame class in which i just do the standard look and feel of the window.
The second class is the first JPanel with two JTextFields.
I won't give code for this one because the second JPanel code is shorter and has the same problem so I imagine that the same solution would apply.
Third class contains the JTextArea in which I should display certain entries from the text-file.
Code:
public class SecondPanel extends JPanel {
JPanel panel;
JTextArea lista;
public SecondPanel() {
panel = new JPanel();
list = new JTextArea("List");
list.setPreferredSize(new Dimension(200, 150));
this.add(list);
}
}
Moving on, the fourth class contains the Jbuttons and the ActionListener(Button listener). Ok so here is the part of the code from the button listener class
CODE:
private class ButtonListener implements ActionListener {
SecondPanel secondPanel = new SecondPanel();
FirstPanel firstPanel = new FirstPanel();
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("Load")) {
//calls method that loads data from the text in a firstPanel field
loadData(firstPanel.theFile.getText());
for(int i = 0; i< students.length; i++) {
if(students[i]!=null) {
// doesn't write anything tried with .setText etc.
secondPanel.list.append(students[i]+"\n");
}
}
}
}
}
So the program won't get text when i type in the JTextField designated for the file path. And when i do it manually in the code, It won't write the changes to the list on the Window (JTextArea). But when i System.out.print to the console it prints the changes and lists entries correctly as well as any setText changes I make. It just won't write or read to and from the Window..
What should I do?
The problem is that you are calling your setText methods on the wrong objects.
In your listener class, you declared two new panels as class variables, and then you call your methods on them, but i think those panels are not the ones you really want to change.
You should first add your panels to your Jframe object, and refer to them on your ActionListener.
Here i provide you a minimal code which modifies a JTextArea when a JButton is pressed. (same for a JTextField)
import java.awt.*;
import javax.swing.*;
public class MyJFrame extends JFrame {
SecondPanel sPanel;
public MyJFrame() {
super("main");
Container c = getContentPane();
c.setLayout(new BorderLayout());
JButton button = new JButton("load");
button.addActionListener(new LoadListener());
c.add(sPanel = new SecondPanel(), BorderLayout.NORTH);
c.add(button, BorderLayout.SOUTH);
pack();
setVisible(true);
}
class SecondPanel extends JPanel {
public JTextArea list;
public SecondPanel() {
super();
list = new JTextArea("List");
list.setPreferredSize(new Dimension(200, 150));
add(list);
}
}
class LoadListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
sPanel.list.setText("new text for the jtext area");
}
}
public static void main(String[] args) {
new MyJFrame();
}
}
Very new to Java, but I am slowly picking my way through things. So please be kind. I understand most things I've tried so far, and built a version of the following that uses console output, but now I'm trying to make a GUI. I tried the netbeans GUI maker, but it created so much new code that when I tried to pick through it, I got lost. I'm much better at learning by piecing new things together myself, not having an IDE generate a ton of code and then attempt to find where I want to work.
I am trying to build an window that has a list with three choices on the left side, a button in the middle that confirms your choice, and an answer output on the right. Once the button is pressed, the input from the list is read and is converted into a corresponding answer. As of right now, all I get is "We recommend... null" after selecting an option in the list. The button appears to do nothing at the moment.
I have used tutorials, hacked up others' code from online, and referenced a few books, but I'm stuck.
Here is what I have:
package diffguidegui;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class DiffGuideGUI extends JPanel implements ListSelectionListener {
private JList resultsTabList;
private DefaultListModel listModel;
private static final String recommendString = "Recommend a Option";
private JButton recommendButton;
private String recommendOutput;
final JLabel output = new JLabel("We recommend..." + recommendOutput);
//build list
public DiffGuideGUI () {
super(new BorderLayout());
listModel = new DefaultListModel();
listModel.addElement("A");
listModel.addElement("B");
//create the list and put it in the scroll pane
resultsTabList = new JList(listModel);
resultsTabList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
resultsTabList.setSelectedIndex(0);
//listener for user input
resultsTabList.addListSelectionListener(this);
resultsTabList.setVisibleRowCount(2);
JScrollPane listScrollPane = new JScrollPane(resultsTabList);
//build the button at the bottom to fire overall behavior
recommendButton = new JButton(recommendString);
recommendButton.setActionCommand(recommendString);
recommendButton.addActionListener(new RecommendListener());
//create a panel that uses Boxlayout for the button
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.add(recommendButton);
//create a panel that uses Boxlayout for the label
JPanel outputPane = new JPanel();
outputPane.setLayout(new BoxLayout(outputPane, BoxLayout.LINE_AXIS));
outputPane.add(output);
add(listScrollPane, BorderLayout.WEST);
add(buttonPane, BorderLayout.CENTER);
add(outputPane, BorderLayout.EAST);
}
//build listener class
class RecommendListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//build in logic for choice made here
String resultsTabChoice;
resultsTabChoice = (String)resultsTabList.getSelectedValue();
if( resultsTabChoice.equals("A")) {
recommendOutput = "One";}
else {recommendOutput = "Two";}
}
}
public void valueChanged(ListSelectionEvent e) {
if(e.getValueIsAdjusting() == false) {
if(resultsTabList.getSelectedIndex() == -1) {
recommendButton.setEnabled(false);
} else {
recommendButton.setEnabled(true);
}
}
}
//Create GUI and show it
private static void createAndShowGUI() {
JFrame frame = new JFrame("Recommend Window");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create and set up content pane
JComponent newContentPane = new DiffGuideGUI();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
//display the window
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
The button appears to do nothing at the moment.
It does something. It calculates the value for your recommendOutput varable. But you never output this value.
try the following:
//build listener class
class RecommendListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//build in logic for choice made here
String resultsTabChoice;
resultsTabChoice = (String)resultsTabList.getSelectedValue();
if( resultsTabChoice.equals("A")) {
recommendOutput = "One";}
else {recommendOutput = "Two";}
System.out.println(recommendOutput); // <-###################
}
}
This should print the value to stdout
To put the value into your label try this instead:
output.setText(recommendOutput);
where do you set the text for the JLabel? It says "We recommend NULL" because recommenedOutput is null when the object is created. I dont see
output.setText("We recommend "+value) anywhere. You probably need output.invalidate() also. Try putting setText(String text)/invalidate() in the RecommendListener.actionPerformed() method.
output.setText("We recommend A");
output.invalidate();
I am writing a program which :
Creates a JPanel that contains some Shape objects which can be MouseDragged around.
Saves an object of this class in a binary file with an ObjectOutputStream
Retrieves the objects from the binary file (with an ObjectInputStream) and adds it in a JFrame.
My problem is that after my JPanel is retrieved (and therefore deserialized, I take it) and added to my JFrame, I cannot MouseDrag my shapes anymore. No clickable actions work actually.
My teacher told me that I could fix this by using the validate() method, although I am not quite sure as to how to do it.
The reason you don't see a change, is that the listeners of the class (even if serialized, which might be the case) do no have references to the objects they're supposed to be in contact with on the other side. Moreover, they are not being re-attached to the components that they were attached to before serialization.
As an example, the following example wouldn't work with serialization, since the listener does something to 'panel', but there's no way the listener can be "re-attached" to the button after deserialization, as well as be aware of 'who' panel is:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MyPanel extends JPanel {
private JPanel innerPanel;
private JLabel label;
private JButton button;
public MyPanel() {
super(new BorderLayout(10, 10));
innerPanel = new JPanel(new BorderLayout());
innerPanel.add(label = new JLabel("PANEL"), BorderLayout.CENTER);
button = new JButton("Remove label");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.remove(label);
}
});
add(innerPanel, BorderLayout.CENTER);
add(button, BorderLayout.PAGE_END);
}
}
I'm a beginner at java and want to make a JFrame with tabs containing a seperate JPanel. One panel has a list where it displays things that you select in a different panel, so I want this panel to always display a list of stuff that you have selected in a different panel (I hope that makes sense). To do this, I need to make a method to refresh the JList. This is the Farthest that I've gotten on that:
public class PanelClass extends JPanel {
private JList list;
private DefaultListModel listModel = new DefaultListModel();
private ArrayList<SomeOtherClass> objectArray = new ArrayList<SomeOtherClass>();
public PanelClass() {
list.setModel(listModel);
}
public void refresh() {
updateListModel();
list.setModel(listModel);
}
public void updateListModel() {
if (objectArray.isEmpty()) {
System.out.println("No Objects In Array!");
} else {
listModel.clear();
for (SomeOtherClass SOC : objectArray) {
// SOC.getName() just returns a string
listModel.addElement(SOC.getName());
}
}
}
public void addObjectToArray(SomeOtherClass SOC) {
objectArray.add(SOC);
}
}
Could someone please tell me how to make a "refresh" method to constantly keep the JList up to date?
The AWT/Swing event model is based upon the widgets being event sources (in the MVC paradigm, they are both view and controller). Different widgets source different event types.
Look at the java.awt.event (primarily), and javax.swing.event packages for the listener interfaces you'll need to implement and register in order to produce your desired effect.
Basically, you write a Listener implementation, and register it with Widget1. When Widget1 detects an event, it will notify you, and you can then use the information it provides to update Widget2.
For instance, if a button being clicked would add an object to your list, you might have something like below (I usually put this code in the encompassing JFrame class, and make it implement the listener interfaces; but you can choose to use inner classes or separate listener classes):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MyFrame extends JFrame implements ActionListener {
private JButton button = new JButton("Click me!");
private DefaultListModel<String> listModel = new DefaultListModel<String>();
private JList<String> list = new JList<String>(listModel);
private int counter = 1;
public MyFrame() {
setTitle("Test Updates");
JTabbedPane tabs = new JTabbedPane();
add(tabs, BorderLayout.CENTER);
JPanel panel = new JPanel();
panel.add(list);
tabs.add("Selections", panel);
panel = new JPanel();
button.addActionListener(this);
panel.add(button);
tabs.add("Options", panel);
pack();
}
#Override
public void actionPerformed(final ActionEvent event) {
if (button.equals(event.getSource())) {
listModel.addElement("Item " + counter++);
}
}
/* Test it! */
public static void main(String[] args) {
final MyFrame frame = new MyFrame();
frame.addWindowListener(new WindowAdapter() {
#Override public void windowClosing(final WindowEvent e) {
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
});
frame.setVisible(true);
}
}
This code sample is minimal, but it should give you an idea of how to go about implementing what you want.
You can do it in two way. First : Write it in infinite thread loop so that it will constantly update JList. Second : You can call refresh() method whenever new SOC objects are added in your ArrayList. It means you can call refresh() method from addObjectToArray() method which ultimately call the refresh method only when you have some change in your ArrayList.
FYI : I did it in my project and I went for second option.
I am really new to GUI programming in Java, I did a lot of research and I couldn't find an answer to this problem.
I have a simple JFrame with a menu, and inside this JFrame I have a JPanel with a log in form (were users input their username and password), and then I want to change that JPanel to another JPanel depending on what users want to do.
What would be the best way of doing this? I think that stacking JPanels is OK. But after I add new JLayeredPanels in Netbeans they don't stack. I read somewhere that I should use Z ordering or something like that, but I can't find it on the designer view.
Well, thank you very much for your patience!
CardLayout class has a useful API that can serve your requirements. Using methods like next(), first(), last() can be helpful.
I've prepared a simple demonstration of changing panels within a parent panel and/or frame.
Take a look at it:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PanelChanger implements ActionListener
{
JPanel panels;
public void init(Container pane)
{
JButton switcher = new JButton("Switch Active Panel!");
switcher.addActionListener(this);
JPanel login = new JPanel();
login.setBackground(Color.CYAN);
login.add(new JLabel("Welcome to login panel."));
JPanel another = new JPanel();
another.setBackground(Color.GREEN);
another.add(new JLabel("Yeah, this is another panel."));
panels = new JPanel(new CardLayout());
panels.add(login);
panels.add(another);
pane.add(switcher, BorderLayout.PAGE_START);
pane.add(panels, BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent evt)
{
CardLayout layout = (CardLayout)(panels.getLayout());
layout.next(panels);
}
public static void main(String[] args)
{
JFrame frame = new JFrame("CardLayoutDemo");
PanelChanger changer = new PanelChanger();
changer.init(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
}